mirror of
https://gitee.com/youlaitech/youlai-mall.git
synced 2024-12-23 05:00:25 +08:00
feat:springsecurity偶通话
This commit is contained in:
parent
aa031f46bf
commit
b41d67af58
@ -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.member.MemberUserDetailsServiceImpl;
|
||||||
import com.youlai.auth.security.core.userdetails.user.SysUserDetails;
|
import com.youlai.auth.security.core.userdetails.user.SysUserDetails;
|
||||||
import com.youlai.auth.security.core.userdetails.user.SysUserDetailsServiceImpl;
|
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.PreAuthenticatedUserDetailsService;
|
||||||
|
import com.youlai.auth.security.extension.username.CaptchaTokenGranter;
|
||||||
import com.youlai.common.result.Result;
|
import com.youlai.common.result.Result;
|
||||||
import com.youlai.common.result.ResultCode;
|
import com.youlai.common.result.ResultCode;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
@ -19,6 +20,7 @@ import lombok.SneakyThrows;
|
|||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.core.io.ClassPathResource;
|
import org.springframework.core.io.ClassPathResource;
|
||||||
|
import org.springframework.data.redis.core.StringRedisTemplate;
|
||||||
import org.springframework.http.HttpHeaders;
|
import org.springframework.http.HttpHeaders;
|
||||||
import org.springframework.http.MediaType;
|
import org.springframework.http.MediaType;
|
||||||
import org.springframework.security.authentication.AuthenticationManager;
|
import org.springframework.security.authentication.AuthenticationManager;
|
||||||
@ -54,6 +56,7 @@ public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdap
|
|||||||
private final ClientDetailsServiceImpl clientDetailsService;
|
private final ClientDetailsServiceImpl clientDetailsService;
|
||||||
private final SysUserDetailsServiceImpl sysUserDetailsService;
|
private final SysUserDetailsServiceImpl sysUserDetailsService;
|
||||||
private final MemberUserDetailsServiceImpl memberUserDetailsService;
|
private final MemberUserDetailsServiceImpl memberUserDetailsService;
|
||||||
|
private final StringRedisTemplate stringRedisTemplate;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* OAuth2客户端
|
* OAuth2客户端
|
||||||
@ -78,10 +81,13 @@ public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdap
|
|||||||
|
|
||||||
// 添加自定义授权模式
|
// 添加自定义授权模式
|
||||||
List<TokenGranter> granterList = new ArrayList<>(Arrays.asList(endpoints.getTokenGranter()));
|
List<TokenGranter> granterList = new ArrayList<>(Arrays.asList(endpoints.getTokenGranter()));
|
||||||
granterList.add(new WechatTokenGranter(endpoints.getTokenServices(), endpoints.getClientDetailsService(), endpoints.getOAuth2RequestFactory(),
|
granterList.add(new WechatTokenGranter(endpoints.getTokenServices(), endpoints.getClientDetailsService(),
|
||||||
authenticationManager));
|
endpoints.getOAuth2RequestFactory(), authenticationManager));
|
||||||
CompositeTokenGranter compositeTokenGranter = new CompositeTokenGranter(granterList);
|
granterList.add(new CaptchaTokenGranter(endpoints.getTokenServices(), endpoints.getClientDetailsService(),
|
||||||
|
endpoints.getOAuth2RequestFactory(), authenticationManager, stringRedisTemplate
|
||||||
|
|
||||||
|
));
|
||||||
|
CompositeTokenGranter compositeTokenGranter = new CompositeTokenGranter(granterList);
|
||||||
endpoints
|
endpoints
|
||||||
.authenticationManager(authenticationManager)
|
.authenticationManager(authenticationManager)
|
||||||
.accessTokenConverter(jwtAccessTokenConverter())
|
.accessTokenConverter(jwtAccessTokenConverter())
|
||||||
@ -112,21 +118,16 @@ public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdap
|
|||||||
tokenServices.setTokenEnhancer(tokenEnhancerChain);
|
tokenServices.setTokenEnhancer(tokenEnhancerChain);
|
||||||
|
|
||||||
PreAuthenticatedAuthenticationProvider provider = new PreAuthenticatedAuthenticationProvider();
|
PreAuthenticatedAuthenticationProvider provider = new PreAuthenticatedAuthenticationProvider();
|
||||||
provider.setPreAuthenticatedUserDetailsService(new PreAuthenticatedUserDetailsService<>(refreshTokenUserDetailsServiceMap()));
|
Map<String, UserDetailsService> 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)));
|
tokenServices.setAuthenticationManager(new ProviderManager(Arrays.asList(provider)));
|
||||||
return tokenServices;
|
return tokenServices;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public Map<String, UserDetailsService> refreshTokenUserDetailsServiceMap() {
|
|
||||||
Map<String, UserDetailsService> clientUserDetailsServiceMap = new HashMap<>();
|
|
||||||
clientUserDetailsServiceMap.put(AuthConstants.ADMIN_CLIENT_ID, sysUserDetailsService);
|
|
||||||
clientUserDetailsServiceMap.put(AuthConstants.APP_CLIENT_ID, memberUserDetailsService);
|
|
||||||
return clientUserDetailsServiceMap;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 使用非对称加密算法对token签名
|
* 使用非对称加密算法对token签名
|
||||||
*/
|
*/
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
package com.youlai.auth.security.config;
|
package com.youlai.auth.security.config;
|
||||||
|
|
||||||
import cn.binarywang.wx.miniapp.api.WxMaService;
|
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 com.youlai.mall.ums.api.MemberFeignClient;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
@ -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 <a href="mailto:xianrui0365@163.com">xianrui</a>
|
||||||
|
* @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<MemberAuthDTO> 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);
|
||||||
|
}
|
||||||
|
}
|
@ -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 <a href="mailto:xianrui0365@163.com">xianrui</a>
|
||||||
|
* @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<? extends GrantedAuthority> 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;
|
||||||
|
}
|
||||||
|
}
|
@ -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 <a href="mailto:xianrui0365@163.com">xianrui</a>
|
||||||
|
* @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<String, String> 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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 <a href="mailto:xianrui0365@163.com">xianrui</a>
|
||||||
|
* @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<String, String> 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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.api.WxMaService;
|
||||||
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
|
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
|
||||||
@ -20,6 +20,8 @@ import org.springframework.security.core.userdetails.UserDetailsService;
|
|||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* 微信认证提供者
|
||||||
|
*
|
||||||
* @author <a href="mailto:xianrui0365@163.com">xianrui</a>
|
* @author <a href="mailto:xianrui0365@163.com">xianrui</a>
|
||||||
* @date 2021/9/25
|
* @date 2021/9/25
|
||||||
*/
|
*/
|
||||||
@ -31,7 +33,7 @@ public class WechatAuthenticationProvider implements AuthenticationProvider {
|
|||||||
private MemberFeignClient memberFeignClient;
|
private MemberFeignClient memberFeignClient;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 认证验证
|
* 微信认证
|
||||||
*
|
*
|
||||||
* @param authentication
|
* @param authentication
|
||||||
* @return
|
* @return
|
||||||
@ -58,8 +60,7 @@ public class WechatAuthenticationProvider implements AuthenticationProvider {
|
|||||||
member.setOpenid(openid);
|
member.setOpenid(openid);
|
||||||
memberFeignClient.add(member);
|
memberFeignClient.add(member);
|
||||||
}
|
}
|
||||||
|
UserDetails userDetails = ((MemberUserDetailsServiceImpl) userDetailsService).loadUserByOpenId(openid);
|
||||||
UserDetails userDetails = ((MemberUserDetailsServiceImpl)userDetailsService).loadUserByOpenId(openid);
|
|
||||||
WechatAuthenticationToken result = new WechatAuthenticationToken(userDetails, new HashSet<>());
|
WechatAuthenticationToken result = new WechatAuthenticationToken(userDetails, new HashSet<>());
|
||||||
result.setDetails(authentication.getDetails());
|
result.setDetails(authentication.getDetails());
|
||||||
return result;
|
return result;
|
@ -1,4 +1,4 @@
|
|||||||
package com.youlai.auth.security.extension.memeber.wechat;
|
package com.youlai.auth.security.extension.wechat;
|
||||||
|
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import org.springframework.security.authentication.AbstractAuthenticationToken;
|
import org.springframework.security.authentication.AbstractAuthenticationToken;
|
@ -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 cn.hutool.json.JSONUtil;
|
||||||
import org.springframework.security.authentication.*;
|
import org.springframework.security.authentication.*;
|
@ -1,4 +1,4 @@
|
|||||||
package com.youlai.auth.security.extension.memeber.wechat;
|
package com.youlai.auth.security.extension.wechat;
|
||||||
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
@ -72,5 +72,15 @@ public interface AuthConstants {
|
|||||||
*/
|
*/
|
||||||
String AUTHENTICATION_METHOD = "authenticationMethod";
|
String AUTHENTICATION_METHOD = "authenticationMethod";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 验证码key前缀
|
||||||
|
*/
|
||||||
|
String VALIDATE_CODE_PREFIX = "VALIDATE_CODE:";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 短信验证码key前缀
|
||||||
|
*/
|
||||||
|
String SMS_CODE_PREFIX = "SMS_CODE:";
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,8 @@ import org.springframework.context.annotation.Configuration;
|
|||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Kaptcha 验证码配置
|
||||||
|
*
|
||||||
* @author <a href="mailto:xianrui0365@163.com">xianrui</a>
|
* @author <a href="mailto:xianrui0365@163.com">xianrui</a>
|
||||||
* @date 2021/10/4
|
* @date 2021/10/4
|
||||||
*/
|
*/
|
||||||
|
@ -1,13 +1,15 @@
|
|||||||
package com.youlai.gateway.kaptcha.handler;
|
package com.youlai.gateway.kaptcha.handler;
|
||||||
|
|
||||||
|
import cn.hutool.core.codec.Base64;
|
||||||
import cn.hutool.core.io.FastByteArrayOutputStream;
|
import cn.hutool.core.io.FastByteArrayOutputStream;
|
||||||
import cn.hutool.core.util.IdUtil;
|
import cn.hutool.core.util.IdUtil;
|
||||||
import com.google.code.kaptcha.Producer;
|
import com.google.code.kaptcha.Producer;
|
||||||
|
import com.youlai.common.constant.AuthConstants;
|
||||||
|
import com.youlai.common.result.Result;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.springframework.core.io.ByteArrayResource;
|
|
||||||
import org.springframework.data.redis.core.RedisTemplate;
|
import org.springframework.data.redis.core.RedisTemplate;
|
||||||
|
import org.springframework.data.redis.core.StringRedisTemplate;
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.http.MediaType;
|
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
import org.springframework.web.reactive.function.BodyInserters;
|
import org.springframework.web.reactive.function.BodyInserters;
|
||||||
import org.springframework.web.reactive.function.server.HandlerFunction;
|
import org.springframework.web.reactive.function.server.HandlerFunction;
|
||||||
@ -18,8 +20,10 @@ import reactor.core.publisher.Mono;
|
|||||||
import javax.imageio.ImageIO;
|
import javax.imageio.ImageIO;
|
||||||
import java.awt.image.BufferedImage;
|
import java.awt.image.BufferedImage;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:xianrui0365@163.com">xianrui</a>
|
* @author <a href="mailto:xianrui0365@163.com">xianrui</a>
|
||||||
* @date 2021/10/4
|
* @date 2021/10/4
|
||||||
@ -28,12 +32,8 @@ import java.util.concurrent.TimeUnit;
|
|||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public class CaptchaImageHandler implements HandlerFunction<ServerResponse> {
|
public class CaptchaImageHandler implements HandlerFunction<ServerResponse> {
|
||||||
|
|
||||||
//随机数code_key
|
|
||||||
public static final String DEFAULT_CODE_KEY = "random_code_";
|
|
||||||
|
|
||||||
private final Producer producer;
|
private final Producer producer;
|
||||||
|
private final StringRedisTemplate redisTemplate;
|
||||||
private final RedisTemplate redisTemplate;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Mono<ServerResponse> handle(ServerRequest serverRequest) {
|
public Mono<ServerResponse> handle(ServerRequest serverRequest) {
|
||||||
@ -43,8 +43,8 @@ public class CaptchaImageHandler implements HandlerFunction<ServerResponse> {
|
|||||||
String code = capText.substring(capText.lastIndexOf("@") + 1);
|
String code = capText.substring(capText.lastIndexOf("@") + 1);
|
||||||
BufferedImage image = producer.createImage(capStr);
|
BufferedImage image = producer.createImage(capStr);
|
||||||
// 保存验证码信息
|
// 保存验证码信息
|
||||||
String randomStr = IdUtil.simpleUUID();
|
String uuid = IdUtil.simpleUUID();
|
||||||
redisTemplate.opsForValue().set(DEFAULT_CODE_KEY + randomStr, code, 60, TimeUnit.SECONDS);
|
redisTemplate.opsForValue().set(AuthConstants.VALIDATE_CODE_PREFIX + uuid, code, 60, TimeUnit.SECONDS);
|
||||||
// 转换流信息写出
|
// 转换流信息写出
|
||||||
FastByteArrayOutputStream os = new FastByteArrayOutputStream();
|
FastByteArrayOutputStream os = new FastByteArrayOutputStream();
|
||||||
try {
|
try {
|
||||||
@ -52,12 +52,14 @@ public class CaptchaImageHandler implements HandlerFunction<ServerResponse> {
|
|||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
return Mono.error(e);
|
return Mono.error(e);
|
||||||
}
|
}
|
||||||
return ServerResponse.status(HttpStatus.OK)
|
|
||||||
.contentType(MediaType.IMAGE_JPEG)
|
|
||||||
.header("randomstr", randomStr)
|
java.util.Map resultMap = new HashMap<String, String>();
|
||||||
.body(BodyInserters.fromResource(new ByteArrayResource(os.toByteArray())));
|
resultMap.put("uuid", uuid);
|
||||||
|
resultMap.put("img", Base64.encode(os.toByteArray()));
|
||||||
|
|
||||||
|
return ServerResponse.status(HttpStatus.OK).body(BodyInserters.fromValue(Result.success(resultMap)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -21,7 +21,7 @@ public class CaptchaImageRouter {
|
|||||||
@Bean
|
@Bean
|
||||||
public RouterFunction<ServerResponse> routeFunction(CaptchaImageHandler captchaImageHandler) {
|
public RouterFunction<ServerResponse> routeFunction(CaptchaImageHandler captchaImageHandler) {
|
||||||
return RouterFunctions
|
return RouterFunctions
|
||||||
.route(RequestPredicates.GET("/code")
|
.route(RequestPredicates.GET("/validate-code")
|
||||||
.and(RequestPredicates.accept(MediaType.TEXT_PLAIN)), captchaImageHandler::handle);
|
.and(RequestPredicates.accept(MediaType.TEXT_PLAIN)), captchaImageHandler::handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user