鉴权/授权自定义一个身份认证Handler
Posted dotNET跨平台
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了鉴权/授权自定义一个身份认证Handler相关的知识,希望对你有一定的参考价值。
微信公众号:趣编程ACE
关注可了解.NET日常开发技巧。如需源码,请公众号留言 [源码];
上文回顾
【鉴权/授权】一步一步实现一个简易JWT鉴权自定义身份验证CustomerAuthenticationHandler使用
上篇文章我演示了如何利用.net core 里面内置的验证方案-Bearer 进行身份验证,本文通过一个简单的例子来实现自定义身份验证流程。
超清观看哦~
首先创建一个登录服务
里面有三大步骤
1//Step1: 登录接口 需要在内置容器里面依赖注入
2public interface ICustomerAuthentication
3
4 ...
5
6
7// 接口的实例
8public class CustomerAuthentication : ICustomerAuthentication
9
10 // Step2:提供一个登录方法
11 public string Login(string userName, string password)
12
13
14
15
16
17// Step3: 容器依赖注入
18builder.Services.AddSingleton<ICustomerAuthentication,CustomerAuthentication>();
登录接口实现
1// 相当于在内存里面定义一个用户对象集合 模拟从数据库查询获取用户对象 方便check
2private readonly IDictionary<string,string> users = new Dictionary<string,string>
3
4 "p1","a1",
5 "p2","a2",
6;
7// 存放token集合
8private readonly IDictionary<string,string> tokens = new Dictionary<string,string>();
9public IDictionary<string,string> Tokens =>tokens; // 实现接口 并初始化
10
11public string Login(string userName, string password)
12
13 // check 用户真实存在
14 if(!users.Any(u=>u.Key==userName && u.Value==password))
15
16 return null;
17
18 // create token 通过一个Guid 类型的数据来代替token 仅为演示
19 var token = new Guid().ToString();
20 tokens.Add(token,userName);
21 return token ;
22
创建一个自定义CustomerAuthenticationHandler类
1public class CustomerAuthenticationHandler :AuthenticationHandler<BasicAuthenticationOptions>
2
3 ...
4
其中CustomerAuthenticationHandler需要继承AuthenticationHandler接口,这个接口需要一个用于身份验证的Options配置类,所以需要定义一下BasicAuthenticationOptions 继承AuthenticationSchemeOptions
1public class BasicAuthenticationOptions :AuthenticationSchemeOptions
2
3
4
实现HandleAuthenticateAsync方法
1protected override async Task<AuthenticateResult> HandleAuthenticateAsync()
2
3 // throw new NotImplementedException();
4 if(!Request.Headers.ContainsKey("Authorization"))
5
6 return AuthenticateResult.Fail("UnAuthorized");
7
8
9 // 获取请求头里面 Authorization对应的value
10 string authenticationHeader = Request.Headers["Authorization"];
11 if(string.IsNullOrEmpty(authenticationHeader))
12
13 return AuthenticateResult.Fail("UnAuthorized");
14
15 if(!authenticationHeader.StartsWith("Bearer",StringComparison.OrdinalIgnoreCase))
16
17 return AuthenticateResult.Fail("UnAuthorized");
18
19 // 获取token
20 string token = authenticationHeader.Substring("bearer".Length).Trim();
21 if(string.IsNullOrEmpty(token))
22
23 return AuthenticateResult.Fail("UnAuthorized");
24
25
26 try
27
28 // 验证token 调用下方ValidateToken() 这个方法
29 return ValidateToken(token);
30
31 catch (System.Exception ex)
32
33 // 记录日志
34 return AuthenticateResult.Fail("UnAuthorized");
35
36
37
38private AuthenticateResult ValidateToken(string token)
39
40 var validateToken = _customerAuthentication.Tokens.FirstOrDefault(t=>t.Key ==token);
41 if(validateToken.Key is null )
42
43 return AuthenticateResult.Fail("UnAuthorized");
44
45 var claims = new List<Claim>
46
47 new Claim(ClaimTypes.Name,validateToken.Value)
48 ;
49
50 var identity = new ClaimsIdentity(claims,Scheme.Name);
51 var principle = new GenericPrincipal(identity,null);
52 var ticket = new AuthenticationTicket(principle,Scheme.Name);
53 return AuthenticateResult.Success(ticket);
54
该方法返回一个AuthenticateResult类型的对象来表示身份验证是否成功,如果成功,需要将这个票据返还给用户。
那么为啥需要票据呢?因为我们在Http传输协议下,需要保证附加在请求头或者请求参数的内容的安全性,所以需要将principal对象包裹成AuthenticationTicket对象,在后者里面我们可以增加一些安全配置。
DI中注册认证服务
1// 自定义验证 取名为一个 test 的Scheme方案
2builder.Services.AddAuthentication("test")
3 .AddScheme<BasicAuthenticationOptions,CustomerAuthenticationHandler>("test",null);
PS:本文来自社区群粉丝投稿~
以上是关于鉴权/授权自定义一个身份认证Handler的主要内容,如果未能解决你的问题,请参考以下文章
EMQX Cloud 更新:新增 Redis 和 JWT 外部认证授权