.NET Framework 4.8 WebForms JWT登录状态保持问题求助
.NET Framework 4.8 WebForms JWT登录状态丢失问题解决
问题根源分析
你当前的代码存在几个核心问题:
UseJwtBearerAuthentication是为WebAPI设计的,默认从Authorization: Bearer {token}请求头读取Token,而WebForms请求不会自动携带该头,导致验证逻辑失效。- 登录时手动设置的
HttpContext.Current.User仅对当前请求有效,刷新或跳转后不会自动恢复身份。 - 生成Token时未配置
Issuer和Audience,与验证参数不匹配,会导致后续验证失败。
解决方案步骤
1. 替换JWT Bearer认证为自定义Cookie验证中间件
在Owin Startup类中添加自定义中间件,从Cookie读取JWT并验证,自动设置请求的用户身份:
using Microsoft.Owin; using Owin; using System.IdentityModel.Tokens.Jwt; using System.Security.Claims; using System.Web; using System.Web.Configuration; [assembly: OwinStartup(typeof(YourProjectNamespace.Startup))] namespace YourProjectNamespace { public class Startup { public void Configuration(IAppBuilder app) { // 自定义JWT Cookie验证中间件 app.Use(async (context, next) => { var jwtCookie = context.Request.Cookies["jwt"]; if (!string.IsNullOrEmpty(jwtCookie)) { try { var validationParams = new Microsoft.IdentityModel.Tokens.TokenValidationParameters { ValidateIssuerSigningKey = true, IssuerSigningKey = new Microsoft.IdentityModel.Tokens.SymmetricSecurityKey( System.Text.Encoding.UTF8.GetBytes(WebConfigurationManager.AppSettings["SecretKey"])), ValidateIssuer = true, ValidIssuer = WebConfigurationManager.AppSettings["Issuer"], ValidateAudience = true, ValidAudience = WebConfigurationManager.AppSettings["Audience"], ValidateLifetime = true, ClockSkew = TimeSpan.Zero }; var tokenHandler = new JwtSecurityTokenHandler(); ClaimsPrincipal principal = tokenHandler.ValidateToken(jwtCookie, validationParams, out _); // 同步设置Owin和System.Web的用户身份 context.Authentication.User = principal; HttpContext.Current.User = principal; } catch { // 验证失败时清除无效Cookie context.Response.Cookies.Delete("jwt"); } } await next.Invoke(); }); } } }
2. 修复JWT生成代码,匹配验证参数
修改GenerateJwtToken方法,添加Issuer和Audience配置:
public static string GenerateJwtToken(string email) { var claims = new[] { new Claim(ClaimTypes.Email, email) }; var tokenDescriptor = new SecurityTokenDescriptor { Subject = new ClaimsIdentity(claims), Expires = DateTime.UtcNow.AddMinutes(30), Issuer = WebConfigurationManager.AppSettings["Issuer"], Audience = WebConfigurationManager.AppSettings["Audience"], SigningCredentials = new SigningCredentials( new SymmetricSecurityKey(System.Text.Encoding.UTF8.GetBytes(_secret)), SecurityAlgorithms.HmacSha256Signature) }; var tokenHandler = new JwtSecurityTokenHandler(); var token = tokenHandler.CreateToken(tokenDescriptor); return tokenHandler.WriteToken(token); }
3. 优化登录代码,增强Cookie安全性
更新登录逻辑,设置Cookie的安全属性,并避免空引用异常:
public void LoginUser(TextBox emailText, TextBox passwordText, Label errorMessage) { string email = emailText.Text.Trim(); string password = passwordText.Text; password = InOutUtils.CalculateHash(email, password); User user = _repo.GetUserByEmail(email); if (user != null && email.Equals(user.Email) && password.Equals(user.Password)) { string token = JwtAuthentication.GenerateJwtToken(email); var jwtCookie = new HttpCookie("jwt", token) { HttpOnly = true, // 防止XSS攻击 Secure = HttpContext.Current.Request.IsSecureConnection, // HTTPS环境下启用 Expires = DateTime.UtcNow.AddMinutes(30), // 与Token过期时间同步 Path = "/" // 确保全站Cookie有效 }; _response.AppendCookie(jwtCookie); // 当前请求立即设置身份,避免跳转前页面无法获取 var identity = new ClaimsIdentity(new[] { new Claim(ClaimTypes.Email, email) }, "jwt"); HttpContext.Current.User = new ClaimsPrincipal(identity); _response.Redirect("Home.aspx"); } else { errorMessage.Text = "邮箱或密码错误"; } }
4. 页面身份验证检查
在需要登录访问的页面(如Home.aspx)添加身份验证逻辑:
protected void Page_Load(object sender, EventArgs e) { if (!User.Identity.IsAuthenticated) { Response.Redirect("Login.aspx"); } // 获取用户邮箱示例 string userEmail = ((ClaimsIdentity)User.Identity).FindFirst(ClaimTypes.Email)?.Value; }
内容的提问来源于stack exchange,提问作者Random
相关产品推荐
相关产品推荐

