我无法通过我的.NET Core 2.0 web api应用程序中的策略([Authorize(Policy = "AdminAccess")]
)进行授权。
我使用基于JWT的身份验证,它几乎可以工作。是的,差不多。
我有ValuesController有3个方法:
[Route("api/values")]
GetValues()
[Authorize]
[Route("api/secretvalues")]
GetSecretValues()
[Authorize(Policy = "AdminAccess")]
[Route("api/adminsecretvalues")]
GetAdminSecretValues()
我能够从不受保护的方法api /值中获取值。当我试图达到api / secretvalues,受[授权]保护时,我得到了401错误,没问题。然后我可以在我的TokenController中调用api / token,我收到令牌,如果我在下次调用api / secretvalues时使用它一切正常,我可以看到受保护的数据。但第三种方法不起作用。我总是得到未经授权。我在.NET Core 2.0 JWT的mozaic中缺少一些小部分,但我不知道它是什么。
这是我的代码:
Startup.cs
namespace JwtWebApplication
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.Configure<TokenAuthenticationSettings>(Configuration.GetSection("TokenAuthentication"));
string key = Configuration.GetSection("TokenAuthentication:Key").Value;
var securityKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(key));
var tokenValidationParameters = new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = securityKey,
ValidateIssuer = true,
ValidIssuer = Configuration.GetSection("TokenAuthentication:Issuer").Value,
ValidateAudience = true,
ValidAudience = Configuration.GetSection("TokenAuthentication:Audience").Value,
ValidateLifetime = true,
ClockSkew = TimeSpan.Zero
};
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options => {
options.RequireHttpsMetadata = false;
options.SaveToken = true;
options.TokenValidationParameters = tokenValidationParameters;
});
services.AddAuthorization(options =>
{
options.DefaultPolicy = new AuthorizationPolicyBuilder(JwtBearerDefaults.AuthenticationScheme).RequireAuthenticatedUser().Build();
options.AddPolicy("AdminAccess", policy => policy.RequireClaim("role", "admin"));
});
services.AddCors(options =>
{
options.AddPolicy("CorsPolicy",
builder => builder.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials());
});
services.AddMvc();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseAuthentication(); // JWT Authentication
app.UseMvc();
}
}
}
TokenController.cs
namespace JwtWebApplication.Controllers
{
public class TokenController : Controller
{
private readonly IConfiguration configuration;
public TokenController(IConfiguration configuration)
{
this.configuration = configuration;
}
[HttpPost]
[Route("api/token")]
public IActionResult GetToken([FromBody] TokenRequest tokenRequest)
{
if (string.IsNullOrWhiteSpace(tokenRequest.Username) || (tokenRequest.Username != tokenRequest.Password))
{
return BadRequest();
}
return new ObjectResult(GenerateToken(tokenRequest.Username));
}
private string GenerateToken(string username)
{
var claims = new Claim[]
{
new Claim(ClaimTypes.Name, username),
new Claim(JwtRegisteredClaimNames.Nbf, new DateTimeOffset(DateTime.Now).ToUnixTimeSeconds().ToString()),
new Claim(JwtRegisteredClaimNames.Exp, new DateTimeOffset(DateTime.Now.AddDays(1)).ToUnixTimeSeconds().ToString()),
new Claim(ClaimTypes.Role, "admin"),
new Claim("role", "admin")
};
string issuer = this.configuration.GetSection("TokenAuthentication:Issuer").Value;
string audience = this.configuration.GetSection("TokenAuthentication:Audience").Value;
string key = this.configuration.GetSection("TokenAuthentication:Key").Value;
SymmetricSecurityKey securityKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(key));
SigningCredentials signingCredentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256);
var token = new JwtSecurityToken(issuer, audience, claims, null, null, signingCredentials);
return new JwtSecurityTokenHandler().WriteToken(token);
}
}
}
ValuesController.cs
namespace JwtWebApplication.Controllers
{
public class ValuesController : Controller
{
[AllowAnonymous]
[HttpGet]
[Route("api/values")]
public IEnumerable<string> GetValues()
{
return new string[] { "Value 1", "Value 2", "Value 3" };
}
[Authorize]
[HttpGet]
[Route("api/secretvalues")]
public IEnumerable<string> GetSecretValues()
{
return new string[] { "Secret Value 1", "Secret Value 2", "Secret Value 3" };
}
[Authorize(Policy = "AdminAccess")]
[HttpGet]
[Route("api/adminsecretvalues")]
public IEnumerable<string> GetAdminSecretValues()
{
return new string[] { "Admin Secret Value 1", "Admin Secret Value 2", "Admin Secret Value 3" };
}
}
}
我将声明new Claim(ClaimTypes.Role, "admin")
添加到令牌中,我认为这已经足够了,但显然不是。就像在授权过程中没有解压缩一样。但是如果我在ValuesController中调试HttpContext.User对象,我可以看到声明存在,但它根本不起作用。
也许我不明白,但我不知道它是什么。
答案 0 :(得分:3)
有同样的问题然后找到了解决方案,以防其他人遇到同样的问题。
services.AddAuthorization(options =&gt; { options.AddPolicy(“AdminAccess”,policy =&gt; { 的 policy.AuthenticationSchemes.Add(JwtBearerDefaults.AuthenticationScheme); 强> policy.RequireAuthenticatedUser(); policy.Requirements.Add(new MinimumAgeRequirement()); }); });
添加策略时,也要定义AuthenticationScheme。
以下是您可以了解更多内容的链接