好吧,我正在尝试在.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的新手,我不知道自己错过了什么。
我可以确认我的登录方法确实有效,找到用户并签发令牌,该令牌会在客户端收到。
答案 0 :(得分:0)
好吧,在启动类的ConfigureServices
方法中进行了一些额外的探索之后,我找到了自己的问题的答案,有必要指定要添加到MVC的授权过滤器,例如所以:
services.AddMvc(config =>
config.Filters.Add(new AuthorizeFilter(JwtBearerDefaults.AuthenticationScheme))
);
就是这样。我的带有[Authorize]
批注的操作现在可以按预期拒绝匿名请求。