簡體   English   中英

.Net Core 2 JWT、Angular 2 通過角色授權不起作用

[英].Net Core 2 JWT, Angular 2 Authorization through roles does not work

我在用 JWT 生成的令牌中有以下有用的負載

{ "sub": "flamelsoft@gmail.com", "jti": "0bca1034-f3ce-4f72-bd91-65c1a61924c4", " http://schemas.microsoft.com/ws/2008/06/identity/claims/角色":"管理員","exp":1509480891,"iss":" http://localhost:40528 ","aud":" http://localhost:40528 "}

使用此代碼 Startup.cs

        public void ConfigureServices(IServiceCollection services)
    {
        services.AddDbContext<DBContextSCM>(options =>
        options.UseMySql(Configuration.GetConnectionString("DefaultConnection"), b =>
         b.MigrationsAssembly("FlamelsoftSCM")));

        services.AddIdentity<User, Role>()
            .AddEntityFrameworkStores<DBContextSCM>()
            .AddDefaultTokenProviders();

        services.AddScoped(typeof(IRepository<>), typeof(Repository<>));

        services.AddAuthentication()
             .AddJwtBearer(cfg =>
             {
                 cfg.RequireHttpsMetadata = false;
                 cfg.SaveToken = true;

                 cfg.TokenValidationParameters = new TokenValidationParameters()
                 {
                     ValidIssuer = Configuration["Tokens:Issuer"],
                     ValidAudience = Configuration["Tokens:Issuer"],
                     IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["Tokens:Key"]))
                 };

             });

        services.AddMvc();
    }

賬戶控制器.cs

        [HttpPost]
    [Authorize(Roles="Administrator")]
    public async Task<IActionResult> Register([FromBody]RegisterModel model)
    {
        try
        {
            var user = new User { UserName = model.Email, Email = model.Email };
            var result = await _userManager.CreateAsync(user, model.Password);
            if (result.Succeeded)
            {
                var role = await _roleManager.FindByIdAsync(model.Role);
                result = await _userManager.AddToRoleAsync(user, role.Name);

                if (result.Succeeded)
                    return View(model);
            }
            return BadRequest($"Error: Could not create user");
        }
        catch (Exception ex)
        {
            return BadRequest($"Error: {ex.Message}");
        }
    }

用戶服務.ts

export class UserService {

constructor(private http: Http, private config: AppConfig, private currentUser: User) { }

create(user: User) {
    return this.http.post(this.config.apiUrl + 'Account/Register', user, this.jwt());
}

private jwt() {
    const userJson = localStorage.getItem('currentUser');
    this.currentUser = userJson !== null ? JSON.parse(userJson) : new User();

    if (this.currentUser && this.currentUser.token) {
        let headers = new Headers({ 'Authorization': 'Bearer ' + this.currentUser.token });
        return new RequestOptions({ headers: headers });
    }
}}

問題是角色的驗證不起作用,請求到達控制器並在header中返回代碼200,但從未進入類。 當我刪除 [Authorize (Roles = "Administrator")] 時,它會正確輸入我的代碼。 有什么不好的定義嗎? 或者通過角色定義授權的替代方法是什么。

TL; DR

如原始問題的評論中所述,更改:

[HttpPost]
[Authorize(Roles = "Administrator")]
public async Task<IActionResult> Register([FromBody]RegisterModel model)
{
    // Code
}

[HttpPost]
[Authorize(AuthenticationSchemes = "Bearer", Roles = "Administrator")]
public async Task<IActionResult> Register([FromBody]RegisterModel model)
{
    // Code
}

解決了這個問題。

在ASP.NET Core中使用JWT承載認證時, Bearer默認的認證方案名稱


但是為什么我們需要在[Authorize]屬性上指定AuthenticationSchemes屬性?

這是因為配置身份驗證方案並不意味着它們將在每個HTTP請求上運行。 如果匿名用戶可以訪問特定操作,為什么還要從cookie或令牌中提取用戶信息呢? MVC對此非常聰明,並且只在需要時運行身份驗證處理程序,即在以某種方式受到保護的請求期間運行。

在我們的例子中,MVC發現[Authorize]屬性,因此知道它必須運行身份驗證和授權來確定請求是否被授權。 訣竅在於它只運行已指定的身份驗證方案處理程序 在這里,我們沒有,所以沒有執行身份驗證,這意味着授權失敗,因為請求被認為是匿名的。

將身份驗證方案添加到屬性指示MVC以運行該處理程序,該處理程序從HTTP請求中的令牌中提取用戶信息,這導致發現Administrator角色,並且允許該請求。


作為旁注,還有另一種方法可以實現這一點,而無需使用[Authorize]屬性的AuthenticationSchemes屬性。

想象一下,您的應用程序只配置了一個身份驗證方案,必須在每個[Authorize]屬性上指定AuthenticationSchemes屬性是一件痛苦的事。

使用ASP.NET Core,您可以配置默認的身份驗證方案。 這樣做意味着將為每個HTTP請求運行關聯的處理程序,無論資源是否受到保護。

設置它分為兩部分:

public class Startup
{
    public void ConfiguresServices(IServiceCollection services)
    {
        services
            .AddAuthentication(JwtBearerDefaults.AuthenticationScheme /* this sets the default authentication scheme */)
            .AddJwtBearer(options =>
            {
                // Configure options here
            });
    }

    public void Configure(IApplicationBuilder app)
    {
        // This inserts the middleware that will execute the 
        // default authentication scheme handler on every request
        app.UseAuthentication();

        app.UseMvc();
    }
}

這樣做意味着在MVC評估請求是否被授權時,已經進行了AuthenticationSchemes ,因此不指定[Authorize]屬性的AuthenticationSchemes屬性的任何值都不會有問題。

進程的授權部分仍將運行,並檢查經過身份驗證的用戶是否屬於Administrator組。

我知道這個問題已經有了答案,但這里遺漏了一些重要的東西。 您需要確保您確實為登錄用戶設置了聲明。 就我而言,我使用的是 JWT 身份驗證,因此這一步非常重要:

    var claims = new ClaimsIdentity(new[] { new Claim(ClaimTypes.NameIdentifier, user.UserName) });
    var roles = await _userManager.GetRolesAsync(user);
    if (roles.Count > 0)
    {
        foreach (var role in roles) { claims.AddClaim(new Claim(ClaimTypes.Role, role)); }
    }

    var token = new JwtSecurityToken(
        issuer: _configuration["JWT:Issuer"],
        audience: _configuration["JWT:Audience"],
        expires: DateTime.UtcNow.AddMinutes(15),
        signingCredentials: signingCredentials,
        claims: claims.Claims);

我正在努力弄清楚為什么HttpContext.User沒有包含我期望縮小[Authroization(Roles="Admin")]問題的范圍。 事實證明,如果您使用JWT身份驗證,您需要記住將Claims[]設置為身份。 也許這是通過其他dotnet方式自動完成的,但jwt似乎要求您手動設置。

在我為用戶設置聲明后, [Authorize(Roles = "Whatever")]按預期工作。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM