表单验证(Forms验证)是一个基于票据(ticket-based)[也称为基于令牌(token-based)]的系统。这意味着当用户登录系统以后,他们得到一个包含基于用户信息的票据(ticket)。这些信息被存放在加密过的cookie里面,这些cookie和响应绑定在一起,因此每一次后续请求都会被自动提交到服务器。

当用户请求匿名用户无法访问的ASP.NET页面时,ASP.NET运行时验证这个表单验证票据是否有效。如果无效,ASP.NET自动将用户转到登录页面。这时就该由你来操作了。你必须创建这个登录页面并且验证由登录页面提交的凭证。如果用户验证成功,你只需要告诉ASP.NET架构验证成功(通过调用FormsAuthentication类的一个方法),运行库会自动设置验证cookie(实际上包含了票据)并将用户转到原先请求的页面。通过这个请求,运行库检测到验证cookie中包含一个有效票据,然后赋给用户对这个页面的访问权限。

下面,就是具体的实现。我们先写一个生成用户票据的方法:

//生成Token并保存到Cookies中
private void CreateToken(Models.User user)
{
    string json = JsonConvert.SerializeObject(user);
    FormsAuthentication.SetAuthCookie(user.UserName.Trim(), true, FormsAuthentication.FormsCookiePath);
    FormsAuthenticationTicket Ticket = new FormsAuthenticationTicket(1, user.UserName, DateTime.Now, DateTime.Now.AddHours(12), false, json);
    Biz126.Cache.SetCookies.AddCookie(FormsAuthentication.FormsCookieName, FormsAuthentication.Encrypt(Ticket));
}

其中Biz126.Cache.SetCookies.AddCookie是我自己封装的保存Cookie方法。
生成Token并保存到Cookie中的方法我们已经写好了,只要在登录成功之后直接调用这个方法就可以了。

下面是验证票据,验证票据,我们放在过滤器中进行验证。
新建AuthenticationAttribute类,继承ActionFilterAttribute,重写OnActionExecuting方法:

        /// <summary>
        /// 检查用户是否有该Action执行的操作权限
        /// </summary>
        /// <param name="actionContext"></param>
        public override void OnActionExecuting(HttpActionContext filterContext)
        {
            Models.ResultModel<object> result = new Models.ResultModel<object>();
            result.code = -401;
            result.message = "请登录后进行操作";
            result.status = false;
            //如果存在身份信息
            if (!HttpContext.Current.User.Identity.IsAuthenticated)
            {
                filterContext.Response = filterContext.Request.CreateResponse(HttpStatusCode.Unauthorized, result, "application/json");
            }
            else
            {                
                
                BLL.IManager manager = new BLL.Manage.Manager();
                result = manager.Detail();    //取当前登录的用户信息,进行其他的操作,比如判断有没有权限等,这里省略
                //。。。省略掉其他的操作
                
                if (!result.status)
                {
                    filterContext.Response = filterContext.Request.CreateResponse(HttpStatusCode.Unauthorized, result, "application/json");
                    //filterContext.Result = redirect;
                }
            }
        }

之后,在要在需要用户登录的Action上面,加上[Authentication]就可以了,也可以新加一个控制器,如BaseWebApiController,在这个控制器上加上[Authentication],其他的控制器都继承BaseWebApiController,在不需要验证的Action上加上[AllowAnonymous]就可以了。
下面是通过票据取得用户信息:

            if (HttpContext.Current.Request.IsAuthenticated)//是否通过身份验证
            {
                HttpCookie authCookie = HttpContext.Current.Request.Cookies[FormsAuthentication.FormsCookieName];//获取cookie
                FormsAuthenticationTicket Ticket = FormsAuthentication.Decrypt(authCookie.Value);//解密
                string json = Ticket.UserData;//反序列化
                Models.Models.User user = new Models.User();
                try
                {
                    user = JsonConvert.DeserializeObject<Models.User>(json);
                    result.data = user;
                    result.message = "success";
                    result.status = true;
                }
                catch
                {

                }

            }

还需要在web.config中增加配置:

  <system.web>
    <authentication mode="Forms">
      <forms loginUrl="~/Users/Login" timeout="2880" />
    </authentication>
  </system.web>

到这里,其本上都已经完成了,但是你会发现,在IE上,会有很多用户登录的时候验证不通过的情况,如果记录日志,会发现HttpContext.Current.Request.IsAuthenticated==false
HttpContext.Current.Request.User为空
而且这种情况只有在IE下才会出现,其他的现代浏览器比如Chrome、Firefox等都很正常。
通过网络搜索,大部分都没给出答案来。其他把配置按下面的方法修改,就可以解决这个问题:

  <system.web>
    <authentication mode="Forms">
      <forms cookieless="UseCookies" loginUrl="~/Users/Login" timeout="2880" />
    </authentication>
    <authorization>
      <allow users="*" />
    </authorization>
  </system.web>

或者是打开服务器的IIS,按下面的步骤修改:
IIS的“身份证验证”
1.打开IIS,选择自己的站点,之后双击IIS中的“身份验证”功能
设置Forms身份验证
2.选中Forms身份验证,点击右侧操作区的“编辑”菜单,如果没有启用请先点击“启用”
Forms身份验证的默认设置
3.这是Forms身份验证的默认设置,我们需要改动一下
修改之后的Forms身份验证设置
4.按这里修改一下,就可以了。

以上。