iT邦幫忙

2022 iThome 鐵人賽

DAY 27
0
Modern Web

擁抱 .Net Core系列 第 27

[Day27] 授權 - Authorized - 1

  • 分享至 

  • xImage
  •  

驗證是確認身分,而授權指的是基於知道你的身分的情況下
根據「策略」(Policy)決定是否有許可權操作資源
策略可以很廣泛,在經過驗證後,會將驗證身分存到ClaimPrincipal
因此,可以透過其中的Claim 不同的策略,例如年齡(你已滿18歲,是,Yes),性別55555555555555555555555555,還有最常見的以角色為基礎的授權

以角色為基礎的驗證

我們一樣要用昨天的jwtService來模擬登入取得身分令牌
修改一下,我們再回傳的Identity中加入Role 的 Claim
先說我知道很多寫法沒那麼好,但就是個範例XD

TokenService.cs

public string CreateJwtToken(Member member)
{
    var userIdentity = new ClaimsIdentity(new[]
    {
        new Claim(JwtRegisteredClaimNames.Name, member.Account),
        new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
        new Claim(JwtRegisteredClaimNames.Email, member.Email),
    });

    userIdentity.AddClaims(member.Roles.Select(role => new Claim(ClaimTypes.Role, role)));

    var issuer = "issuer";//_configuration["jwt:Issuer"];
    var key = "kewernmkjohiusdfy";//_configuration["jwt:key"];

    var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(key));
    var signingCredentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256Signature);

    var securityTokenDescriptor = new SecurityTokenDescriptor
    {
        Issuer = issuer,
        Subject = userIdentity,
        Expires = DateTime.Now.AddDays(7),
        SigningCredentials = signingCredentials
    };
    var securityToken = _jwtSecurityTokenHandler.CreateToken(securityTokenDescriptor);
    var token = _jwtSecurityTokenHandler.WriteToken(securityToken);

    return token;
}

在Member 添加Role的屬性,並且在fakeData補上角色

public class Member
{
    public string Account { get; set; }
    public string Password { get; set; }
    public string Email { get; set; }
    public string[] Roles { get; set; }
}

private IReadOnlyList<Member> _fakeMembers = new List<Member>()
{
    new() { Account = "Admin", Password = "Admin", Email = "admin@gmail.com", Roles = new[] { "Admin", "User" } },
    new() { Account = "User", Password = "User", Email = "user@gmail.com", Roles = new []{ "User" } }
};

這邊在TokenController 中加入authorize Service 的驗證
TokenController.cs

[HttpGet]
public async Task<string> Get()
{
    var authorizeService = HttpContext.RequestServices.GetRequiredService<IAuthorizationService>();
    var authorizationResult = await authorizeService.AuthorizeAsync(HttpContext.User, null, new List<IAuthorizationRequirement>()
    {
        new RolesAuthorizationRequirement(new[] { "Admin" })
    });

    if(authorizationResult.Succeeded) return "Hello World";
    Response.StatusCode = 403;
    return "Forbidden";
}

最後需要在pipeline中加入app.UseAuthorization()的方法
記得放在app.UseAuthentication(); 後面
要先有驗證才有授權

透過加入IAuthorizationRequirement物件,可以添加要針對的授權
RolesAuthorizationRequirement會去驗證當前使用者的Claim中的 ClaimType.Role 是否有符合的身分
有的話可以順利取到Helloworld 的字眼
沒有的話就會被Forbid

使用Policy的授權

在每個方法都加一個上面的授權應該會崩潰
而且授權的邏輯應該是可共用且與原先方法的邏輯並無這麼的相關
因此,我們可以透過AOP的方式來處理

.NetCore 提供以Policy為基礎的授權方式
可以透過添加Policy加Attribute的方式來做驗證
program.cs

builder.Services.AddAuthorization(opt =>
{
    var authorizationRequirements = new List<IAuthorizationRequirement>()
    {
        new RolesAuthorizationRequirement(new[] { "Admin" })
    };
    var authorizationPolicy = new AuthorizationPolicy(authorizationRequirements, new []{JwtBearerDefaults.AuthenticationScheme});
    opt.AddPolicy("Admin", authorizationPolicy);
});

透過Policy的方式在全域添加驗證的政策

再來只要在Controller添加Attrbute即可使用
TokenController.cs

[HttpGet]
[Authorize(policy: "Admin", AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
public async Task<string> Get()
{
     return "Hello World";
}

上一篇
[Day26] 驗證 Authentication - 3
下一篇
[Day28] 授權 - Authorized - 2
系列文
擁抱 .Net Core30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言