mirror of
https://gitee.com/youlaitech/youlai-mall.git
synced 2024-12-22 20:54:26 +08:00
feat:刷新token时选择userDetailService
This commit is contained in:
parent
fab7d40eb8
commit
d86a9d549f
@ -33,7 +33,7 @@
|
||||
</sql>
|
||||
|
||||
<resultMap id="UserAuthMap" type="com.youlai.admin.pojo.dto.UserAuthDTO">
|
||||
<id property="userId" column="id" jdbcType="BIGINT"/>
|
||||
<id property="userId" column="userId" jdbcType="BIGINT"/>
|
||||
<result property="username" column="username" jdbcType="VARCHAR"/>
|
||||
<result property="password" column="password" jdbcType="VARCHAR"/>
|
||||
<result property="status" column="status" jdbcType="BOOLEAN"/>
|
||||
|
@ -6,6 +6,7 @@ import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.security.authentication.InternalAuthenticationServiceException;
|
||||
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||
import org.springframework.security.oauth2.common.exceptions.InvalidGrantException;
|
||||
import org.springframework.security.oauth2.common.exceptions.InvalidTokenException;
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
import org.springframework.web.bind.annotation.RestControllerAdvice;
|
||||
|
||||
@ -47,4 +48,15 @@ public class OAuthExceptionHandler {
|
||||
return Result.failed(e.getMessage());
|
||||
}
|
||||
|
||||
/**
|
||||
* token 无效或已过期
|
||||
*
|
||||
* @param e
|
||||
* @return
|
||||
*/
|
||||
@ExceptionHandler({InvalidTokenException.class})
|
||||
public Result handleInvalidTokenExceptionException(InvalidTokenException e) {
|
||||
return Result.failed(e.getMessage());
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -60,7 +60,7 @@ public class OAuthController {
|
||||
* 方式一:client_id、client_secret放在请求路径中(注:当前版本已废弃)
|
||||
* 方式二:放在请求头(Request Headers)中的Authorization字段,且经过加密,例如 Basic Y2xpZW50OnNlY3JldA== 明文等于 client:secret
|
||||
*/
|
||||
String clientId = JwtUtils.getOAuthClientId();
|
||||
String clientId = JwtUtils.getOAuth2ClientId();
|
||||
log.info("OAuth认证授权 客户端ID:{},请求参数:{}", clientId, JSONUtil.toJsonStr(parameters));
|
||||
|
||||
/**
|
||||
|
@ -5,11 +5,14 @@ import cn.hutool.http.HttpStatus;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.youlai.auth.security.core.clientdetails.ClientDetailsServiceImpl;
|
||||
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.system.SysUserDetails;
|
||||
import com.youlai.auth.security.core.userdetails.system.SysUserDetailsServiceImpl;
|
||||
import com.youlai.auth.security.extension.wechat.WechatTokenGranter;
|
||||
import com.youlai.auth.security.core.CustomUserDetailsByNameServiceWrapper;
|
||||
import com.youlai.common.result.Result;
|
||||
import com.youlai.common.result.ResultCode;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.SneakyThrows;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
@ -17,6 +20,8 @@ import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.authentication.ProviderManager;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken;
|
||||
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
|
||||
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
|
||||
@ -24,11 +29,13 @@ import org.springframework.security.oauth2.config.annotation.web.configuration.E
|
||||
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
|
||||
import org.springframework.security.oauth2.provider.CompositeTokenGranter;
|
||||
import org.springframework.security.oauth2.provider.TokenGranter;
|
||||
import org.springframework.security.oauth2.provider.token.DefaultTokenServices;
|
||||
import org.springframework.security.oauth2.provider.token.TokenEnhancer;
|
||||
import org.springframework.security.oauth2.provider.token.TokenEnhancerChain;
|
||||
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
|
||||
import org.springframework.security.oauth2.provider.token.store.KeyStoreKeyFactory;
|
||||
import org.springframework.security.web.AuthenticationEntryPoint;
|
||||
import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationProvider;
|
||||
|
||||
import java.security.KeyPair;
|
||||
import java.util.*;
|
||||
@ -38,12 +45,15 @@ import java.util.*;
|
||||
*/
|
||||
@Configuration
|
||||
@EnableAuthorizationServer
|
||||
@AllArgsConstructor
|
||||
@RequiredArgsConstructor
|
||||
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
|
||||
|
||||
private AuthenticationManager authenticationManager;
|
||||
private final AuthenticationManager authenticationManager;
|
||||
private final ClientDetailsServiceImpl clientDetailsService;
|
||||
private final SysUserDetailsServiceImpl sysUserDetailsService;
|
||||
private final MemberUserDetailsServiceImpl memberUserDetailsService;
|
||||
|
||||
private ClientDetailsServiceImpl clientDetailsService;
|
||||
private final List<UserDetailsService> userDetailsServices;
|
||||
|
||||
/**
|
||||
* OAuth2客户端
|
||||
@ -68,7 +78,8 @@ public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdap
|
||||
|
||||
// 添加自定义授权模式
|
||||
List<TokenGranter> granterList = new ArrayList<>(Arrays.asList(endpoints.getTokenGranter()));
|
||||
granterList.add(new WechatTokenGranter(endpoints.getTokenServices(), endpoints.getClientDetailsService(), endpoints.getOAuth2RequestFactory(), authenticationManager));
|
||||
granterList.add(new WechatTokenGranter(endpoints.getTokenServices(), endpoints.getClientDetailsService(), endpoints.getOAuth2RequestFactory(),
|
||||
authenticationManager));
|
||||
CompositeTokenGranter compositeTokenGranter = new CompositeTokenGranter(granterList);
|
||||
|
||||
endpoints
|
||||
@ -76,12 +87,37 @@ public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdap
|
||||
.accessTokenConverter(jwtAccessTokenConverter())
|
||||
.tokenEnhancer(tokenEnhancerChain)
|
||||
.tokenGranter(compositeTokenGranter)
|
||||
// .userDetailsService(sysUserDetailsService)
|
||||
// refresh token有两种使用方式:重复使用(true)、非重复使用(false),默认为true
|
||||
// 1 重复使用:access token过期刷新时, refresh token过期时间未改变,仍以初次生成的时间为准
|
||||
// 2 非重复使用:access token过期刷新时, refresh token过期时间延续,在refresh token有效期内刷新便永不失效达到无需再次登录的目的
|
||||
.reuseRefreshTokens(true);
|
||||
.reuseRefreshTokens(true)
|
||||
.tokenServices(tokenServices(endpoints)); // 自定义的TokenService
|
||||
}
|
||||
|
||||
|
||||
public DefaultTokenServices tokenServices(AuthorizationServerEndpointsConfigurer endpoints) {
|
||||
// Token增强
|
||||
TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain();
|
||||
List<TokenEnhancer> tokenEnhancers = new ArrayList<>();
|
||||
tokenEnhancers.add(tokenEnhancer());
|
||||
tokenEnhancers.add(jwtAccessTokenConverter());
|
||||
tokenEnhancerChain.setTokenEnhancers(tokenEnhancers);
|
||||
|
||||
DefaultTokenServices tokenServices = new DefaultTokenServices();
|
||||
tokenServices.setTokenStore(endpoints.getTokenStore());
|
||||
tokenServices.setSupportRefreshToken(true);
|
||||
tokenServices.setClientDetailsService(clientDetailsService);
|
||||
tokenServices.setTokenEnhancer(tokenEnhancerChain);
|
||||
|
||||
PreAuthenticatedAuthenticationProvider provider = new PreAuthenticatedAuthenticationProvider();
|
||||
provider.setPreAuthenticatedUserDetailsService(new CustomUserDetailsByNameServiceWrapper<>(userDetailsServices));
|
||||
tokenServices.setAuthenticationManager(new ProviderManager(Arrays.asList(provider)));
|
||||
return tokenServices;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 使用非对称加密算法对token签名
|
||||
*/
|
||||
|
@ -55,8 +55,8 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
|
||||
|
||||
@Override
|
||||
public void configure(AuthenticationManagerBuilder auth) {
|
||||
auth.authenticationProvider(wechatAuthenticationProvider())
|
||||
.authenticationProvider(daoAuthenticationProvider());
|
||||
auth.authenticationProvider(wechatAuthenticationProvider());
|
||||
auth.authenticationProvider(daoAuthenticationProvider());
|
||||
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,61 @@
|
||||
package com.youlai.auth.security.core;
|
||||
|
||||
import com.youlai.auth.security.core.userdetails.member.MemberUserDetailsServiceImpl;
|
||||
import com.youlai.auth.security.core.userdetails.system.SysUserDetailsServiceImpl;
|
||||
import com.youlai.auth.security.extension.wechat.WechatAuthenticationToken;
|
||||
import com.youlai.common.web.util.JwtUtils;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.userdetails.AuthenticationUserDetailsService;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||
import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:xianrui0365@163.com">xianrui</a>
|
||||
* @date 2021/10/2
|
||||
*/
|
||||
@NoArgsConstructor
|
||||
public class CustomUserDetailsByNameServiceWrapper<T extends Authentication> implements AuthenticationUserDetailsService<T>, InitializingBean {
|
||||
|
||||
|
||||
private List<UserDetailsService> userDetailsServiceList;
|
||||
|
||||
public CustomUserDetailsByNameServiceWrapper(List<UserDetailsService> userDetailsServiceList) {
|
||||
Assert.notNull(userDetailsServiceList, "userDetailsService cannot be null.");
|
||||
this.userDetailsServiceList = userDetailsServiceList;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
Assert.notNull(this.userDetailsServiceList, "UserDetailsService must be set");
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserDetails loadUserDetails(T authentication) throws UsernameNotFoundException {
|
||||
UserDetailsService userDetailsService = null;
|
||||
|
||||
|
||||
String clientId = JwtUtils.getOAuth2ClientId();
|
||||
|
||||
for (UserDetailsService detailsService : userDetailsServiceList) {
|
||||
if (clientId.equals("youlai-mall-weapp")) {
|
||||
if (detailsService instanceof MemberUserDetailsServiceImpl) {
|
||||
userDetailsService = detailsService;
|
||||
continue;
|
||||
}
|
||||
}else{
|
||||
if (detailsService instanceof SysUserDetailsServiceImpl) {
|
||||
userDetailsService = detailsService;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
return userDetailsService.loadUserByUsername(authentication.getName());
|
||||
}
|
||||
}
|
@ -13,6 +13,9 @@ import org.springframework.security.oauth2.provider.NoSuchClientException;
|
||||
import org.springframework.security.oauth2.provider.client.BaseClientDetails;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* OAuth2 客户端信息
|
||||
*/
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class ClientDetailsServiceImpl implements ClientDetailsService {
|
||||
|
@ -1,7 +1,5 @@
|
||||
package com.youlai.auth.security.core.userdetails.member;
|
||||
|
||||
import cn.binarywang.wx.miniapp.api.WxMaService;
|
||||
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
|
||||
import com.youlai.common.result.Result;
|
||||
import com.youlai.common.result.ResultCode;
|
||||
import com.youlai.mall.ums.api.MemberFeignClient;
|
||||
|
@ -58,14 +58,14 @@ public class JwtUtils {
|
||||
/**
|
||||
* 获取登录认证的客户端ID
|
||||
*
|
||||
* 兼容两种方式获取Oauth2客户端信息(client_id、client_secret)
|
||||
* 兼容两种方式获取OAuth2客户端信息(client_id、client_secret)
|
||||
* 方式一:client_id、client_secret放在请求路径中
|
||||
* 方式二:放在请求头(Request Headers)中的Authorization字段,且经过加密,例如 Basic Y2xpZW50OnNlY3JldA== 明文等于 client:secret
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@SneakyThrows
|
||||
public static String getOAuthClientId() {
|
||||
public static String getOAuth2ClientId() {
|
||||
String clientId;
|
||||
|
||||
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
|
||||
|
Loading…
Reference in New Issue
Block a user