代码之家  ›  专栏  ›  技术社区  ›  Daniel S.

为什么是ASP。NET Core Identity 2.0授权过滤器导致我获得404?

  •  7
  • Daniel S.  · 技术社区  · 8 年前

    我有一个控制器,我只想限制到一个特定的角色,比方说 admin 管理 角色,我可以使用 IsInRoleAsync 方法(返回true)。使用设置属性时 [Authorize(Roles = "admin")]

    无控制器 [Authorize] :返回资源。[确定]

    :返回资源 只有 当我使用 Authentication: Bearer [access token] [确定]

    控制器 :即使在与具有角色集的用户登录后,我也会得到404[NOK]

    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>();
    
    2 回复  |  直到 7 年前
        1
  •  6
  •   Kévin Chalet    8 年前

    您可能会收到404响应,因为身份自动配置为默认身份验证、登录/注销和质询/禁止方案 services.AddIdentity() -尝试将您重定向到“拒绝访问页面”( Account/AccessDenied 默认情况下),这可能在应用程序中不存在。

    services.AddAuthentication(options =>
    {
        // ...
        options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
        options.DefaultForbidScheme = JwtBearerDefaults.AuthenticationScheme;
    });
    

    要解决第二个问题,请确保禁用JWT索赔映射功能。如果不是,JWT处理程序将“转换”所有 role ClaimTypes.Role ,当您将其配置为使用时,它将不起作用 作为角色声明由使用 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>()
        });
    });
    
        2
  •  2
  •   Ricardo Peres    8 年前

    我认为你需要的是检查声明,而不是角色。添加 AuthorizeAttribute 例如:

    [Authorize(Policy = "AdminOnly")]
    

    然后配置需要声明的策略:

    services.AddAuthorization(options =>
    {
        options.AddPolicy("AdminOnly", policy =>
                          policy.RequireClaim(OpenIdConnectConstants.Claims.Role, "Admin"));
    });
    

    services.AddAuthorization(options =>
    {
        options.AddPolicy("AdminOnly", policy =>
                          policy.RequireAssertion(ctx =>
       {
           //do your checks
           return true;
       }));
    });