在ASP.NET MVC项目里,Forms身份验证是一种基于Cookie的轻量认证方案。它不依赖外部服务,适合内部系统或中小型网站。其核心思路是:用户提交账号密码,服务端校验通过后,把身份信息加密成一个票据(ticket),写入浏览器Cookie;后续请求携带该Cookie,框架自动解密并构建用户主体,再结合授权过滤器控制访问。

一、基础配置与Web.config设置
使用Forms身份验证的第一步是在Web.config中启用认证模式,并定义登录页与Cookie名称。很多项目直接保留默认配置,但在多服务器部署时,必须显式设置machineKey,否则一台机器签发的票据在另一台无法解密。
下面是一段典型的配置代码。其中loginUrl指向登录视图,timeout控制Cookie有效期,slidingExpiration表示滑动过期。protection设为All代表同时加密和验证签名,防止篡改。
<system.web>
<authentication mode="Forms">
<forms loginUrl="~/Account/Login"
timeout="30"
slidingExpiration="true"
name=".ASPXAUTH"
protection="All" />
</authentication>
<authorization>
<deny users="?" />
</authorization>
<machineKey validationKey="AutoGenerate"
decryptionKey="AutoGenerate"
validation="SHA1" />
</system.web>
二、登录动作与票据签发实例
在AccountController中,我们编写一个Login动作。它接收视图模型,调用业务层校验密码,成功后使用FormsAuthentication.SetAuthCookie或Ticket手动签发。简单场景用SetAuthCookie即可,但如需携带角色或自定义数据,应构造FormsAuthenticationTicket。
以下示例演示手动创建票据并写入Cookie,这样可以把用户ID存进UserData,方便后续读取。注意Cookie的HttpOnly应设为true,降低XSS风险;Secure可按站点是否HTTPS来决定。
public ActionResult Login(LoginViewModel model)
{
if (!ModelState.IsValid)
return View(model);
// 假设校验通过
if (!Membership.ValidateUser(model.UserName, model.Password))
{
ModelState.AddModelError("", "用户名或密码错误");
return View(model);
}
var ticket = new FormsAuthenticationTicket(
version: 1,
name: model.UserName,
issueDate: DateTime.Now,
expiration: DateTime.Now.AddMinutes(30),
isPersistent: model.RememberMe,
userData: "user_id=1001",
cookiePath: FormsAuthentication.FormsCookiePath
);
string encTicket = FormsAuthentication.Encrypt(ticket);
var cookie = new HttpCookie(FormsAuthentication.FormsCookieName, encTicket);
cookie.HttpOnly = true;
if (model.RememberMe)
cookie.Expires = ticket.Expiration;
Response.Cookies.Add(cookie);
return RedirectToAction("Index", "Home");
}
三、授权控制与获取身份信息
控制器或动作上添加[Authorize]特性,即可限制匿名访问。框架在管道中解密Cookie,把票据转为GenericPrincipal附加到HttpContext.User。我们在业务代码里通过User.Identity.Name拿到登录名,通过解密UserData获取附加信息。
下面的帮助方法展示如何从当前请求还原自定义数据。由于UserData是字符串,可自行定义格式,如用等号分割键值。这一步在需要细粒度权限判断时非常实用。
public static string GetUserData(string key)
{
var identity = HttpContext.Current.User.Identity as FormsIdentity;
if (identity == null) return null;
var ticket = identity.Ticket;
// userData格式: user_id=1001
foreach (var pair in ticket.UserData.Split('&'))
{
var arr = pair.Split('=');
if (arr.Length == 2 && arr[0] == key)
return arr[1];
}
return null;
}
四、退出登录与Cookie清理
退出动作应当清除认证Cookie并终止会话状态。调用FormsAuthentication.SignOut会移除对应的Cookie,但如果页面还用了Session,应额外调用Session.Abandon,避免残留数据被复用。
实际部署中,常有人只做重定向而忘记SignOut,导致浏览器Cookie仍在,用户点后退又能进入受限页。正确做法如下,同时把过期Cookie也写回客户端双保险。
public ActionResult Logout()
{
FormsAuthentication.SignOut();
Session.Abandon();
var cookie = new HttpCookie(FormsAuthentication.FormsCookieName, "");
cookie.Expires = DateTime.Now.AddYears(-1);
Response.Cookies.Add(cookie);
return RedirectToAction("Login");
}
五、常见误区与多服务器注意点
第一,把Forms身份验证和Session混用。前者无状态、靠Cookie,后者存服务端;重启Web服务Session丢失但Cookie仍有效。第二,负载均衡下未同步machineKey,票据解密失败引发反复跳登录。
解决machineKey问题,可在Web.config写死validationKey与decryptionKey,确保所有节点一致。另外,若站点混合HTTP与HTTPS,Secure Cookie设置不当会造成登录态丢失,需按入口统一规划。
| 对比项 | SetAuthCookie | 手动Ticket |
|---|---|---|
| 携带自定义数据 | 不支持 | 支持UserData |
| 控制Cookie属性 | 有限 | 完全可控 |
| 代码复杂度 | 低 | 稍高 |
通过上述实例,你可以看到ASP.NET MVC的Forms身份验证流程并不复杂,关键在于理解票据生命周期与Cookie安全设置。按照配置、签发、授权、退出四个环节落地,就能构建稳定可控的登录系统。
ASP.NET_MVCForms身份验证身份验证流程修改时间:2026-08-07 08:30:33