diff --git a/youlai-auth/src/main/java/com/youlai/auth/security/config/AuthorizationServerConfig.java b/youlai-auth/src/main/java/com/youlai/auth/security/config/AuthorizationServerConfig.java index 63f577cee..a520f927c 100644 --- a/youlai-auth/src/main/java/com/youlai/auth/security/config/AuthorizationServerConfig.java +++ b/youlai-auth/src/main/java/com/youlai/auth/security/config/AuthorizationServerConfig.java @@ -10,8 +10,9 @@ import com.youlai.auth.security.core.userdetails.member.MemberUserDetails; import com.youlai.auth.security.core.userdetails.member.MemberUserDetailsServiceImpl; import com.youlai.auth.security.core.userdetails.user.SysUserDetails; import com.youlai.auth.security.core.userdetails.user.SysUserDetailsServiceImpl; -import com.youlai.auth.security.extension.memeber.wechat.WechatTokenGranter; +import com.youlai.auth.security.extension.wechat.WechatTokenGranter; import com.youlai.auth.security.extension.PreAuthenticatedUserDetailsService; +import com.youlai.auth.security.extension.username.CaptchaTokenGranter; import com.youlai.common.result.Result; import com.youlai.common.result.ResultCode; import lombok.RequiredArgsConstructor; @@ -19,6 +20,7 @@ import lombok.SneakyThrows; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.io.ClassPathResource; +import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; import org.springframework.security.authentication.AuthenticationManager; @@ -54,6 +56,7 @@ public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdap private final ClientDetailsServiceImpl clientDetailsService; private final SysUserDetailsServiceImpl sysUserDetailsService; private final MemberUserDetailsServiceImpl memberUserDetailsService; + private final StringRedisTemplate stringRedisTemplate; /** * OAuth2客户端 @@ -78,10 +81,13 @@ public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdap // 添加自定义授权模式 List granterList = new ArrayList<>(Arrays.asList(endpoints.getTokenGranter())); - granterList.add(new WechatTokenGranter(endpoints.getTokenServices(), endpoints.getClientDetailsService(), endpoints.getOAuth2RequestFactory(), - authenticationManager)); - CompositeTokenGranter compositeTokenGranter = new CompositeTokenGranter(granterList); + granterList.add(new WechatTokenGranter(endpoints.getTokenServices(), endpoints.getClientDetailsService(), + endpoints.getOAuth2RequestFactory(), authenticationManager)); + granterList.add(new CaptchaTokenGranter(endpoints.getTokenServices(), endpoints.getClientDetailsService(), + endpoints.getOAuth2RequestFactory(), authenticationManager, stringRedisTemplate + )); + CompositeTokenGranter compositeTokenGranter = new CompositeTokenGranter(granterList); endpoints .authenticationManager(authenticationManager) .accessTokenConverter(jwtAccessTokenConverter()) @@ -112,21 +118,16 @@ public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdap tokenServices.setTokenEnhancer(tokenEnhancerChain); PreAuthenticatedAuthenticationProvider provider = new PreAuthenticatedAuthenticationProvider(); - provider.setPreAuthenticatedUserDetailsService(new PreAuthenticatedUserDetailsService<>(refreshTokenUserDetailsServiceMap())); + Map clientUserDetailsServiceMap = new HashMap<>(); + clientUserDetailsServiceMap.put(AuthConstants.ADMIN_CLIENT_ID, sysUserDetailsService); + clientUserDetailsServiceMap.put(AuthConstants.APP_CLIENT_ID, memberUserDetailsService); + + provider.setPreAuthenticatedUserDetailsService(new PreAuthenticatedUserDetailsService<>(clientUserDetailsServiceMap)); tokenServices.setAuthenticationManager(new ProviderManager(Arrays.asList(provider))); return tokenServices; } - - public Map refreshTokenUserDetailsServiceMap() { - Map clientUserDetailsServiceMap = new HashMap<>(); - clientUserDetailsServiceMap.put(AuthConstants.ADMIN_CLIENT_ID, sysUserDetailsService); - clientUserDetailsServiceMap.put(AuthConstants.APP_CLIENT_ID, memberUserDetailsService); - return clientUserDetailsServiceMap; - } - - /** * 使用非对称加密算法对token签名 */ diff --git a/youlai-auth/src/main/java/com/youlai/auth/security/config/WebSecurityConfig.java b/youlai-auth/src/main/java/com/youlai/auth/security/config/WebSecurityConfig.java index fdbdfab17..aec12b0e5 100644 --- a/youlai-auth/src/main/java/com/youlai/auth/security/config/WebSecurityConfig.java +++ b/youlai-auth/src/main/java/com/youlai/auth/security/config/WebSecurityConfig.java @@ -1,7 +1,7 @@ package com.youlai.auth.security.config; import cn.binarywang.wx.miniapp.api.WxMaService; -import com.youlai.auth.security.extension.memeber.wechat.WechatAuthenticationProvider; +import com.youlai.auth.security.extension.wechat.WechatAuthenticationProvider; import com.youlai.mall.ums.api.MemberFeignClient; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; diff --git a/youlai-auth/src/main/java/com/youlai/auth/security/extension/mobile/SmsCodeAuthenticationProvider.java b/youlai-auth/src/main/java/com/youlai/auth/security/extension/mobile/SmsCodeAuthenticationProvider.java new file mode 100644 index 000000000..bc56e5d32 --- /dev/null +++ b/youlai-auth/src/main/java/com/youlai/auth/security/extension/mobile/SmsCodeAuthenticationProvider.java @@ -0,0 +1,76 @@ +package com.youlai.auth.security.extension.mobile; + +import cn.binarywang.wx.miniapp.api.WxMaService; +import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult; +import cn.hutool.core.bean.BeanUtil; +import com.youlai.auth.security.core.userdetails.member.MemberUserDetailsServiceImpl; +import com.youlai.auth.security.extension.wechat.WechatAuthenticationToken; +import com.youlai.auth.security.extension.wechat.WechatUserInfo; +import com.youlai.common.result.Result; +import com.youlai.common.result.ResultCode; +import com.youlai.mall.ums.api.MemberFeignClient; +import com.youlai.mall.ums.pojo.dto.MemberAuthDTO; +import com.youlai.mall.ums.pojo.entity.UmsMember; +import lombok.Data; +import me.chanjar.weixin.common.error.WxErrorException; +import org.springframework.security.authentication.AuthenticationProvider; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UserDetailsService; + +import java.util.HashSet; + +/** + * 手机短信验证码提供者 + * + * @author xianrui + * @date 2021/9/25 + */ +@Data +public class SmsCodeAuthenticationProvider implements AuthenticationProvider { + + private UserDetailsService userDetailsService; + private WxMaService wxMaService; + private MemberFeignClient memberFeignClient; + + /** + * 微信认证 + * + * @param authentication + * @return + * @throws AuthenticationException + */ + @Override + public Authentication authenticate(Authentication authentication) throws AuthenticationException { + WechatAuthenticationToken authenticationToken = (WechatAuthenticationToken) authentication; + String code = (String) authenticationToken.getPrincipal(); + WechatUserInfo wechatUserInfo = authenticationToken.getWechatUserInfo(); + + WxMaJscode2SessionResult sessionInfo = null; + try { + sessionInfo = wxMaService.getUserService().getSessionInfo(code); + } catch (WxErrorException e) { + e.printStackTrace(); + } + String openid = sessionInfo.getOpenid(); + Result memberAuthResult = memberFeignClient.loadUserByOpenId(openid); + // 微信用户不存在,注册成为新会员 + if (memberAuthResult != null && ResultCode.USER_NOT_EXIST.getCode().equals(memberAuthResult.getCode())) { + UmsMember member = new UmsMember(); + BeanUtil.copyProperties(wechatUserInfo, member); + member.setOpenid(openid); + memberFeignClient.add(member); + } + UserDetails userDetails = ((MemberUserDetailsServiceImpl) userDetailsService).loadUserByOpenId(openid); + WechatAuthenticationToken result = new WechatAuthenticationToken(userDetails, new HashSet<>()); + result.setDetails(authentication.getDetails()); + return result; + } + + + @Override + public boolean supports(Class authentication) { + return WechatAuthenticationToken.class.isAssignableFrom(authentication); + } +} diff --git a/youlai-auth/src/main/java/com/youlai/auth/security/extension/mobile/SmsCodeAuthenticationToken.java b/youlai-auth/src/main/java/com/youlai/auth/security/extension/mobile/SmsCodeAuthenticationToken.java new file mode 100644 index 000000000..d318aea0b --- /dev/null +++ b/youlai-auth/src/main/java/com/youlai/auth/security/extension/mobile/SmsCodeAuthenticationToken.java @@ -0,0 +1,52 @@ +package com.youlai.auth.security.extension.mobile; + +import org.springframework.security.authentication.AbstractAuthenticationToken; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.util.Assert; + +import java.util.Collection; + +/** + * 手机验证码登录 + * + * @author xianrui + * @date 2021/10/5 + */ +public class SmsCodeAuthenticationToken extends AbstractAuthenticationToken { + + private static final long serialVersionUID = 550L; + private final Object principal; + private Object credentials; + + public SmsCodeAuthenticationToken(Object principal, Object credentials) { + super((Collection) null); + this.principal = principal; + this.credentials = credentials; + this.setAuthenticated(false); + } + + public SmsCodeAuthenticationToken(Object principal, Object credentials, Collection authorities) { + super(authorities); + this.principal = principal; + this.credentials = credentials; + super.setAuthenticated(true); + } + + public Object getCredentials() { + return this.credentials; + } + + public Object getPrincipal() { + return this.principal; + } + + public void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException { + Assert.isTrue(!isAuthenticated, "Cannot set this token to trusted - use constructor which takes a GrantedAuthority list instead"); + super.setAuthenticated(false); + } + + public void eraseCredentials() { + super.eraseCredentials(); + this.credentials = null; + } +} diff --git a/youlai-auth/src/main/java/com/youlai/auth/security/extension/mobile/SmsCodeTokenGranter.java b/youlai-auth/src/main/java/com/youlai/auth/security/extension/mobile/SmsCodeTokenGranter.java new file mode 100644 index 000000000..789477f48 --- /dev/null +++ b/youlai-auth/src/main/java/com/youlai/auth/security/extension/mobile/SmsCodeTokenGranter.java @@ -0,0 +1,67 @@ +package com.youlai.auth.security.extension.mobile; + +import cn.hutool.core.lang.Assert; +import cn.hutool.core.util.StrUtil; +import com.youlai.common.constant.AuthConstants; +import com.youlai.common.web.exception.BizException; +import org.springframework.data.redis.core.StringRedisTemplate; +import org.springframework.security.authentication.*; +import org.springframework.security.core.Authentication; +import org.springframework.security.oauth2.common.exceptions.InvalidGrantException; +import org.springframework.security.oauth2.provider.*; +import org.springframework.security.oauth2.provider.token.AbstractTokenGranter; +import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices; + +import java.util.LinkedHashMap; +import java.util.Map; + +/** + * 手机验证码 + * + * @author xianrui + * @date 2021/9/25 + */ +public class SmsCodeTokenGranter extends AbstractTokenGranter { + + private static final String GRANT_TYPE = "sms_code"; + private final AuthenticationManager authenticationManager; + private StringRedisTemplate redisTemplate; + + public SmsCodeTokenGranter(AuthorizationServerTokenServices tokenServices, ClientDetailsService clientDetailsService, + OAuth2RequestFactory requestFactory, AuthenticationManager authenticationManager, + StringRedisTemplate redisTemplate + ) { + super(tokenServices, clientDetailsService, requestFactory, GRANT_TYPE); + this.authenticationManager = authenticationManager; + this.redisTemplate = redisTemplate; + } + + @Override + protected OAuth2Authentication getOAuth2Authentication(ClientDetails client, TokenRequest tokenRequest) { + + Map parameters = new LinkedHashMap(tokenRequest.getRequestParameters()); + + String mobile = parameters.get("mobile"); // 手机号 + String code = parameters.get("code"); // 短信验证码 + + parameters.remove("code"); + + Authentication userAuth = new SmsCodeAuthenticationToken(mobile, code); + ((AbstractAuthenticationToken) userAuth).setDetails(parameters); + + try { + userAuth = this.authenticationManager.authenticate(userAuth); + } catch (AccountStatusException var8) { + throw new InvalidGrantException(var8.getMessage()); + } catch (BadCredentialsException var9) { + throw new InvalidGrantException(var9.getMessage()); + } + + if (userAuth != null && userAuth.isAuthenticated()) { + OAuth2Request storedOAuth2Request = this.getRequestFactory().createOAuth2Request(client, tokenRequest); + return new OAuth2Authentication(storedOAuth2Request, userAuth); + } else { + throw new InvalidGrantException("Could not authenticate user: " + mobile); + } + } +} diff --git a/youlai-auth/src/main/java/com/youlai/auth/security/extension/username/CaptchaTokenGranter.java b/youlai-auth/src/main/java/com/youlai/auth/security/extension/username/CaptchaTokenGranter.java new file mode 100644 index 000000000..5cdb629f1 --- /dev/null +++ b/youlai-auth/src/main/java/com/youlai/auth/security/extension/username/CaptchaTokenGranter.java @@ -0,0 +1,81 @@ +package com.youlai.auth.security.extension.username; + +import cn.hutool.core.lang.Assert; +import cn.hutool.core.util.StrUtil; +import com.youlai.common.constant.AuthConstants; +import com.youlai.common.web.exception.BizException; +import org.springframework.data.redis.core.StringRedisTemplate; +import org.springframework.security.authentication.*; +import org.springframework.security.core.Authentication; +import org.springframework.security.oauth2.common.exceptions.InvalidGrantException; +import org.springframework.security.oauth2.provider.*; +import org.springframework.security.oauth2.provider.token.AbstractTokenGranter; +import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices; + +import java.util.LinkedHashMap; +import java.util.Map; + +/** + * 验证码授权模式 + * + * @author xianrui + * @date 2021/9/25 + */ +public class CaptchaTokenGranter extends AbstractTokenGranter { + + private static final String GRANT_TYPE = "captcha"; + private final AuthenticationManager authenticationManager; + private StringRedisTemplate redisTemplate; + + public CaptchaTokenGranter(AuthorizationServerTokenServices tokenServices, ClientDetailsService clientDetailsService, + OAuth2RequestFactory requestFactory, AuthenticationManager authenticationManager, + StringRedisTemplate redisTemplate + ) { + super(tokenServices, clientDetailsService, requestFactory, GRANT_TYPE); + this.authenticationManager = authenticationManager; + this.redisTemplate = redisTemplate; + } + + @Override + protected OAuth2Authentication getOAuth2Authentication(ClientDetails client, TokenRequest tokenRequest) { + + Map parameters = new LinkedHashMap(tokenRequest.getRequestParameters()); + + String validateCode = parameters.get("validateCode"); + String uuid = parameters.get("uuid"); + + Assert.isTrue(StrUtil.isNotBlank(validateCode), "验证码不能为空"); + String validateCodeKey = AuthConstants.VALIDATE_CODE_PREFIX + uuid; + String correctValidateCode = redisTemplate.opsForValue().get(validateCodeKey); + if (!validateCode.equals(correctValidateCode)) { + throw new BizException("验证码不正确"); + } else { + redisTemplate.delete(validateCodeKey); + } + + String username = parameters.get("username"); + String password = parameters.get("password"); + + parameters.remove("password"); + parameters.remove("validateCode"); + parameters.remove("uuid"); + + Authentication userAuth = new UsernamePasswordAuthenticationToken(username, password); + ((AbstractAuthenticationToken) userAuth).setDetails(parameters); + + try { + userAuth = this.authenticationManager.authenticate(userAuth); + } catch (AccountStatusException var8) { + throw new InvalidGrantException(var8.getMessage()); + } catch (BadCredentialsException var9) { + throw new InvalidGrantException(var9.getMessage()); + } + + if (userAuth != null && userAuth.isAuthenticated()) { + OAuth2Request storedOAuth2Request = this.getRequestFactory().createOAuth2Request(client, tokenRequest); + return new OAuth2Authentication(storedOAuth2Request, userAuth); + } else { + throw new InvalidGrantException("Could not authenticate user: " + username); + } + } +} diff --git a/youlai-auth/src/main/java/com/youlai/auth/security/extension/memeber/wechat/WechatAuthenticationProvider.java b/youlai-auth/src/main/java/com/youlai/auth/security/extension/wechat/WechatAuthenticationProvider.java similarity index 95% rename from youlai-auth/src/main/java/com/youlai/auth/security/extension/memeber/wechat/WechatAuthenticationProvider.java rename to youlai-auth/src/main/java/com/youlai/auth/security/extension/wechat/WechatAuthenticationProvider.java index 547d03917..e4c12fe50 100644 --- a/youlai-auth/src/main/java/com/youlai/auth/security/extension/memeber/wechat/WechatAuthenticationProvider.java +++ b/youlai-auth/src/main/java/com/youlai/auth/security/extension/wechat/WechatAuthenticationProvider.java @@ -1,4 +1,4 @@ -package com.youlai.auth.security.extension.memeber.wechat; +package com.youlai.auth.security.extension.wechat; import cn.binarywang.wx.miniapp.api.WxMaService; import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult; @@ -20,6 +20,8 @@ import org.springframework.security.core.userdetails.UserDetailsService; import java.util.HashSet; /** + * 微信认证提供者 + * * @author xianrui * @date 2021/9/25 */ @@ -31,7 +33,7 @@ public class WechatAuthenticationProvider implements AuthenticationProvider { private MemberFeignClient memberFeignClient; /** - * 认证验证 + * 微信认证 * * @param authentication * @return @@ -58,8 +60,7 @@ public class WechatAuthenticationProvider implements AuthenticationProvider { member.setOpenid(openid); memberFeignClient.add(member); } - - UserDetails userDetails = ((MemberUserDetailsServiceImpl)userDetailsService).loadUserByOpenId(openid); + UserDetails userDetails = ((MemberUserDetailsServiceImpl) userDetailsService).loadUserByOpenId(openid); WechatAuthenticationToken result = new WechatAuthenticationToken(userDetails, new HashSet<>()); result.setDetails(authentication.getDetails()); return result; diff --git a/youlai-auth/src/main/java/com/youlai/auth/security/extension/memeber/wechat/WechatAuthenticationToken.java b/youlai-auth/src/main/java/com/youlai/auth/security/extension/wechat/WechatAuthenticationToken.java similarity index 96% rename from youlai-auth/src/main/java/com/youlai/auth/security/extension/memeber/wechat/WechatAuthenticationToken.java rename to youlai-auth/src/main/java/com/youlai/auth/security/extension/wechat/WechatAuthenticationToken.java index 6f0e00741..485370b2e 100644 --- a/youlai-auth/src/main/java/com/youlai/auth/security/extension/memeber/wechat/WechatAuthenticationToken.java +++ b/youlai-auth/src/main/java/com/youlai/auth/security/extension/wechat/WechatAuthenticationToken.java @@ -1,4 +1,4 @@ -package com.youlai.auth.security.extension.memeber.wechat; +package com.youlai.auth.security.extension.wechat; import lombok.Getter; import org.springframework.security.authentication.AbstractAuthenticationToken; diff --git a/youlai-auth/src/main/java/com/youlai/auth/security/extension/memeber/wechat/WechatTokenGranter.java b/youlai-auth/src/main/java/com/youlai/auth/security/extension/wechat/WechatTokenGranter.java similarity index 97% rename from youlai-auth/src/main/java/com/youlai/auth/security/extension/memeber/wechat/WechatTokenGranter.java rename to youlai-auth/src/main/java/com/youlai/auth/security/extension/wechat/WechatTokenGranter.java index bf26c3e4c..d11173c78 100644 --- a/youlai-auth/src/main/java/com/youlai/auth/security/extension/memeber/wechat/WechatTokenGranter.java +++ b/youlai-auth/src/main/java/com/youlai/auth/security/extension/wechat/WechatTokenGranter.java @@ -1,4 +1,4 @@ -package com.youlai.auth.security.extension.memeber.wechat; +package com.youlai.auth.security.extension.wechat; import cn.hutool.json.JSONUtil; import org.springframework.security.authentication.*; diff --git a/youlai-auth/src/main/java/com/youlai/auth/security/extension/memeber/wechat/WechatUserInfo.java b/youlai-auth/src/main/java/com/youlai/auth/security/extension/wechat/WechatUserInfo.java similarity index 85% rename from youlai-auth/src/main/java/com/youlai/auth/security/extension/memeber/wechat/WechatUserInfo.java rename to youlai-auth/src/main/java/com/youlai/auth/security/extension/wechat/WechatUserInfo.java index 3d1b256b8..cddc1c581 100644 --- a/youlai-auth/src/main/java/com/youlai/auth/security/extension/memeber/wechat/WechatUserInfo.java +++ b/youlai-auth/src/main/java/com/youlai/auth/security/extension/wechat/WechatUserInfo.java @@ -1,4 +1,4 @@ -package com.youlai.auth.security.extension.memeber.wechat; +package com.youlai.auth.security.extension.wechat; import lombok.Data; diff --git a/youlai-common/common-core/src/main/java/com/youlai/common/constant/AuthConstants.java b/youlai-common/common-core/src/main/java/com/youlai/common/constant/AuthConstants.java index 9982079b2..8a9982183 100644 --- a/youlai-common/common-core/src/main/java/com/youlai/common/constant/AuthConstants.java +++ b/youlai-common/common-core/src/main/java/com/youlai/common/constant/AuthConstants.java @@ -72,5 +72,15 @@ public interface AuthConstants { */ String AUTHENTICATION_METHOD = "authenticationMethod"; + /** + * 验证码key前缀 + */ + String VALIDATE_CODE_PREFIX = "VALIDATE_CODE:"; + + /** + * 短信验证码key前缀 + */ + String SMS_CODE_PREFIX = "SMS_CODE:"; + } diff --git a/youlai-gateway/src/main/java/com/youlai/gateway/kaptcha/config/CaptchaConfig.java b/youlai-gateway/src/main/java/com/youlai/gateway/kaptcha/config/CaptchaConfig.java index e203d3533..b160a4400 100644 --- a/youlai-gateway/src/main/java/com/youlai/gateway/kaptcha/config/CaptchaConfig.java +++ b/youlai-gateway/src/main/java/com/youlai/gateway/kaptcha/config/CaptchaConfig.java @@ -8,6 +8,8 @@ import org.springframework.context.annotation.Configuration; import java.util.Properties; /** + * Kaptcha 验证码配置 + * * @author xianrui * @date 2021/10/4 */ diff --git a/youlai-gateway/src/main/java/com/youlai/gateway/kaptcha/handler/CaptchaImageHandler.java b/youlai-gateway/src/main/java/com/youlai/gateway/kaptcha/handler/CaptchaImageHandler.java index fd37d34ce..1c9a65edb 100644 --- a/youlai-gateway/src/main/java/com/youlai/gateway/kaptcha/handler/CaptchaImageHandler.java +++ b/youlai-gateway/src/main/java/com/youlai/gateway/kaptcha/handler/CaptchaImageHandler.java @@ -1,13 +1,15 @@ package com.youlai.gateway.kaptcha.handler; +import cn.hutool.core.codec.Base64; import cn.hutool.core.io.FastByteArrayOutputStream; import cn.hutool.core.util.IdUtil; import com.google.code.kaptcha.Producer; +import com.youlai.common.constant.AuthConstants; +import com.youlai.common.result.Result; import lombok.RequiredArgsConstructor; -import org.springframework.core.io.ByteArrayResource; import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; import org.springframework.stereotype.Component; import org.springframework.web.reactive.function.BodyInserters; import org.springframework.web.reactive.function.server.HandlerFunction; @@ -18,8 +20,10 @@ import reactor.core.publisher.Mono; import javax.imageio.ImageIO; import java.awt.image.BufferedImage; import java.io.IOException; +import java.util.HashMap; import java.util.concurrent.TimeUnit; + /** * @author xianrui * @date 2021/10/4 @@ -28,12 +32,8 @@ import java.util.concurrent.TimeUnit; @RequiredArgsConstructor public class CaptchaImageHandler implements HandlerFunction { - //随机数code_key - public static final String DEFAULT_CODE_KEY = "random_code_"; - private final Producer producer; - - private final RedisTemplate redisTemplate; + private final StringRedisTemplate redisTemplate; @Override public Mono handle(ServerRequest serverRequest) { @@ -43,8 +43,8 @@ public class CaptchaImageHandler implements HandlerFunction { String code = capText.substring(capText.lastIndexOf("@") + 1); BufferedImage image = producer.createImage(capStr); // 保存验证码信息 - String randomStr = IdUtil.simpleUUID(); - redisTemplate.opsForValue().set(DEFAULT_CODE_KEY + randomStr, code, 60, TimeUnit.SECONDS); + String uuid = IdUtil.simpleUUID(); + redisTemplate.opsForValue().set(AuthConstants.VALIDATE_CODE_PREFIX + uuid, code, 60, TimeUnit.SECONDS); // 转换流信息写出 FastByteArrayOutputStream os = new FastByteArrayOutputStream(); try { @@ -52,12 +52,14 @@ public class CaptchaImageHandler implements HandlerFunction { } catch (IOException e) { return Mono.error(e); } - return ServerResponse.status(HttpStatus.OK) - .contentType(MediaType.IMAGE_JPEG) - .header("randomstr", randomStr) - .body(BodyInserters.fromResource(new ByteArrayResource(os.toByteArray()))); + + + java.util.Map resultMap = new HashMap(); + resultMap.put("uuid", uuid); + resultMap.put("img", Base64.encode(os.toByteArray())); + + return ServerResponse.status(HttpStatus.OK).body(BodyInserters.fromValue(Result.success(resultMap))); } - } diff --git a/youlai-gateway/src/main/java/com/youlai/gateway/router/CaptchaImageRouter.java b/youlai-gateway/src/main/java/com/youlai/gateway/router/CaptchaImageRouter.java index 88b2a434c..35bde69a6 100644 --- a/youlai-gateway/src/main/java/com/youlai/gateway/router/CaptchaImageRouter.java +++ b/youlai-gateway/src/main/java/com/youlai/gateway/router/CaptchaImageRouter.java @@ -21,7 +21,7 @@ public class CaptchaImageRouter { @Bean public RouterFunction routeFunction(CaptchaImageHandler captchaImageHandler) { return RouterFunctions - .route(RequestPredicates.GET("/code") + .route(RequestPredicates.GET("/validate-code") .and(RequestPredicates.accept(MediaType.TEXT_PLAIN)), captchaImageHandler::handle); }