You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 02:00:36