(23/30) Everyone learns Blazor together: ASP.NET Core Identity(3)

(23/30) Everyone learns Blazor together: ASP.NET Core Identity(3)

We mentioned earlier that `UserAuthentication()` and `UserAuthorization()`. The difference between the two is that the former is used to verify who the login person is, and the latter determines what the login person can do.

最后更新 12/23/2021 10:19 PM
StrayaWorker
预计阅读 5 分钟
分类
Blazor
专题
Learn the Blazor series together
标签
.NET C# ASP.NET Core Blazor

前面有说到UserAuthentication()UserAuthorization(),这两个的差别在于:前者用于验证登录者是谁,后者则决定登录者可以做什么。

举例来说,一个员工要登录员工系统,他必须输入账号(如员工 ID、姓名或是 email)、密码,系统才能知道是谁登录了,这就是Authentication(验证),处理Authentication 的方式有CookieToken第三方验证(OAuth 或API-token)OpenIdSAML

而当员工登录系统后,一般员工通常不会有跨部门或是管理权限,他只能看到他自己或所属部门的信息,例如生产部员工看不到会计部的财务,不过会计部为了计算成本却看得到生产部的原料价格,这就是Authorization (授权)

在决定登录者可以做什么前,必须先知道登录者是谁,所以UserAuthentication()必须放在UserAuthorization()前面。

ASP.NET Core Identity 使用的是基于Claim 的验证,要了解Claim,必须先了解ClaimClaimsIdentityClaimsPrincipal 是什么。

Claim 就是关于使用者的一些信息,Claim TypeClaim Value(可以不用给)就组成一个ClaimClaim 可以是姓名电话角色Email甚至是角色等等。Authorization 就是用Claim 判断使用者有无授权。

new System.Security.Claims.Claim(ClaimTypes.Role, role.Name)

ClaimsIdentity 则是多个Claim 的集合,像是驾照上面记录了姓名生日电话驾照就是一个ClaimsIdentity

ClaimsPrincipal 是多个ClaimsIdentity 的集合,台湾人都有身分证跟健保卡,有些人还有驾照,身分证、健保卡跟驾照都是ClaimsIdentity,持有它们的人就是ClaimsPrincipal

而每一个HTTP request 都会产生HttpContext 对象,该对象就存有目前request 的信息,其下可以找到一个类型为ClaimsPrincipal 的 Property 名为User,这个 Property 就是由UseAuthentication()引入的Authentication Middleware 产生的。

登录机制可以用Cookie 或是JWT 实现,但Authentication Middleware 怎么知道要用哪个方法产生User Property?那就要看Authentication Scheme 跟Authentication Handlers。

Authentication Handlers

Authentication Handlers 就是处理验证的方式,ASP.NET Core Identity 可以调用AuthenticateAsync()API 去验证使用者已登录,如验证失败就调用ChallengeAsync()将使用者导回登录页面,如授权失败则用ForbidAsync()禁止使用者访问,当然也可以自己实现这些行为。下面例子中用了JWTCookie 的验证方式,如果用了前者,就必须验证JWT token 并产生ClaimsPrincipal 回传到HttpContext.User 中;使用后者则会检查当前requestcookie并产生ClaimsPrincipal

builder.Services.AddAuthentication()
	.AddJwtBearer()
	.AddCookie();

Authentication Scheme

用了任何一种方式注册Authentication Handlers 就称为Authentication Scheme,每个Authentication Scheme 都有一个独特的名字以识别,且可以自己设定Authentication Handlers,下面的程序结果跟上面会是一样,因为它们都有预设的Scheme Name。

builder.Services.AddAuthentication()
    .AddJwtBearer("Bearer")
    .AddCookie("Cookies");

Blazor Authentication

Blazor 用的验证方式跟ASP.NET Core 一样,不过Blazor WebAssemblyBlazor Server 又有不同,前者的验证就像任何前端网站一样可以被绕过,因为使用者一端的程序可以被使用者改动,因此发送数据的API 端一定也需要验证;后者则可用内建的AuthenticationStateProvider 取得前面说的HttpContext.User,笔者此前就是自己继承并重写这项Service 实现JWT 验证的。

AuthenticationStateProvider 就是昨天说到的<AuthorizeView><CascadingAuthenticationState>可以取得当前验证状态的原因,但如果没有要重写预设验证机制的话,建议不要自己在Component 注入一个AuthenticationStateProvider 出来,直接使用的缺点很明显,若当前request 的验证状态有改动,因为你改动了这个Component 的验证机制,该Component 就不会被告知。

可以看到下图,ApiAuthenticationStateProvider继承了AuthenticationStateProvider,并重写了Task<AuthenticationState>,这个 Property 可以取得当前的验证状态,MarkUserAsAuthenticated()MarkUserAsLoggedOut()则是笔者自己写的方法用以标示使用者通过验证及注销系统,NotifyAuthenticationStateChanged()顾名思义会通知各个 Component 当前验证状态,这就是自己继承并重写的案例。

下图则是在 Component 取得当前requestHttpContext.UserClaims 的作法,不过这里是先利用服务取得User 再取得其下Claims,其实是多此一举了。

如果只是要取得HttpContext.User,只要如下图般就可以了,因为 Task<AuthenticationState>会以[CascadingParameter]的方式层层传递下去。

** Quotes: **

  1. Introduction to Authentication in ASP.NET Core
  2. ASP.NET Core Blazor authentication and authorization

** Note: The code in this article is refactored through. NET 6 + Visual Studio 2022. You can click on the original link to compare and learn the refactored code. Thank you for reading and support the original author **

Keep Exploring

延伸阅读

更多文章
同分类 / 同标签 12/25/2021

(29/30) Everyone learn Blazor together: Blazor unit testing

Probably the most boring process of developing a system is to solve bugs, especially the error of trying to value null objects (`Object reference not set to an instance of an object.`). This should be the most common problem that most people encounter when they first step into the programming field. In order to relieve themselves from the boring process of solving bugs, this article introduces 'unit testing'.

继续阅读
同分类 / 同标签 12/25/2021

(28/30) Everyone learns Blazor together: Policy-based authorization

It was mentioned before that 'ASP.NET Core Identity' uses 'Claim' based authentication. In fact,'ASP.NET Core Identity' has different types of authorization methods, the simplest are 'login authorization','role authorization', and 'Claim authorization', but all of the above are implemented in one way: 'Policy-based authorization'.

继续阅读