首页 > 解决方案 > 尽管为安全端点分发了有效令牌,但邮递员仍返回 401

问题描述

我已经设置了这样的授权,松散地遵循这里这里这里的三个博客(除了验证到期时间之外,基本上是开放的)。

string secret = "super-secret-password";
byte[] bytes = Encoding.ASCII.GetBytes(secret);
SymmetricSecurityKey key = new SymmetricSecurityKey(bytes);
TokenValidationParameters parameters = new TokenValidationParameters
{
  IssuerSigningKey = key,
  ValidateLifetime = true,
  ValidateIssuerSigningKey = false,
  ValidateIssuer = false,
  ValidateAudience = false,
  RequireAudience = false,
  RequireExpirationTime = false,
  RequireSignedTokens = false
};
services.AddAuthentication(_ => _.DefaultScheme = JwtBearerDefaults.AuthenticationScheme)
  .AddJwtBearer(_ => _.TokenValidationParameters = parameters);

分发的令牌是这样创建的。

string secret = "super-secret-password";
byte[] bytes = Encoding.ASCII.GetBytes(secret);
SymmetricSecurityKey key = new SymmetricSecurityKey(bytes);

Claim[] claims = {
  new Claim("role", "basic"),
  new Claim("role", "elevated"),
  new Claim("name", name)
};

JwtSecurityTokenHandler handler = new JwtSecurityTokenHandler();
SecurityTokenDescriptor descriptor = new SecurityTokenDescriptor
{
  Subject = new ClaimsIdentity(claims),
  Expires = DateTime.Now.AddHours(1),
  SigningCredentials = new SigningCredentials(key, SecurityAlgorithms.HmacSha256Signature)
};

SecurityToken token = handler.CreateToken(descriptor);
return handler.WriteToken(token);

然后,我将返回的字符串粘贴到 JWT.io 中,它确认一切都很好(有效的签名等等)。但是,当我在 Postman 中使用该令牌时(它添加了标头Bearer + my_token_string),该调用给了我 401 未授权。

我在我的控制器中尝试了两种安全方法,一种是打开的(后者按预期工作)。

[HttpGet("open"), AllowAnonymous]
public ActionResult OpenResult() { return Ok("Open result accessed."); }
[HttpGet("secure"), Authorize]
public ActionResult SecureResult() { return Ok("Secure result accessed."); }
[HttpGet("elevated"), Authorize(Roles = "elevated")]
public ActionResult ElevatedResult() { return Ok("Elevated result accessed."); }

我不知道我可能会错过什么。更糟糕的是,我不确定如何进一步调查。

此时我能做什么?

这个答案建议设置标题。这个答案与我没有观众验证的轻松案例无关。这个答案真的没什么。(只是确保表明我已经尽力了。)

标签: c#securityasp.net-core.net-corejwt

解决方案


要检查的一件事是 Startup.cs 中配置中“使用”语句的顺序。如果你在 app.UseAuthentication() 之前有 app.UseAuthorization(),你会得到 401。这已经抓住了我之前:

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }

        app.UseCors("CorsPolicy");

        app.UseRouting();

        app.UseAuthentication(); //make sure this comes before app.UseAuthorization()
        app.UseAuthorization(); 
        app.UseHttpsRedirection();

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllers();
            endpoints.MapHub<NotificationHubService>("/notification");
        });
    }

推荐阅读