- <fieldset><legend>用户状态</legend><form action="<%= Request.RawUrl %>" method="post">
- <% if( Request.IsAuthenticated ) { %>
- 当前用户已登录,登录名:<%= Context.User.Identity.Name.HtmlEncode() %> <br />
- <% var user = Context.User as MyFormsPrincipal<UserInfo>; %>
- <% if( user != null ) { %>
- <%= user.UserData.ToString().HtmlEncode() %>
- <% } %>
- <input type="submit" name="Logon" value="退出" />
- <% } else { %>
- <b>当前用户还未登录。</b>
- <% } %>
- </form></fieldset>
为了能让上面的页面代码发挥工作,必须在页面显示前重新设置HttpContext.User对象。
为此,我在Global.asax中添加了一个事件处理器:
- protected void Application_AuthenticateRequest(object sender, EventArgs e)
- {
- HttpApplication app = (HttpApplication)sender;
- MyFormsPrincipal<UserInfo>.TrySetUserInfo(app.Context);
- }
TrySetUserInfo的实现代码:
- /// <summary>
- /// 根据HttpContext对象设置用户标识对象
- /// </summary>
- /// <param name="context"></param>
- public static void TrySetUserInfo(HttpContext context)
- {
- if( context == null )
- throw new ArgumentNullException("context");
- // 1. 读登录Cookie
- HttpCookie cookie = context.Request.Cookies[FormsAuthentication.FormsCookieName];
- if( cookie == null || string.IsNullOrEmpty(cookie.Value) )
- return;
- try {
- TUserData userData = null;
- // 2. 解密Cookie值,获取FormsAuthenticationTicket对象
- FormsAuthenticationTicket ticket = FormsAuthentication.Decrypt(cookie.Value);
- if( ticket != null && string.IsNullOrEmpty(ticket.UserData) == false )
- // 3. 还原用户数据
- userData = (new JavaScriptSerializer()).Deserialize<TUserData>(ticket.UserData);
- if( ticket != null && userData != null )
- // 4. 构造我们的MyFormsPrincipal实例,重新给context.User赋值。
- context.User = new MyFormsPrincipal<TUserData>(ticket, userData);
- }
- catch { /* 有异常也不要抛出,防止攻击者试探。 */ }
- }
在多台服务器之间使用Forms身份认证
默