.net core 認證與授權(三)


前言

在寫三上是在一的基礎上寫的,所以有沒有看過二是沒得關系的,在一中介紹了認證與授權,但是沒有去介紹拿到證書后怎樣去驗證授權。
概念性東西:在這套機制中,把這個權限認證呢,稱作為policy。這個policy是怎么樣的過程呢?
就像我前面說的,證書也認證了,policy做的是檢查你的證書中是否符合我心中的標准。
比如說,我有一個接口實行的是駕駛證檢查。結果你只有一張學生證,你不能那一張學生證當駕駛證去開車吧,肯定就不讓你訪問啊。
也許還有點迷糊,請看正文。正文皆為個人理解,如有錯誤,請指正。

正文

請看下面的:

services.AddAuthorization(config=> {
	var defaultAuthBuilder = new AuthorizationPolicyBuilder();
	var defaultPolicy = defaultAuthBuilder.RequireAuthenticatedUser().Build();
	config.DefaultPolicy = defaultPolicy;
});

這時候就是在配置授權了。
defaultAuthBuilder.RequireAuthenticatedUser().Build() 中,RequireAuthenticatedUser去要求用戶必須經過認證的,也就是不允許匿名用戶,這個很好理解。
設置默認的策略認證就是這個了。
這時候我訪問:
https://localhost:44350/Home/Secret
是正常的,因為我本來就是認證過的。
然后我改了一下:

services.AddAuthorization(config=> {
	var defaultAuthBuilder = new AuthorizationPolicyBuilder();
	var defaultPolicy = defaultAuthBuilder.RequireAuthenticatedUser().RequireClaim(ClaimTypes.Country).Build();
	config.DefaultPolicy = defaultPolicy;
});

和上面不同的,我加了RequireClaim(ClaimTypes.Country),我要求起碼有一個證書你要有國家。

我再次貼下證書的代碼,在.net core 認證與授權(一)中也有。

var SchoolClaims = new List<Claim>()
{
	new Claim(ClaimTypes.Name,"Jack"),
	new Claim(ClaimTypes.Email,"Jack@fmail.com")
};

var LicensClaims = new List<Claim>()
{
	new Claim(ClaimTypes.Name,"Jack.li"),
	new Claim(ClaimTypes.Email,"Jack@fmail.com"),
	new Claim("begin","2000.10.1")
};
var SchoolIdentity = new ClaimsIdentity(SchoolClaims,"Student Identity");
var CarManagerIdentity = new ClaimsIdentity(LicensClaims, "Licens Identity");
var userPrincipal = new ClaimsPrincipal(new[] { SchoolIdentity, CarManagerIdentity });

HttpContext.SignInAsync("CookieAuth", userPrincipal);
return RedirectToAction("Index");

在兩個證書中,都沒得國家。
然后訪問:
https://localhost:44350/Home/Secret

自動跳轉到了一個授權沒有通過的網站,恰巧我沒有寫這個網頁,姑且着就是沒有通過的意思。
然后我再一個證書中添加了一個:

new Claim(ClaimTypes.Country,"china")

這樣我又成功了。
好的,這是默認的策略,那么如何自定義呢?

config.AddPolicy("Claim.Country", policyBuilder =>
{
	policyBuilder.RequireClaim(ClaimTypes.Country);
});

上面我添加了一個策略,名字叫做Claim.Country.
因為不是默認,所以要[Authorize(Policy = "Claim.Country")]
policyBuilder 相當於上面的var defaultAuthBuilder = new AuthorizationPolicyBuilder();。
然后里面去設置起碼有一個證書中要有國家。
policyBuilder 默認有一些限制可以使用,那么如何自己來定義呢?究竟是一種什么模式呢?

public class CustomRequireClaim:IAuthorizationRequirement
{
	public CustomRequireClaim(string ClainType)
	{
		this.ClainType = ClainType;
	}

	public string ClainType{ get; }
}

public class CustomRequireClaimHandler : AuthorizationHandler<CustomRequireClaim>
{
	protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, CustomRequireClaim requirement)
	{
		var hasClaim = context.User.Claims.Any(u=>u.Type== requirement.ClainType);
		if (hasClaim)
		{
			context.Succeed(requirement);

		}
		return Task.CompletedTask;
	}
}

CustomRequireClaim 是什么呢?繼承IAuthorizationRequirement。其實是模擬生活中的什么呢,比如說你要向批發商進一匹東西,有一些需求,比如說蘋果要通紅的,你就可以在這里填寫。
CustomRequireClaimHandler 繼承自AuthorizationHandler ,批發商帶一批貨(程序也就是用戶帶着證書來了),你可以這個檢查合格不合格,拿着你的需求表對照。
那么注冊進入:

config.AddPolicy("Claim.Country", policyBuilder =>
{
	policyBuilder.AddRequirements(new CustomRequireClaim(ClaimTypes.Country));
});

同樣需要:

services.AddScoped<IAuthorizationHandler, CustomRequireClaimHandler>();

這里就有疑問了,你這個policyBuilder.AddRequirements(new CustomRequireClaim(ClaimTypes.Country));就能調用到CustomRequireClaimHandler。
這個疑問簡單化就是,你有一個需求,就只調用到檢查類?
其實是在軟件設計中,有這樣一種套路,就是根據實體類,能自動調用執行類,這是一種設計模式。其實也能理解,就是呢,比如說公司有一張請假單,都標明是請假單了,肯定交給部門經理啊,AuthorizationHandler
<CustomRequireClaim>就是標記,處理CustomRequireClaim的。
在里面其實只有IAuthorizationHandler,但是根據CustomRequireClaim能實例出CustomRequireClaimHandler。所以也需要加上:

services.AddScoped<IAuthorizationHandler, CustomRequireClaimHandler>();

同樣,回過頭來,看下面的。

policyBuilder.RequireClaim(ClaimTypes.Country);

如何做到直接點出來,不用這種add的方式呢?也就是說我也想實現這樣的。

policyBuilder.RequireCustomClaim(ClaimTypes.Country);

我要能RequireCustomClaim然后可以調用到我給的限制.
下面是使用擴展的方式實現:

public static class AuthorizationPolicyBuilderExtensions
{
	public static AuthorizationPolicyBuilder RequireCustomClaim(this AuthorizationPolicyBuilder policyBuilder,string claimType)
	{
		policyBuilder.AddRequirements(new CustomRequireClaim(claimType));
		return policyBuilder;
	}
}

擴展一下AuthorizationPolicyBuilder 就可以,這樣方便復用性。
以前的時候我們這樣寫:

[Authorize(Roles  = "admin")]

在這里就會檢查我們的證書中是否有Roles 為admin。
然后呢,我們同樣可以通過policy去實現。

config.AddPolicy("Claim.Role", policyBuilder =>
{
	policyBuilder.RequireClaim(ClaimTypes.Role, "admin");
});

限制需要admin也是可以的,然后[Authorize(Policy= "Claim.Role")]。
具體看自己需求。

總結

后續繼續寫自己對認證授權理解。以上均為個人理解,如有誤差,請指正。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM