为什么ASP.NET Core Identity 2.0 Authorize过滤器导致我得到404? [英] Why is ASP.NET Core Identity 2.0 Authorize filter causing me to get a 404?
问题描述
我有一个控制器,只想限制为特定角色,例如admin
.设置具有admin
角色的用户后,我可以使用IsInRoleAsync
方法(返回true)来验证他是否处于该角色.当使用[Authorize(Roles = "admin")]
设置属性时,我得到了与该用户相同的404信息.我正在使用不记名令牌(我认为这并不重要,但是无论如何),这是我尝试调试的方法:
I have a controller that I want to restrict only to a specific role, let's say admin
. After setting a user with the admin
role, I can validate that he's on that role using the IsInRoleAsync
method (which returns true). When setting the attribute with [Authorize(Roles = "admin")]
I get a 404 with that very same user . I'm using bearer tokens (I don't think that is relevant but anyway) and here's what I've done to try debugging:
不带[Authorize]
的控制器:返回资源. [确定]
Controller w/o [Authorize]
: the resource is returned. [OK]
带有[Authorize]
的控制器:当我使用Authentication: Bearer [access token]
[确定]
Controller with [Authorize]
: the resource is returned only when I use the Authentication: Bearer [access token]
[OK]
使用[Authorize(Roles = "admin")]
的控制器:即使使用具有角色集的用户登录,我仍然会收到404 [NOK]
Controller with [Authorize(Roles = "admin")]
: even after logging in with the user that has the role set, I get the 404 [NOK]
我不知道是否缺少某些配置,但这是我的ConfigureServices:
I don't know if I'm missing some configuration, but here's my ConfigureServices:
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
// Add framework services.
services.AddDbContext<ApplicationDbContext>(options =>
{
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"));
options.UseOpenIddict();
});
services.AddIdentity<ApplicationUser, IdentityRole>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();
services.AddOpenIddict(opt =>
{
opt.AddEntityFrameworkCoreStores<ApplicationDbContext>();
opt.AddMvcBinders();
opt.EnableTokenEndpoint("/api/token");
opt.AllowPasswordFlow();
opt.DisableHttpsRequirement(); //for dev only!
opt.UseJsonWebTokens();
opt.AddEphemeralSigningKey();
opt.AllowRefreshTokenFlow();
opt.SetAccessTokenLifetime(TimeSpan.FromMinutes(5));
});
services.AddAuthentication(options =>
{
options.DefaultScheme = OAuthValidationDefaults.AuthenticationScheme;
options.DefaultAuthenticateScheme = OAuthValidationConstants.Schemes.Bearer;
options.DefaultSignInScheme = IdentityConstants.ExternalScheme;
})
.AddJwtBearer(options =>
{
options.Authority = "http://localhost:44337/";
options.Audience = "resource_server";
options.RequireHttpsMetadata = false;
options.TokenValidationParameters = new TokenValidationParameters
{
NameClaimType = OpenIdConnectConstants.Claims.Subject,
RoleClaimType = OpenIdConnectConstants.Claims.Role
};
});
services.Configure<IdentityOptions>(options =>
{
// Password settings
options.Password.RequireDigit = true;
options.Password.RequiredLength = 8;
options.Password.RequireNonAlphanumeric = false;
options.Password.RequireUppercase = true;
options.Password.RequireLowercase = false;
// Lockout settings
options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(30);
options.Lockout.MaxFailedAccessAttempts = 10;
// User settings
options.User.RequireUniqueEmail = true;
// Add application services.
options.ClaimsIdentity.UserNameClaimType= OpenIdConnectConstants.Claims.Name;
options.ClaimsIdentity.UserIdClaimType = OpenIdConnectConstants.Claims.Subject;
options.ClaimsIdentity.RoleClaimType = OpenIdConnectConstants.Claims.Role;
});
services.AddSingleton(typeof(RoleManager<ApplicationUser>));
// Add application services.
services.AddTransient<IEmailSender, AuthMessageSender>();
services.AddTransient<ISmsSender, AuthMessageSender>();
推荐答案
您可能会收到404响应,因为Identity-由Account/AccessDenied
).
You likely get a 404 response because Identity - which is automatically configured as the default authentication, sign-in/sign-out and challenge/forbidden scheme by services.AddIdentity()
- tries to redirect you to the "access denied page" (Account/AccessDenied
by default), that probably doesn't exist in your application.
尝试覆盖默认的质询/禁止方案,以查看它是否可以解决您的问题:
Try to override the default challenge/forbidden scheme to see if it fixes your issue:
services.AddAuthentication(options =>
{
// ...
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultForbidScheme = JwtBearerDefaults.AuthenticationScheme;
});
要解决第二个问题,请确保已禁用JWT声明映射功能.如果不是,那么JWT处理程序会将您的所有role
声明转换"为ClaimTypes.Role
,这在您将其配置为使用role
作为ClaimsPrincipal.IsInRole(...)
(RoleClaimType = OpenIdConnectConstants.Claims.Role
)所使用的角色声明时将不起作用
To fix your second issue, make sure the JWT claims mapping feature is disabled. If it's not, the JWT handler will "convert" all your role
claims to ClaimTypes.Role
, which won't work as you configured it to use role
as the role claim used by ClaimsPrincipal.IsInRole(...)
(RoleClaimType = OpenIdConnectConstants.Claims.Role
).
services.AddAuthentication(options =>
{
options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(options =>
{
// ...
options.SecurityTokenValidators.Clear();
options.SecurityTokenValidators.Add(new JwtSecurityTokenHandler
{
// Disable the built-in JWT claims mapping feature.
InboundClaimTypeMap = new Dictionary<string, string>()
});
});
这篇关于为什么ASP.NET Core Identity 2.0 Authorize过滤器导致我得到404?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!