前面有说到UserAuthentication()
跟UserAuthorization()
,这两个的差别在於:前者用於验证登入者是谁,後者则决定登入者可以做什麽。
举例来说,一个员工要登入员工系统,他必须输入帐号(如员工 ID、姓名或是 email)、密码,系统才能知道是谁登入了,这就是 Authentication(验证),处理 Authentication 的方式有 Cookie、Token、第三方验证(OAuth 或 API-token)、OpenId 及 SAML。
而当员工登入系统後,一般员工通常不会有跨部门或是管理权限,他只能看到他自己或所属部门的资讯,例如生产部员工看不到会计部的财务,不过会计部为了计算成本却看得到生产部的原料价格,这就是 Authorization (授权)。
在决定登入者可以做什麽前,必须先知道登入者是谁,所以UserAuthentication()
必须放在UserAuthorization()
前面。
ASP.NET Core Identity 使用的是基於 Claim 的验证,要了解 Claim,必须先了解 Claim、ClaimsIdentity 跟 ClaimsPrincipal 是什麽。
Claim 就是关於使用者的一些资讯,Claim Type 跟 Claim Value(可以不用给)就组成一个 Claim,Claim 可以是姓名、电话、角色、Email甚至是角色等等。Authorization 就是用 Claim 判断使用者有无授权。
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 就是处理验证的方式,ASP.NET Core Identity 可以呼叫AuthenticateAsync()
API 去验证使用者已登入,如验证失败就呼叫ChallengeAsync()
将使用者导回登入页面,如授权失败则用ForbidAsync()
禁止使用者访问,当然也可以自己实作这些行为。下面例子中用了 JWT 跟 Cookie 的验证方式,如果用了前者,就必须验证 JWT token 并产生 ClaimsPrincipal 回传到 HttpContext.User 中;使用後者则会检查当前 request 的 cookie并产生 ClaimsPrincipal。
services.AddAuthentication()
.AddJwtBearer()
.AddCookie();
用了任何一种方式注册 Authentication Handlers 就称为 Authentication Scheme,每个 Authentication Scheme 都有一个独特的名字以识别,且可以自己设定 Authentication Handlers,下面的程序结果跟上面会是一样,因为它们都有预设的 Scheme Name。
services.AddAuthentication()
.AddJwtBearer("Bearer")
.AddCookie("Cookies");
Blazor 用的验证方式跟 ASP.NET Core 一样,不过 Blazor WebAssembly 跟 Blazor 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 取得当前 request 的 HttpContext.User 及 Claims 的作法,不过这里是先利用服务取得 User 再取得其下 Claims,其实是多此一举了。
如果只是要取得 HttpContext.User,只要如下图般就可以了,因为 Task<AuthenticationState>
会以[CascadingParameter]
的方式层层传递下去。
Ref:Introduction to Authentication in ASP.NET Core
Ref:ASP.NET Core Blazor authentication and authorization
>>: EP 15: The Button of item in ListView binds Command to ViewModel
执行过後的结果大概是像这样 不过执行结果并不理想 不确定是否是训练样本不足 还是训练模型时的设定没有...
接下来的几天,要跟大家介绍一个超级重要的模组—BeautifulSoup 利用它,能轻松地找到HTM...
目的 当系统内的物件们各自沟通的情况日益严重时,建立一个负责沟通的集中所,让元件们不在「直接」,而是...
前言 参考文件 https://kubernetes.io/docs/tutorials/state...
既然空间有维度, 阵列也像是空间一样, 他是拥有维度的, 就让我们探索看看吧 二维阵列 就如同象棋棋...