緣起
該問題來自於ABP Framework 研習社
的Avatar
,聊天記錄和文章已經和本人溝通過了,發這篇文章是因為今天他升級ABP 4.4
不小心寫出了點問題找到我,我才想可以把這個事寫一下。老哥在群里提問ABP如何走角色授權,當時看到這個問題並沒有在意因為ABP默認只是擴展了策略授權,角色授權直接走微軟的就可以了。
但是:當我看到這個老哥的role驗證的時候,我的第一直覺是這個人是個憨憨,怎么可以這樣寫角色授權,官方明明提供了。
后面這位老哥發出了他的Jwt解析,成功引起了我的注意,他說他用角色授權一直不通過,無奈才用了上面的方案
當時群里很多大佬都在提出解決方案,當時我也覺得這個應該可以授權成功,但是我還是抱有丟丟的懷疑,我覺得去幫這個老哥解決這個問題。
解密
帶着疑惑我開始一探究竟,首先官方提供了IsInRole
方法來驗證角色是否有權限,然后根據IAuthorizationRequirement
引用我找到了RolesAuthorizationRequirement
,
代碼里已經很明顯了。
請注意下面這個RoleClaimType
,微軟要求我們的角色key是"http://schemas.microsoft.com/ws/2008/06/identity/claims/role"
而這個老哥用的是Role
,這就直接找到問題原因了。
public virtual bool IsInRole(string role)
{
for (int index = 0; index < this._identities.Count; ++index)
{
if (this._identities[index] != null && this._identities[index].HasClaim(this._identities[index].RoleClaimType, role))
return true;
}
return false;
}
private string _roleClaimType = "http://schemas.microsoft.com/ws/2008/06/identity/claims/role";
驗證設想
我將我的猜想發給這個老哥,讓他進行實驗,實驗證明我的猜想對了,接下來就是解決問題了,他的這個token是授權服務器頒發的,授權服務器頒發下來key就是role
,但是微軟的RolesAuthorizationRequirement
要求你必須是"http://schemas.microsoft.com/ws/2008/06/identity/claims/role"
.
安全落地
接下來就是給老哥出方案了,雖然老哥的基礎有點讓我懵圈了但是這不是問題!
我們在認證中間和和授權中間件加入如下代碼,針對Role
進行替換。
app.Use(async (ctx, next) =>
{
var currentPrincipalAccessor = ctx.RequestServices.GetRequiredService<IHttpContextAccessor>();
var map = new Dictionary<string, string>()
{
{ "role", ClaimTypes.Role },
};
var mapClaims = currentPrincipalAccessor.HttpContext.User.Claims.Where(p => map.Keys.Contains(p.Type)).ToList();
currentPrincipalAccessor.HttpContext.User.AddIdentity(new ClaimsIdentity(mapClaims.Select(p =>
new Claim(map[p.Type], p.Value, p.ValueType, p.Issuer))
));
await next();
});
反思
ABP框架值得學習,但是.Net Core官方文檔也要記得經常去看一下鞏固復習。不過這個地方也應該有其他更好的解決方案,希望大佬如果有更好的方案給我留言蟹蟹!
聯系作者:加群:867095512 @MrChuJiu
非常歡迎各位針對日常開發中使用ABP遇到的疑難雜症找我提問(ps:我不一定能解決,哈哈哈)。