mirror of
https://gitee.com/youlaitech/youlai-mall.git
synced 2024-12-23 13:03:43 +08:00
feat:刷新token时选择userDetailService
This commit is contained in:
parent
fab7d40eb8
commit
d86a9d549f
@ -33,7 +33,7 @@
|
|||||||
</sql>
|
</sql>
|
||||||
|
|
||||||
<resultMap id="UserAuthMap" type="com.youlai.admin.pojo.dto.UserAuthDTO">
|
<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="username" column="username" jdbcType="VARCHAR"/>
|
||||||
<result property="password" column="password" jdbcType="VARCHAR"/>
|
<result property="password" column="password" jdbcType="VARCHAR"/>
|
||||||
<result property="status" column="status" jdbcType="BOOLEAN"/>
|
<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.authentication.InternalAuthenticationServiceException;
|
||||||
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||||
import org.springframework.security.oauth2.common.exceptions.InvalidGrantException;
|
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.ExceptionHandler;
|
||||||
import org.springframework.web.bind.annotation.RestControllerAdvice;
|
import org.springframework.web.bind.annotation.RestControllerAdvice;
|
||||||
|
|
||||||
@ -47,4 +48,15 @@ public class OAuthExceptionHandler {
|
|||||||
return Result.failed(e.getMessage());
|
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放在请求路径中(注:当前版本已废弃)
|
* 方式一:client_id、client_secret放在请求路径中(注:当前版本已废弃)
|
||||||
* 方式二:放在请求头(Request Headers)中的Authorization字段,且经过加密,例如 Basic Y2xpZW50OnNlY3JldA== 明文等于 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));
|
log.info("OAuth认证授权 客户端ID:{},请求参数:{}", clientId, JSONUtil.toJsonStr(parameters));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -5,11 +5,14 @@ import cn.hutool.http.HttpStatus;
|
|||||||
import cn.hutool.json.JSONUtil;
|
import cn.hutool.json.JSONUtil;
|
||||||
import com.youlai.auth.security.core.clientdetails.ClientDetailsServiceImpl;
|
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.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.SysUserDetails;
|
||||||
|
import com.youlai.auth.security.core.userdetails.system.SysUserDetailsServiceImpl;
|
||||||
import com.youlai.auth.security.extension.wechat.WechatTokenGranter;
|
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.Result;
|
||||||
import com.youlai.common.result.ResultCode;
|
import com.youlai.common.result.ResultCode;
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.SneakyThrows;
|
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;
|
||||||
@ -17,6 +20,8 @@ import org.springframework.core.io.ClassPathResource;
|
|||||||
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;
|
||||||
|
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.common.DefaultOAuth2AccessToken;
|
||||||
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
|
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
|
||||||
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
|
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.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
|
||||||
import org.springframework.security.oauth2.provider.CompositeTokenGranter;
|
import org.springframework.security.oauth2.provider.CompositeTokenGranter;
|
||||||
import org.springframework.security.oauth2.provider.TokenGranter;
|
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.TokenEnhancer;
|
||||||
import org.springframework.security.oauth2.provider.token.TokenEnhancerChain;
|
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.JwtAccessTokenConverter;
|
||||||
import org.springframework.security.oauth2.provider.token.store.KeyStoreKeyFactory;
|
import org.springframework.security.oauth2.provider.token.store.KeyStoreKeyFactory;
|
||||||
import org.springframework.security.web.AuthenticationEntryPoint;
|
import org.springframework.security.web.AuthenticationEntryPoint;
|
||||||
|
import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationProvider;
|
||||||
|
|
||||||
import java.security.KeyPair;
|
import java.security.KeyPair;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
@ -38,12 +45,15 @@ import java.util.*;
|
|||||||
*/
|
*/
|
||||||
@Configuration
|
@Configuration
|
||||||
@EnableAuthorizationServer
|
@EnableAuthorizationServer
|
||||||
@AllArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
|
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客户端
|
* OAuth2客户端
|
||||||
@ -68,7 +78,8 @@ 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(), authenticationManager));
|
granterList.add(new WechatTokenGranter(endpoints.getTokenServices(), endpoints.getClientDetailsService(), endpoints.getOAuth2RequestFactory(),
|
||||||
|
authenticationManager));
|
||||||
CompositeTokenGranter compositeTokenGranter = new CompositeTokenGranter(granterList);
|
CompositeTokenGranter compositeTokenGranter = new CompositeTokenGranter(granterList);
|
||||||
|
|
||||||
endpoints
|
endpoints
|
||||||
@ -76,12 +87,37 @@ public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdap
|
|||||||
.accessTokenConverter(jwtAccessTokenConverter())
|
.accessTokenConverter(jwtAccessTokenConverter())
|
||||||
.tokenEnhancer(tokenEnhancerChain)
|
.tokenEnhancer(tokenEnhancerChain)
|
||||||
.tokenGranter(compositeTokenGranter)
|
.tokenGranter(compositeTokenGranter)
|
||||||
|
// .userDetailsService(sysUserDetailsService)
|
||||||
// refresh token有两种使用方式:重复使用(true)、非重复使用(false),默认为true
|
// refresh token有两种使用方式:重复使用(true)、非重复使用(false),默认为true
|
||||||
// 1 重复使用:access token过期刷新时, refresh token过期时间未改变,仍以初次生成的时间为准
|
// 1 重复使用:access token过期刷新时, refresh token过期时间未改变,仍以初次生成的时间为准
|
||||||
// 2 非重复使用:access token过期刷新时, refresh 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签名
|
* 使用非对称加密算法对token签名
|
||||||
*/
|
*/
|
||||||
|
@ -55,8 +55,8 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void configure(AuthenticationManagerBuilder auth) {
|
public void configure(AuthenticationManagerBuilder auth) {
|
||||||
auth.authenticationProvider(wechatAuthenticationProvider())
|
auth.authenticationProvider(wechatAuthenticationProvider());
|
||||||
.authenticationProvider(daoAuthenticationProvider());
|
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.security.oauth2.provider.client.BaseClientDetails;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* OAuth2 客户端信息
|
||||||
|
*/
|
||||||
@Service
|
@Service
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public class ClientDetailsServiceImpl implements ClientDetailsService {
|
public class ClientDetailsServiceImpl implements ClientDetailsService {
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
package com.youlai.auth.security.core.userdetails.member;
|
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.Result;
|
||||||
import com.youlai.common.result.ResultCode;
|
import com.youlai.common.result.ResultCode;
|
||||||
import com.youlai.mall.ums.api.MemberFeignClient;
|
import com.youlai.mall.ums.api.MemberFeignClient;
|
||||||
|
@ -58,14 +58,14 @@ public class JwtUtils {
|
|||||||
/**
|
/**
|
||||||
* 获取登录认证的客户端ID
|
* 获取登录认证的客户端ID
|
||||||
*
|
*
|
||||||
* 兼容两种方式获取Oauth2客户端信息(client_id、client_secret)
|
* 兼容两种方式获取OAuth2客户端信息(client_id、client_secret)
|
||||||
* 方式一:client_id、client_secret放在请求路径中
|
* 方式一:client_id、client_secret放在请求路径中
|
||||||
* 方式二:放在请求头(Request Headers)中的Authorization字段,且经过加密,例如 Basic Y2xpZW50OnNlY3JldA== 明文等于 client:secret
|
* 方式二:放在请求头(Request Headers)中的Authorization字段,且经过加密,例如 Basic Y2xpZW50OnNlY3JldA== 明文等于 client:secret
|
||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
public static String getOAuthClientId() {
|
public static String getOAuth2ClientId() {
|
||||||
String clientId;
|
String clientId;
|
||||||
|
|
||||||
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
|
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
|
||||||
|
Loading…
Reference in New Issue
Block a user