前言
asp.net core2.2 用戶驗證 和授權有很詳細和特貼心的介紹,我感興趣的主要是這兩篇:
我的項目有兩類用戶:
- 微信公眾號用戶,用戶名為公眾號的openid
- 企業微信的用戶,用戶名為企業微信的userid
每類用戶中部分人員具有“Admin”角色
因為企業微信的用戶有可能同時是微信公眾號用戶,即一個人兩個名,所以需要多用戶驗證和授權。咱用代碼說話最簡潔,如下所示:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
|
public class DemoController : Controller { /// <summary> /// 企業微信用戶使用的模塊 /// </summary> /// <returns></returns> public IActionResult Work() { return Content(User.Identity.Name +User.IsInRole( "Admin" )); } /// <summary> /// 企業微信管理員使用的模塊 /// </summary> /// <returns></returns> public IActionResult WorkAdmin() { return Content(User.Identity.Name + User.IsInRole( "Admin" )); } /// <summary> /// 微信公眾號用戶使用的模塊 /// </summary> /// <returns></returns> public IActionResult Mp() { return Content(User.Identity.Name + User.IsInRole( "Admin" )); } /// <summary> /// 微信公眾號管理員使用的模塊 /// </summary> /// <returns></returns> public IActionResult MpAdmin() { return Content(User.Identity.Name + User.IsInRole( "Admin" )); } } |
下面咱一步一步實現。
第一步 改造類Startup
修改ConfigureServices方法,加入以下代碼
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
services.AddAuthentication ( "Work" //就是設置一個缺省的cookie驗證的名字,缺省的意思就是需要寫的時候可以不寫。另外很多時候用CookieAuthenticationDefaults.AuthenticationScheme,這玩意就是字符串常量“Cookies”, ) .AddCookie ( "Work" , //cookie驗證的名字,“Work”可以省略,因為是缺省名 option => { option.LoginPath = new PathString( "/Demo/WorkLogin" ); //設置驗證的路徑 option.AccessDeniedPath= new PathString( "/Demo/WorkDenied" ); //設置無授權訪問跳轉的路徑 }).AddCookie( "Mp" , option => { option.LoginPath = new PathString( "/Demo/MpLogin" ); option.AccessDeniedPath = new PathString( "/Demo/MpDenied" ); }); |
修改Configure方法,加入以下代碼
1
|
app.UseAuthentication(); |
第二步 添加驗證
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
|
public async Task WorkLogin( string returnUrl) { var claims = new List<Claim> { new Claim(ClaimTypes.Name, "UserId" ), new Claim(ClaimTypes.Role, "Admin" ) //如果是管理員 }; var claimsIdentity = new ClaimsIdentity(claims, "Work" ); //“,"Work"”可以省略,因為是缺省名 var authProperties = new AuthenticationProperties { AllowRefresh = true , //ExpiresUtc = DateTimeOffset.UtcNow.AddMinutes(10), // The time at which the authentication ticket expires. A // value set here overrides the ExpireTimeSpan option of // CookieAuthenticationOptions set with AddCookie. IsPersistent = false , //持久化保存,到底什么意思我也不太清楚,哪位兄弟清楚的話,盼解釋 //IssuedUtc = <DateTimeOffset>, // The time at which the authentication ticket was issued. RedirectUri = returnUrl ?? "/Demo/Work" }; await HttpContext.SignInAsync( "Work" , new ClaimsPrincipal(claimsIdentity), authProperties); } public IActionResult WorkDenied() { return Forbid(); } public async Task MpLogin( string returnUrl) { var claims = new List<Claim> { new Claim(ClaimTypes.Name, "OpenId" ), new Claim(ClaimTypes.Role, "Admin" ) //如果是管理員 }; var claimsIdentity = new ClaimsIdentity(claims, "Mp" ); //“,"Mp"”不能省略,因為不是缺省名 var authProperties = new AuthenticationProperties { AllowRefresh = true , IsPersistent = false , RedirectUri = returnUrl ?? "/Demo/Mp" }; await HttpContext.SignInAsync( "Mp" , new ClaimsPrincipal(claimsIdentity), authProperties); } public IActionResult MpDenied() { return Forbid(); } |
第三步 添加授權
就是在對應的Action前面加[Authorize]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
|
/// <summary> /// 企業微信用戶使用的模塊 /// </summary> /// <returns></returns> [Authorize( AuthenticationSchemes = "Work" //缺省名可以省略 )] public IActionResult Work() { return Content(User.Identity.Name + User.IsInRole( "Admin" )); } /// <summary> /// 企業微信管理員使用的模塊 /// </summary> /// <returns></returns> [Authorize(AuthenticationSchemes = "Work" ,Roles = "Admin" )] public IActionResult WorkAdmin() { return Content(User.Identity.Name + User.IsInRole( "Admin" )); } /// <summary> /// 微信公眾號用戶使用的模塊 /// </summary> /// <returns></returns> [Authorize(AuthenticationSchemes = "Mp" )] public IActionResult Mp() { return Content(User.Identity.Name + User.IsInRole( "Admin" )); } /// <summary> /// 微信公眾號管理員使用的模塊 /// </summary> /// <returns></returns> [Authorize(AuthenticationSchemes = "Mp" ,Roles = "Admin" )] public IActionResult MpAdmin() { return Content(User.Identity.Name + User.IsInRole( "Admin" )); } |
Ctrl+F5運行,截屏如下:
![]() |
最后,講講碰到的坑和求助
坑
一開始的驗證的代碼如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
public async Task<IActionResult> Login( string returnUrl) { var claims = new List<Claim> { new Claim(ClaimTypes.Name, "UserId" ), new Claim(ClaimTypes.Role, "Admin" ) //如果是管理員 }; var claimsIdentity = new ClaimsIdentity(claims, "Work" ); //“,"Work"”可以省略,因為是缺省名 var authProperties = new AuthenticationProperties { //AllowRefresh = true, //IsPersistent = false, //RedirectUri }; await HttpContext.SignInAsync( "Work" , new ClaimsPrincipal(claimsIdentity), authProperties); return Content( "OK" ); } |
- 返回類型為Task<IActionResult> ,因為懶得寫View,順手寫了句return Content("OK");
- 從網站復制過來代碼,AuthenticationProperties沒有設置任何內容
運行起來以后不停的調用login,百度了半天,改了各種代碼,最后把return Content("OK");
改成return RedirectToAction("Index");
一切OK!
揣摩原因可能是當 return Content("OK");
時,自動調用AuthenticationProperties的RedirectUri,而RedirectUri為空時,自動調用自己。也不知道對不對。
這時候重視起RedirectUri,本來就要返回到returnUrl,是不是給RedirectUri賦值returnUrl就能自動跳轉?
確實,return Content("OK");
時候自動跳轉了,return RedirectToAction("Index");
無效。
最后把Task<IActionResult>
改成Task ,把return ...刪除,一切完美!(弱弱問一句,是不是原來就應該這樣寫?我一直在走彎路?)
求助
User有屬性Identities,看起來可以有多個Identity,如何有?
總結
以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對服務器之家的支持。
原文鏈接:https://www.cnblogs.com/catzhou/p/10243069.html