c# - 尽管为安全端点分发了有效令牌,但邮递员仍返回 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."); }
我不知道我可能会错过什么。更糟糕的是,我不确定如何进一步调查。
此时我能做什么?
解决方案
要检查的一件事是 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");
});
}
推荐阅读
- vue.js - axios 响应中的 Vue 数据绑定未在视图中更新
- mysql - 在带有 mysql-source 的 grafana 中使用 sankey-diagram
- qt - 在 QML tableview 中单击时复选框变大
- python-3.x - 如何使用 Python 旋转数据框字符串值
- hibernate - 为什么“ORDER BY field_name LIKE 'start%'”在 Hibernate/Spring/JPA 中不起作用,而在普通 SQL 中起作用?
- c# - 有效地从 .xml 文件中获取信息并使其可用于其他方法
- wpf - WPF 在标签周围放置一个白色间隙
- reactjs - react-hook-form 条件表单值控制
- batch-file - 批处理:如何使用“devcon status”返回作为 IF 条件?
- python - 基于多个条件填充numpy数组的正确方法