Commit 3eb444be by tangyi

修复refresh token失败问题

parent 21f4f0c1
......@@ -21,17 +21,17 @@ public enum LoginTypeEnum {
/**
* 验证码登录
*/
SMS("SMS", "验证码登录", "/api/v1/mobile/token"),
SMS("SMS", "验证码登录", "/mobile/token"),
/**
* QQ登录
*/
QQ("QQ", "QQ登录", "/api/v1/mobile/token"),
QQ("QQ", "QQ登录", "/mobile/token"),
/**
* 微信登录
*/
WECHAT("WX", "微信登录", "/api/v1/wx/token");
WECHAT("WX", "微信登录", "/wx/token");
/**
* 类型
......
......@@ -29,12 +29,12 @@ public class SecurityConstant {
/**
* 手机登录URL
*/
public static final String MOBILE_TOKEN_URL = "/api/v1/mobile/token";
public static final String MOBILE_TOKEN_URL = "/mobile/token";
/**
* 微信登录URL
*/
public static final String WX_TOKEN_URL = "/api/v1/wx/token";
public static final String WX_TOKEN_URL = "/wx/token";
/**
* 租户编号请求头
......
......@@ -3,6 +3,7 @@ package com.github.tangyi.common.security.core;
import com.github.tangyi.common.security.mobile.MobileUser;
import com.github.tangyi.common.security.wx.WxUser;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
/**
......@@ -11,7 +12,7 @@ import org.springframework.security.core.userdetails.UsernameNotFoundException;
* @author tangyi
* @date 2019/5/28 21:05
*/
public interface CustomUserDetailsService {
public interface CustomUserDetailsService extends UserDetailsService {
/**
* 根据用户名和租户标识查询
......
......@@ -110,6 +110,8 @@ ignore:
- /health
- /metrics/**
- /loggers/**
- /mobile/token
- /wx/token
# 集群ID生成配置
cluster:
......
......@@ -117,6 +117,9 @@ ignore:
- /
- /error
- /favicon.ico
- /csrf
- /*swagger*/**
- /**/*swagger*/**
- /actuator/**
- /api/auth/**
- /api/user/**
......
......@@ -11,7 +11,7 @@ Auth Service
#### 账号密码+图片验证码登录
POST:`/api/auth/api/v1//token?grant_type=password&scope=read&username=admin&credential=lBTqrKS0kZixOFXeZ0HRng==&randomStr=86111562225179514&code=mf3f`
POST:`/api/auth/api/v1/token?grant_type=password&scope=read&username=admin&credential=lBTqrKS0kZixOFXeZ0HRng==&randomStr=86111562225179514&code=mf3f`
url参数:
```
......
package com.github.tangyi.auth.config;
import com.github.tangyi.auth.security.CustomTokenConverter;
import com.github.tangyi.auth.security.CustomTokenServices;
import com.github.tangyi.auth.security.CustomUserDetailsByNameServiceWrapper;
import com.github.tangyi.common.security.core.ClientDetailsServiceImpl;
import com.github.tangyi.common.security.core.CustomUserDetailsService;
import com.github.tangyi.common.security.exception.CustomOauthException;
import com.nimbusds.jose.JWSAlgorithm;
import com.nimbusds.jose.jwk.JWKSet;
......@@ -15,7 +18,9 @@ import org.springframework.context.annotation.Lazy;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.security.authentication.ProviderManager;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
import org.springframework.security.core.token.TokenService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.oauth2.common.exceptions.OAuth2Exception;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
......@@ -29,10 +34,12 @@ import org.springframework.security.oauth2.provider.token.TokenStore;
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.redis.RedisTokenStore;
import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationProvider;
import javax.sql.DataSource;
import java.security.KeyPair;
import java.security.interfaces.RSAPublicKey;
import java.util.Arrays;
import java.util.Collections;
/**
......@@ -61,13 +68,16 @@ public class CustomAuthorizationServerConfigurer extends AuthorizationServerConf
*/
private final KeyProperties keyProperties;
private final CustomUserDetailsService userDetailsService;
@Autowired
public CustomAuthorizationServerConfigurer(RedisConnectionFactory redisConnectionFactory,
DataSource dataSource,
KeyProperties keyProperties) {
KeyProperties keyProperties, CustomUserDetailsService userDetailsService) {
this.redisConnectionFactory = redisConnectionFactory;
this.dataSource = dataSource;
this.keyProperties = keyProperties;
this.userDetailsService = userDetailsService;
}
/**
......@@ -80,6 +90,36 @@ public class CustomAuthorizationServerConfigurer extends AuthorizationServerConf
return new RedisTokenStore(redisConnectionFactory);
}
/**
* 防止刷新token是调用默认的loadUserByUsername,需要自定义tokenService
* @param endpoints endpoints
* @return CustomTokenServices
*/
private CustomTokenServices tokenService(AuthorizationServerEndpointsConfigurer endpoints) {
CustomTokenServices tokenServices = new CustomTokenServices();
tokenServices.setTokenStore(tokenStore());
tokenServices.setSupportRefreshToken(true);
tokenServices.setReuseRefreshToken(true);
tokenServices.setAccessTokenValiditySeconds(-1);
tokenServices.setClientDetailsService(endpoints.getClientDetailsService());
tokenServices.setTokenEnhancer(jwtTokenEnhancer());
addUserDetailsService(tokenServices, userDetailsService);
return tokenServices;
}
/**
* PreAuthenticatedAuthenticationProvider自定义userDetailsService
* @param tokenServices tokenServices
* @param userDetailsService userDetailsService
*/
private void addUserDetailsService(CustomTokenServices tokenServices, CustomUserDetailsService userDetailsService) {
if (userDetailsService != null) {
PreAuthenticatedAuthenticationProvider provider = new PreAuthenticatedAuthenticationProvider();
provider.setPreAuthenticatedUserDetailsService(new CustomUserDetailsByNameServiceWrapper<>(userDetailsService));
tokenServices.setAuthenticationManager(new ProviderManager(Collections.singletonList(provider)));
}
}
/**
* 生成KeyPair
* @return KeyPair
......@@ -141,6 +181,7 @@ public class CustomAuthorizationServerConfigurer extends AuthorizationServerConf
.authenticationManager(this.authenticationConfiguration.getAuthenticationManager())
// 将token存储到redis
.tokenStore(tokenStore())
.tokenServices(tokenService(endpoints))
// token增强
.tokenEnhancer(jwtTokenEnhancer())
// 异常转换
......
package com.github.tangyi.auth.security;
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.util.Assert;
/**
* @author tangyi
* @date 2020-04-19 11:32
*/
public class CustomUserDetailsByNameServiceWrapper<T extends Authentication> implements AuthenticationUserDetailsService<T>, InitializingBean {
private UserDetailsService userDetailsService = null;
public CustomUserDetailsByNameServiceWrapper() {
}
public CustomUserDetailsByNameServiceWrapper(UserDetailsService userDetailsService) {
Assert.notNull(userDetailsService, "userDetailsService cannot be null.");
this.userDetailsService = userDetailsService;
}
public void afterPropertiesSet() {
Assert.notNull(this.userDetailsService, "UserDetailsService must be set");
}
public UserDetails loadUserDetails(T authentication) throws UsernameNotFoundException {
return this.userDetailsService.loadUserByUsername(authentication.getName());
}
public void setUserDetailsService(UserDetailsService aUserDetailsService) {
this.userDetailsService = aUserDetailsService;
}
}
......@@ -15,6 +15,7 @@ import com.github.tangyi.common.core.utils.ResponseUtil;
import com.github.tangyi.common.security.core.CustomUserDetailsService;
import com.github.tangyi.common.security.core.GrantedAuthorityImpl;
import com.github.tangyi.common.security.mobile.MobileUser;
import com.github.tangyi.common.security.tenant.TenantContextHolder;
import com.github.tangyi.common.security.wx.WxUser;
import com.github.tangyi.user.api.dto.UserDto;
import com.github.tangyi.user.api.enums.IdentityType;
......@@ -48,6 +49,25 @@ public class CustomUserDetailsServiceImpl implements CustomUserDetailsService {
/**
* 加载用户信息
* @param username username
* @return UserDetails
* @throws UsernameNotFoundException
*/
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
long start = System.currentTimeMillis();
ResponseBean<UserVo> userVoResponseBean = userServiceClient.findUserByIdentifier(username, TenantContextHolder.getTenantCode());
if (!ResponseUtil.isSuccess(userVoResponseBean))
throw new ServiceException(GET_USER_INFO_FAIL + userVoResponseBean.getMsg());
UserVo userVo = userVoResponseBean.getData();
if (userVo == null)
throw new UsernameNotFoundException("user does not exist");
return new CustomUserDetails(username, userVo.getCredential(), CommonConstant.STATUS_NORMAL.equals(userVo.getStatus()), getAuthority(userVo), userVo.getTenantCode(), userVo.getId(), start, LoginTypeEnum.PWD);
}
/**
* 加载用户信息
*
* @param tenantCode 租户标识
* @param username 用户名
......
......@@ -26,7 +26,7 @@ public class ValidateTenantAspect {
private final UserServiceClient userServiceClient;
@Before("execution(* com.github.tangyi.auth.security.CustomUserDetailsServiceImpl.load*(..)) && args(tenantCode,..)")
@Before("execution(* com.github.tangyi.auth.security.CustomUserDetailsServiceImpl.*AndTenantCode(..)) && args(tenantCode,..)")
public void validateTenantCode(String tenantCode) throws TenantNotFoundException {
// 获取tenantCode
if (StringUtils.isBlank(tenantCode))
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment