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

ASP.NET WEB API自定义过滤器Session Token获取为Null问题求助

问题

我正在为ASP.NET Web API做JWT令牌的POC验证:

  1. 实现学生登录API,生成JWT令牌并存入Session
  2. 学生登录后请求个人资料接口时,需通过自定义StudentAttribute过滤器验证身份
  3. 调试发现过滤器中从Session获取的Token值为Null,但通过请求头能正常获取该令牌
  4. 相同逻辑在MVC Core项目中可正常运行,求问题原因及解决办法

登录API代码

[HttpPost]
public JsonResult AuthenticateStudent(string emailId, string password)
{
    try
    {
        if(studBLObj.AuthenticateStudent(emailId, password))
        {
            HttpContext.Session.SetString("email_ID", emailId);
            HttpContext.Session.SetString("studentRole", "Student");
            string token = GenerateToken();
            HttpContext.Session.SetString("Token", token);
            return new JsonResult(new { Success = true, message = "Login Succesful", token = token });
        }
        else
        {
            return new JsonResult(new { Success = false, message = "Error! Please contact admin" });
        }

    }
    catch (Exception e)
    {
        return new JsonResult(new { Success = false, message = e.Message });
    }
}

个人资料接口代码

[Student]
[HttpGet]
public string GetStudentProfile(int rollNo)
{
    
    try
    {
        var studentsProfile = studentBLObj.GetStudentProfile(rollNo);
        JsonResult jsonResult = new JsonResult(studentsProfile);
        var jsonString = Newtonsoft.Json.JsonConvert.SerializeObject(jsonResult.Value);
        
        return jsonString;
    }
    catch (Exception e)
    {
        throw e;
    }
}

自定义StudentAttribute过滤器代码

public class StudentAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext context)
    {
        base.OnActionExecuting(context);
        // 此处无法获取Token,值为Null
        string sessionToken = context.HttpContext.Session.GetString("Token");
        
        // 通过请求头可正常获取Token
        var req = context.HttpContext.Request.Headers["Authorization"];
        
        if (sessionToken==null ||  sessionToken != req)
        {
            context.Result =
            new RedirectToRouteResult(new RouteValueDictionary
                     {
                          { "action", "UnauthorizedAccess" },
                        { "controller", "Student" }
                      });
            return;
        }
        else
        {
            return;
        }

    }
}

原因分析

  • Web API与MVC的Session依赖差异:MVC项目基于浏览器运行,浏览器会自动保存并在后续请求中携带Session对应的Cookie(如.AspNetCore.Session);但Web API的客户端(如Postman、前端AJAX请求)默认不会自动处理Cookie,导致后续请求无法携带Session标识,服务器无法识别会话,因此Session中取不到值。
  • JWT与Session的设计冲突:JWT的核心是无状态认证,令牌本身包含所有用户信息,不需要依赖服务器端Session存储;当前设计既用JWT又存Session,违背了JWT的无状态特性,也放大了Session在API场景中的局限性。

解决方案

方案1:修正Session使用方式(不推荐,仅适配API场景)

如果一定要保留Session验证逻辑,需确保客户端携带Session Cookie:

  1. 配置API允许Cookie传递:在Program.cs中完善Session和Cookie政策配置
builder.Services.AddSession(options =>
{
    options.IdleTimeout = TimeSpan.FromMinutes(30);
    options.Cookie.HttpOnly = true;
    options.Cookie.IsEssential = true;
});

builder.Services.Configure<CookiePolicyOptions>(options =>
{
    options.MinimumSameSitePolicy = SameSiteMode.None;
    options.HttpOnly = HttpOnlyPolicy.Always;
    options.Secure = CookieSecurePolicy.Always; // 生产环境启用,需HTTPS
});
  1. 客户端设置:
    • Postman:开启请求的「Send cookies」选项
    • 前端AJAX:设置withCredentials: true,同时后端需配置CORS允许凭证

方案2:遵循JWT无状态认证设计(推荐)

放弃Session存储Token,直接通过请求头验证JWT令牌,这是API场景的标准做法:

  1. 修改过滤器逻辑,直接解析验证请求头中的JWT令牌:
public class StudentAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext context)
    {
        base.OnActionExecuting(context);
        
        if (!context.HttpContext.Request.Headers.TryGetValue("Authorization", out var authHeader))
        {
            context.Result = new UnauthorizedResult();
            return;
        }

        var token = authHeader.ToString().Replace("Bearer ", string.Empty);
        try
        {
            var claimsPrincipal = ValidateToken(token);
            var roleClaim = claimsPrincipal.Claims.FirstOrDefault(c => c.Type == ClaimTypes.Role);
            
            if (roleClaim?.Value != "Student")
            {
                context.Result = new ForbidResult();
                return;
            }
        }
        catch (Exception)
        {
            context.Result = new UnauthorizedResult();
            return;
        }
    }

    private ClaimsPrincipal ValidateToken(string token)
    {
        var tokenHandler = new JwtSecurityTokenHandler();
        var key = Encoding.ASCII.GetBytes("你的JWT密钥"); // 建议从配置文件读取
        tokenHandler.ValidateToken(token, new TokenValidationParameters
        {
            ValidateIssuerSigningKey = true,
            IssuerSigningKey = new SymmetricSecurityKey(key),
            ValidateIssuer = false, // 根据实际配置调整
            ValidateAudience = false,
            ClockSkew = TimeSpan.Zero
        }, out SecurityToken validatedToken);

        return new ClaimsPrincipal(tokenHandler.ReadJwtToken(token).Claims);
    }
}
  1. 登录API无需存储Session,直接返回JWT令牌即可:
[HttpPost]
public JsonResult AuthenticateStudent(string emailId, string password)
{
    try
    {
        if(studBLObj.AuthenticateStudent(emailId, password))
        {
            string token = GenerateToken(); // 确保生成的Token包含Student角色声明
            return new JsonResult(new { Success = true, message = "Login Successful", token = token });
        }
        else
        {
            return new JsonResult(new { Success = false, message = "Error! Please contact admin" });
        }

    }
    catch (Exception e)
    {
        return new JsonResult(new { Success = false, message = e.Message });
    }
}

内容的提问来源于stack exchange,提问作者Varun Gupta

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 11:23:23