【发布时间】:2019-08-05 21:06:20
【问题描述】:
好吧,我正在尝试在我的 .NET Core 2.x API 中建立基于 JWT 的授权。我一切正常,除此之外:我为应用授权而设置的测试操作不会拒绝未经身份验证的请求——它只是提供内容,就好像根本没有应用授权一样。
在我的Startup 我有:
services.AddAuthentication(authOptions =>
{
authOptions.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
authOptions.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(jwtOptions =>
{
jwtOptions.Authority = configuration["Jwt:Issuer"];
jwtOptions.SaveToken = true;
jwtOptions.RequireHttpsMetadata = false;
jwtOptions.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = true,
ValidIssuer = configuration["Jwt:Issuer"],
ValidAudience = configuration["Jwt:Issuer"],
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(configuration["Jwt:Key"]))
};
});
services.AddAuthorization(options =>
{
options.AddPolicy("Bearer", new AuthorizationPolicyBuilder()
.AddAuthenticationSchemes(JwtBearerDefaults.AuthenticationScheme)
.RequireAuthenticatedUser()
.Build());
});
然后在Configure:
app.UseAuthentication();
我有一个像这样的登录 API 操作:
...
[Route("api/user")]
[ApiController]
public class AppUserController : ControllerBase
{
...
[HttpPost("authenticate")]
[AllowAnonymous]
[Produces("application/json")]
public async Task<IActionResult> Authenticate([FromBody] LoginDto model)
{
if (ModelState.IsValid)
{
var user = await _authenticationHandler.Authenticate(model);
if (user != null)
{
return Ok(_authenticationHandler.GetJwt(user.Name));
}
}
ModelState.AddModelError("", "Invalid login attempt");
return Ok();
}
}
...
其中 _authenticationHandler 是以下实例:
public class IdentityHandler
{
private readonly UserManager<AppUser> _userManager;
private readonly IConfiguration _configuration;
public IdentityHandler
(
IConfiguration configuration,
UserManager<AppUser> userManager
)
{
_configuration = configuration;
_userManager = userManager;
}
public string GetJwt(string username)
{
var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_configuration["Jwt:Key"]));
var credentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256);
var claims = new HashSet<Claim>
{
new Claim(JwtRegisteredClaimNames.Sub, username),
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
new Claim(JwtRegisteredClaimNames.Iat, DateTime.Now.ToString())
};
var token = new JwtSecurityToken
(
_configuration["Jwt:Issuer"],
claims: claims,
signingCredentials: credentials,
expires: DateTime.Now.AddDays(10)
);
return new JwtSecurityTokenHandler().WriteToken(token);
}
public async Task<ClaimsIdentity> Authenticate(LoginDto loginModel)
{
var user = await _userManager.FindByNameAsync(loginModel.Username);
var identity = new ClaimsIdentity();
if (user != null && await _userManager.CheckPasswordAsync(user, loginModel.Password))
{
identity.AddClaim(new Claim(ClaimTypes.Name, user.NormalizedUserName));
}
return identity;
}
}
最后,我有一个使用 Authorize 指令注释的 API 操作,例如:
[HttpGet("test")]
[Authorize]
[Produces("application/json")]
public IActionResult Test()
{
return Ok("accepted");
}
我的期望是,如果我尝试导航到该操作,则该请求应被视为未经授权而被拒绝。它不是。作为 JWT 的新手,我不知道自己错过了什么。
我可以确认我的登录方法确实有效,找到用户并发出一个令牌,该令牌在客户端收到。
【问题讨论】:
-
你能检查你的请求头,你有什么键和值吗?并在 Test 操作中添加断点并检查
User.Identity的值是什么 -
是的,我已经做到了。用户的测试操作中的传入值为 null - 即,根本没有特定身份,就像测试这种情况一样。
标签: c# .net-core jwt asp.net-authorization