ABP vNext 拓展短信授权登陆

今天,准备在ABP vNext上拓展一下短信登录,流程很简单:用户请求发送验证码接口,后台生成验证码,然后发送到用户手机,用户收到验证码,使用拓展授权方式SMSGrantType获取令牌,完成授权。

首先,关于验证码生成,为了避免生成存储到本地再校验一般采用TOTP加密算法,它是基于时间的一次性密码生成算法,由 RFC 6238 定义。和基于事件的一次性密码生成算法不同 HOTP,TOTP 是基于时间的,在有效时间过后,针对同一用户所生成的验证码将会发生改变。

AspNetCore已经在其TOTP- (2FA) 双因素身份验证 里借助Rfc6238AuthenticationService实现了加密,我去翻了一遍源码,大概调用流程如下:

实现原理 => 加密实现 => 加密调用 => 认证调用 => 使用示例

然后,我们可以借助这个加密算法来进行短信验证码生成,通过拓展IDS4的grant_type来做一个SMSGrantType的授权方式。

第一步,生成验证码

 1 public class SmsService : ApplicationService, ISmsService
 2 {
 3       private readonly UserManager<Volo.Abp.Identity.IdentityUser> UserManager;
 4       public SmsService(
 5           IdentityUserManager identityUserManager,
 6           UserManager<Volo.Abp.Identity.IdentityUser> userManager)
 7       {
 8            UserManager = userManager;
 9       }
10 }
11     
12 // 生成验证码
13 protected async Task<string> GetVerificationCodeAsync(
14     Volo.Abp.Identity.IdentityUser user, string selectedProvider = "Phone")
15 {
16             var code = await UserManager.GenerateTwoFactorTokenAsync(user, selectedProvider);
17 
18             Check.NotNull(code, nameof(code));
19 
20             return code;
21         }
22 }

 

第二步,HttpApi.Host 层拓展自定义授权模式

 1 public class ExtensionGrantTypes
 2  {
 3         public const string SMSGrantType = "SMSGrantType";
 4  }
 5 
 6 public class SMSGrantValidator : IExtensionGrantValidator
 7  {
 8         public string GrantType => ExtensionGrantTypes.SMSGrantType;
 9         private readonly UserManager<Volo.Abp.Identity.IdentityUser> UserManager;
10         private readonly IdentityUserManager IdentityUserManager;
11 
12         public SMSGrantValidator(
13             UserManager<Volo.Abp.Identity.IdentityUser> userManager,
14             IdentityUserManager identityUserManager)
15         {
16             UserManager = userManager;
17             IdentityUserManager = identityUserManager;
18         }
19 
20         public Task ValidateAsync(ExtensionGrantValidationContext context)
21         {
22             var smsCode = context.Request.Raw.Get("smsCode");
23             var phoneNumber = context.Request.Raw.Get("phoneNumber");
24 
25             if (string.IsNullOrEmpty(smsCode) || string.IsNullOrEmpty(phoneNumber))
26             {
27                 context.Result = new         GrantValidationResult(TokenRequestErrors.InvalidGrant);
28             }
29             // 在此实现自己的验证逻辑…
30             return Task.FromResult(0);
31         }
32  }

第三步,XXXHttpApiHostModule注册校验类

 1 // 在httpapi.host的module文件内添加自定义授权模式
 2 public override void PreConfigureServices(ServiceConfigurationContext context)
 3 {
 4             context.Services.PreConfigure<IIdentityServerBuilder>(
 5                 builder =>
 6                 {
 7                     // 添加自定义授权模式
 8                     builder.AddExtensionGrantValidator<SMSGrantValidator>();
 9                 }
10             );
11  }

第四步,Domain添加Client数据种子(同时DbMigratorappsettings添加配置)

 1 var testClientId = configurationSection["Test_App:ClientId"];
 2  if (!testClientId.IsNullOrWhiteSpace())
 3  {
 4       await CreateClientAsync(
 5            name: testClientId,
 6            scopes: commonScopes,
 7            grantTypes: new[] { "password", "client_credentials", ExtensionGrantTypes.SMSGrantType },
 8            secret: (configurationSection["Test_App:ClientSecret"] ?? "123456").Sha256()
 9       );
10  }

第五步,愉快的使用(测试号码是假的不要来骚扰我......[狗头].jpg)

猜你喜欢

转载自blog.csdn.net/csdn102347501/article/details/116524580