前言
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