| | |
| | | public class AppSmsCodeService { |
| | | |
| | | private static final String LOGIN_CODE_CACHE_PREFIX = "app:sms:login:"; |
| | | private static final String REGISTER_CODE_CACHE_PREFIX = "app:sms:register:"; |
| | | |
| | | private final StringRedisTemplate stringRedisTemplate; |
| | | private final AppSmsSender appSmsSender; |
| | |
| | | * 生成并发送登录验证码,同时写入缓存。 |
| | | */ |
| | | public AppSmsCodeSendResponse createLoginCode(String phone) { |
| | | String code = generateCode(); |
| | | stringRedisTemplate.opsForValue().set( |
| | | buildCacheKey(phone), |
| | | code, |
| | | appSmsAuthProperties.getExpireSeconds(), |
| | | TimeUnit.SECONDS |
| | | ); |
| | | appSmsSender.sendLoginCode(phone, code); |
| | | return new AppSmsCodeSendResponse(appSmsAuthProperties.getExpireSeconds()); |
| | | return createCode(phone, LOGIN_CODE_CACHE_PREFIX, true); |
| | | } |
| | | |
| | | /** |
| | | * 生成并发送注册验证码,同时写入缓存。 |
| | | */ |
| | | public AppSmsCodeSendResponse createRegisterCode(String phone) { |
| | | return createCode(phone, REGISTER_CODE_CACHE_PREFIX, false); |
| | | } |
| | | |
| | | /** |
| | | * 校验登录验证码,成功后销毁缓存中的一次性验证码。 |
| | | */ |
| | | public void validateLoginCode(String phone, String code) { |
| | | validateCode(phone, code, LOGIN_CODE_CACHE_PREFIX); |
| | | } |
| | | |
| | | /** |
| | | * 校验注册验证码,成功后销毁缓存中的一次性验证码。 |
| | | */ |
| | | public void validateRegisterCode(String phone, String code) { |
| | | validateCode(phone, code, REGISTER_CODE_CACHE_PREFIX); |
| | | } |
| | | |
| | | /** |
| | | * 统一生成指定场景的验证码并写入缓存。 |
| | | */ |
| | | private AppSmsCodeSendResponse createCode(String phone, String cachePrefix, boolean loginScene) { |
| | | String code = generateCode(); |
| | | stringRedisTemplate.opsForValue().set( |
| | | buildCacheKey(cachePrefix, phone), |
| | | code, |
| | | appSmsAuthProperties.getExpireSeconds(), |
| | | TimeUnit.SECONDS |
| | | ); |
| | | if (loginScene) { |
| | | appSmsSender.sendLoginCode(phone, code); |
| | | } else { |
| | | appSmsSender.sendRegisterCode(phone, code); |
| | | } |
| | | return new AppSmsCodeSendResponse(appSmsAuthProperties.getExpireSeconds()); |
| | | } |
| | | |
| | | /** |
| | | * 统一校验指定场景的验证码并执行一次性销毁。 |
| | | */ |
| | | private void validateCode(String phone, String code, String cachePrefix) { |
| | | if (matchesDebugCode(code)) { |
| | | // 开发环境允许固定验证码直通,便于前后端联调。 |
| | | return; |
| | | } |
| | | String cacheKey = buildCacheKey(phone); |
| | | String cacheKey = buildCacheKey(cachePrefix, phone); |
| | | String cachedCode = stringRedisTemplate.opsForValue().get(cacheKey); |
| | | if (cachedCode == null || cachedCode.trim().isEmpty()) { |
| | | throw new IllegalArgumentException("验证码已失效,请重新获取"); |
| | |
| | | /** |
| | | * 构造手机号维度的验证码缓存 key。 |
| | | */ |
| | | private String buildCacheKey(String phone) { |
| | | return LOGIN_CODE_CACHE_PREFIX + phone; |
| | | private String buildCacheKey(String cachePrefix, String phone) { |
| | | return cachePrefix + phone; |
| | | } |
| | | } |