2017-08-28 261 views
3

我有一個控制器,我只想限制到一個特定的角色,比如說admin。在爲admin角色設置用戶後,我可以使用IsInRoleAsync方法(它返回true)驗證他是否在該角色上。當使用[Authorize(Roles = "admin")]設置屬性時,我得到了一個與該用戶完全相同的404。我使用持票人令牌(我認爲這不是相關的,但無論如何),這裏是我已經做的嘗試調試:ASP.NET Core Identity 2.0授權過濾器

控制器w/o [Authorize]:資源被返回。 [OK]

控制器與[Authorize]:即使有作用組中的用戶登錄後,我得到了:當我使用Authentication: Bearer [access token] [OK]

控制器與[Authorize(Roles = "admin")]資源只返回 404 [NOK]

我不知道如果我錯過了一些配置,但這裏是我的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>(); 

回答

3

您可能會收到404響應,因爲身份 - 自動配置爲services.AddIdentity()的默認身份驗證,登錄/註銷和質詢/禁止計劃 - 嘗試將您重定向到「訪問被拒絕的頁面」(默認爲Account/AccessDenied),這可能不會在您的應用程序中存在。

嘗試覆蓋缺省挑戰/禁止方案,看看是否能解決您的問題:

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

要解決你的第二個問題,確保了智威湯遜聲稱映射功能將被禁用。如果不是,JWT處理程序會將您所有的role索賠「轉換」爲ClaimTypes.Role,這將不起作用,因爲您將其配置爲使用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>() 
    }); 
}); 
+0

那麼,這解釋並解決了404,但是,爲什麼我無法訪問內容,因爲我的用戶具有所需的角色?現在我得到一個403 –

+0

@DanielS。答案更新爲您的第二個問題的修復。 – Pinpoint

+0

正如你所說的,我的問題是我的代幣沒有「角色」,因爲我認爲如果用戶分配了該角色,身份將檢查「AspNetUserRoles」。謝謝您的回答 –

1

我認爲你需要什麼是檢查索賠,而不是角色。添加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; 
    })); 
}); 
+0

我會盡力,雖然在[微軟的文檔](https://docs.microsoft.com/en-us/aspnet/core/security/authorization/roles)它似乎並沒有被需要。我的意思是,聽起來像不同的事情。 –

+0

角色有點老派,現在都是關於索賠。 –

+0

即使使用該策略,它也會返回404 –