Blazor學習記錄_11.身份認證與授權

26.Blazor 身份認證與授權

26.0 基礎背景知識 OAuth 2.0 和 OpenID Connect

這兩個協議是用於授權和認證的使用最廣泛的的協議。OAuth 2.0 用於授權,OpenID Connect 用於認證。OpenID Connect 是 OAuth 2.0 協議之上的標識層,以使 OAuth 適用於認證的用例。
認證(Authentication)是確保通信實體是其所聲稱的實體。
授權(Authorization)是驗證通信實體是否有權訪問資源的過程。
換言之,認證關注的是你是誰,授權關注的是你有什麼權限。

有兩種 OAuth 2.0 授權流程最爲常見:服務端應用程序的授權碼流程和基於瀏覽器的應用程序的隱式流程。

26.0.2 OpenID Connect

OpenID Connect 是在 OAuth2.0 協議之上的標識層。它拓展了 OAuth2.0,使得認證方式標準化。

OAuth 不會立即提供用戶身份,而是會提供用於授權的訪問令牌。 OpenID Connect 使客戶端能夠通過認證來識別用戶,其中,認證在授權服務端執行。它是這樣實現的:在向授權服務端發起用戶登錄和授權告知的請求時,定義一個名叫openid的授權範圍。在告知授權服務器需要使用 OpenID Connect 時,openid是必須存在的範圍。

客戶端發起的用於 OpenID Connect 認證請求 URI 會是如下的形式:

https://accounts.google.com/o/oauth2/v2/auth?
 response_type=code&
 client_id=your_client_id&
 scope=openid%20contacts&
 redirect_uri=https%3A//oauth2.example.com/code

該請求的返回結果是客戶端可以用來交換訪問令牌和 ID 令牌的授權碼。如果 OAuth 流程是隱式的,那麼授權服務端將直接返回訪問令牌和 ID 令牌。

ID 令牌是 JWT,或者又稱 JSON Web Token。JWT 是一個編碼令牌,它由三部分組成:頭部,有效負載和簽名。在獲得了 ID 令牌後,客戶端可以將其解碼,並且得到被編碼在有效負載中的用戶信息,如以下例子所示:

{
  "iss": "https://accounts.google.com",
  "sub": "10965150351106250715113082368",
  "email": "[email protected]",
  "iat": 1516239022,
  "exp": 1516242922
}

26.0.3 聲明(Claim)

ID 令牌的有效負載包括了一些被稱作聲明的域。基本的聲明有:

iss:令牌發佈者

sub:用戶的唯一標識符

email:用戶的郵箱

iat:用 Unix 時間表示的令牌發佈時間

exp:Unix 時間表示的令牌到期時間

然而,聲明不僅限於上述這些域。由授權服務器對聲明進行編碼。客戶端可以用這些信息來認證用戶。

如果客戶端需要更多的用戶信息,客戶端可以指定標準的 OpenID Connect 範圍,來告知授權服務端將所需信息包括在 ID 令牌的有效負載中。這些範圍包括個人主頁(profile)、郵箱(email)、地址(address)和電話(phone)。

26.1 Microsoft 標識平臺中的 OAuth 2.0 和 OpenID Connect (OIDC)

26.1.1 身份驗證和授權交換通常涉及四方

身份驗證和授權交換通常涉及四方。 這些交換通常稱爲身份驗證流。

  1. Authorazition Server
  2. Resource Server
  3. Resource Owner
  4. Client

26.1.2 持有者令牌 (Bearer Token 或叫不記名令牌)

身份驗證流中的各方使用持有者令牌來確保、確認和驗證某個主體(用戶、主機或服務)並授予或拒絕對受保護資源的訪問權限(授權)。 Microsoft 標識平臺中的持有者令牌已格式化爲 JSON Web 令牌 (JWT)。

標識平臺使用三種類型的持有者令牌作爲安全令牌:

  1. 訪問令牌 - 訪問令牌由授權服務器頒發給客戶端應用程序。 客戶端將訪問令牌傳遞給資源服務器。 訪問令牌包含授權服務器授予客戶端的權限。
  2. ID 令牌 - ID 令牌由授權服務器頒發給客戶端應用程序。 客戶端在登錄用戶時使用 ID 令牌,可獲取有關用戶的基本信息。
  3. 刷新令牌 - 客戶端使用刷新令牌(簡稱 RT)從授權服務器請求新的訪問令牌和 ID 令牌。 代碼應將刷新令牌及其字符串內容視爲敏感數據,因爲它們僅供授權服務器使用。

26.1.3 應用註冊

客戶端應用需要一種方法來信任 Microsoft 標識平臺頒發給自己的安全令牌。 建立信任的第一步是註冊應用。 當你註冊應用時,標識平臺會自動爲其分配一些值,而其他值則由你根據應用程序的類型進行配置。
兩個最常引用的應用註冊設置爲:

  1. 應用程序(客戶端)ID - 也稱爲“應用程序 ID”和“客戶端 ID”,此值由標識平臺分配給你的應用。 客戶端 ID 可對標識平臺中的應用進行唯一標識,包含在平臺頒發的安全令牌中。
  2. 重定向 URI - 授權服務器使用重定向 URI,將資源所有者的用戶代理(Web 瀏覽器、移動應用)定向到另一個目標(在完成其交互後)。 例如,在最終用戶通過授權服務器進行身份驗證之後。 並非所有客戶端類型都使用重定向 URI。
    應用的註冊還保存有關身份驗證和授權終結點的信息,這些信息可以在代碼中用於獲取 ID 和訪問令牌。

26.1.4 終結點(理解爲就是訪問地址)

符合標準的實現提供身份驗證和授權服務。 符合標準的授權服務器(例如標識平臺)提供一組 HTTP 終結點,供身份驗證流中的各方用於執行流。

當你註冊或配置應用時,系統會自動生成應用的終結點 URI。 在應用的代碼中使用的終結點取決於應用程序的類型以及應支持的標識(帳戶類型)。

兩個常用的終結點是授權終結點和令牌終結點。 下面是 authorize 和 token 終結點的示例:

# 1.授權終結點-由客戶端用於從資源所有者獲取授權
https://login.microsoftonline.com/<issuer>/oauth2/v2.0/authorize
# 2.令牌終結點-由客戶端用於交換訪問令牌的授權授予或刷新令牌
https://login.microsoftonline.com/<issuer>/oauth2/v2.0/token

26.2 框架中的IIdentity和IPrincipal

26.2.1 接口定義

命名空間:System.Security.Principal

  • IIdentity 接口有三個屬性:
//認證類型,如:微信、支付寶、驗證碼、jwt、windows等
AuthenticationType,
IsAuthenticated,//是否已經通過認證
Name //認證用戶名稱
  • IPrincipal(已鑑別用戶 委託人 負責人)
    包括一個屬性,一個方法
IIdentity? Identity{get;}
//是否屬於指定角色
bool IsInRole(string role);

26.2.1 官方庫中的三個實現

  1. windows 系統實現
var identity = new WindowsIdentity.GetCurrent();
IPrincipal principal = new WindowsPrincipal(identity);
//程序中就可以使用:
Thread.CurrentPrincipal = principal;
//或 如果是asp.net MVC 應用程序
HttpContext.User = principal;
  1. GenericIdentity 通用實現,較簡單
var identity = new GenericIdentity("張三");
IPrincipal principal = new GenericPrincipal(identity,new[]{"admin","role2"});

3. 基於聲明的 ClaimsIdentity (重要)
可以通過AddClaims(IEnumberable<Claim?>)方法自定義擴展內部信息

var identity = new CliamsIdentity("微信");
identity.AddClaim(new(ClaimTypes.Email,"[email protected]"));
identity.AddClaim(new(ClaimTypes.Name,"張三"));
identity.AddClaim(new(ClaimTypes.Role,"Admin"));
identity.AddClaim(new(ClaimTypes.Role,"Users"));
//自定義增加需要的聲明鍵值對
identity.AddClaim("TypeKey","TypeValue"));
IPrincipal principal = new GenericPrincipal(identity,new[]{"admin","role2"});
//判斷當前用戶是認證或說登錄
bool isAuthenticated = principal.Identity.IsAuthenticated;
//判斷當前用戶是否擁有某角色
bool isInRole = principal.Identity.IsInRole("Admin");

26.3 Microsoft.Identity 詳解

26.3.1 引入包

核心包:Microsoft.Extensions.Identity.Core
倉儲抽像包:Microsoft.Extensions.Identity.Stores
倉儲EF實現包:Microsoft.AspNetCore.Identity.EntityFrameworkCore
官方UI實現包:Microsoft.AspNetCore.Identity.UI

26.3.2 添加服務

  • 1.幾個服務介紹
    builder.Services.AddMvc();
    builder.Services.AddIdentity<TUser,TRole>();

    builder.Services.AddIdentityCore<TUser>();
    或帶UI的
    builder.Services.AddDefaultIdentity<TUser>();
    TUser有官方的默認定義類型:IdentityUser Id爲GUID類型
    TRole有官方的默認定義類型:IdentityRole Id爲GUID類型
    兩者都可以由開發者繼承後進行進一步擴充
  • 2.用項目模版創建的項目中主要代碼
builder.Services.AddDefaultIdentity<IdentityUser>(options=>
options.SignIn.RequireConfirmedAccount=true)
.AddEntityFrameworkStores<ApplicationsDbContext>();
builder.Service.AddRazorPages();
//授權中間件
app.UseAuthorization();

若需擴展則數據庫上下文ApplicationsDbContext代碼如下:

public class ApplicationsDbContext:IdentityDbContext<User,Role,string>
{
    public ApplicationsDbContext(DbContextOptions options) : base(options)
    { }
    protected  override void OnModelCreating(ModelBuilder builder)
    {
        base.OnModelCreating(builder);
        builder.Entity<User>().ToTable("MyUsers");
    }
}

生成的數據庫表有:

AspNetRoleClaims
AspNetRoles
AspNetUserClaims
AspNetRoles
AspNetUsers
//後面這兩張表是有關做微信、QQ等第三方登錄即Auth2.0時用到的
AspNetUserLogins //相關第三方登錄配置
AspNetUserTokens //相關第三方登錄Token

26.4 Blazor官方身份認證與授權組件

  1. 引入Nuget包 Microstoft.AspNetCore.Components.Authorization
  2. 在_Imports.razor文件中增加全局引用
    @using Microstoft.AspNetCore.Components.Authorization
  3. 組件的使用
    該組件結合了微軟OpenId認證與授權系統
    System.Security.Principal.IIdentity
    3.1 AuthorzeRouteView 組件
<AuthorzeRouteView>
	@context?.User?.Identity?.Name
</AuthorzeRouteView>

<AuthorzeView>
<CascadingAuthenticationState>

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章