|
@@ -44,7 +44,6 @@ public class DefaultCaptchaSmsHandler implements CaptchaSmsHandler {
|
|
|
};
|
|
|
|
|
|
private final CaptchaSmsProperties properties;
|
|
|
- private final TemplateSmsHandler templateSmsHandler;
|
|
|
private final RedisTemplate<String, Object> redisTemplate;
|
|
|
|
|
|
/**
|
|
@@ -57,12 +56,43 @@ public class DefaultCaptchaSmsHandler implements CaptchaSmsHandler {
|
|
|
return "sms:token:" + mobile;
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * 获取模版短信处理器
|
|
|
+ *
|
|
|
+ * @return 模版短信处理器
|
|
|
+ */
|
|
|
+ private TemplateSmsHandler getTemplateSmsHandler() {
|
|
|
+ return ApplicationContextHolder.getBean(ApplicationContextHolder.getSafeProperty(
|
|
|
+ "platform.sms.captcha.handler", AliyunSmsHandler.class.getName()
|
|
|
+ ));
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 查找手机号测试验证码
|
|
|
+ *
|
|
|
+ * @param mobile 手机号
|
|
|
+ * @return 验证码
|
|
|
+ */
|
|
|
+ private String lookupTestingCaptcha(String mobile) {
|
|
|
+ List<Captcha> testes = ApplicationContextHolder.getSafeProperty("platform.sms.captcha.test", CAPTCHA_REFERENCE);
|
|
|
+ if (CollectionUtils.isEmpty(testes)) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ return testes.stream().filter(captcha -> Objects.equals(captcha.getMobile(), mobile)).map(Captcha::getCode)
|
|
|
+ .filter(StringUtils::nonEmpty).findFirst().orElse(null);
|
|
|
+ }
|
|
|
+
|
|
|
@Override
|
|
|
public SmsSession send(@NonNull String mobile) {
|
|
|
- String code = String.valueOf(ThreadLocalRandom.current().nextInt(100000, 1000000));
|
|
|
+ // 如果目标手机号属于测试手机号,则直接返回配置的验证码信息,否则获取真实的验证码
|
|
|
+ String test = this.lookupTestingCaptcha(mobile);
|
|
|
+ boolean testing = StringUtils.nonEmpty(test);
|
|
|
+ String code = testing ? test : String.valueOf(ThreadLocalRandom.current().nextInt(100000, 1000000));
|
|
|
Duration duration = Duration.ofSeconds(this.properties.getInterval());
|
|
|
return RedisUtils.tryLockAround("sms:interval:" + mobile, duration, () -> {
|
|
|
- this.templateSmsHandler.sendCaptcha(mobile, this.properties.getTemplate(), code);
|
|
|
+ if (!testing) {
|
|
|
+ this.getTemplateSmsHandler().sendCaptcha(mobile, this.properties.getTemplate(), code);
|
|
|
+ }
|
|
|
String key = this.key(mobile), token = StringUtils.uuid();
|
|
|
Captcha captcha = Captcha.builder().token(token).code(code).mobile(mobile).build();
|
|
|
this.redisTemplate.opsForValue().set(key, captcha, this.properties.getExpiration(), TimeUnit.SECONDS);
|
|
@@ -74,15 +104,6 @@ public class DefaultCaptchaSmsHandler implements CaptchaSmsHandler {
|
|
|
|
|
|
@Override
|
|
|
public Captcha getCaptcha(@NonNull String mobile) {
|
|
|
- // 如果目标手机号属于测试手机号,则直接返回配置的验证码信息,否则获取真实的验证码
|
|
|
- List<Captcha> testes = ApplicationContextHolder.getSafeProperty("platform.sms.captcha.test", CAPTCHA_REFERENCE);
|
|
|
- if (!CollectionUtils.isEmpty(testes)) {
|
|
|
- Captcha captcha = testes.stream().filter(test -> Objects.equals(test.getMobile(), mobile))
|
|
|
- .findFirst().orElse(null);
|
|
|
- if (captcha != null) {
|
|
|
- return captcha;
|
|
|
- }
|
|
|
- }
|
|
|
return (Captcha) this.redisTemplate.opsForValue().get(this.key(mobile));
|
|
|
}
|
|
|
|
|
@@ -96,14 +117,14 @@ public class DefaultCaptchaSmsHandler implements CaptchaSmsHandler {
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
- public boolean check(String token, @NonNull String mobile, @NonNull String code) {
|
|
|
+ public boolean check(@NonNull String token, @NonNull String mobile, @NonNull String code) {
|
|
|
Captcha captcha = this.getCaptcha(mobile);
|
|
|
- return captcha != null && (StringUtils.isEmpty(captcha.getToken()) || Objects.equals(token, captcha.getToken()))
|
|
|
+ return captcha != null && Objects.equals(token, captcha.getToken())
|
|
|
&& Objects.equals(mobile, captcha.getMobile()) && Objects.equals(code, captcha.getCode());
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
- public boolean validate(String token, @NonNull String mobile, @NonNull String code) {
|
|
|
+ public boolean validate(@NonNull String token, @NonNull String mobile, @NonNull String code) {
|
|
|
boolean available = this.check(token, mobile, code);
|
|
|
if (available) {
|
|
|
this.redisTemplate.delete(this.key(mobile));
|