springboot OAuth2 jwt的几个问题及解决
首先说明自己的问题, 基本的集成的话可以参考其他的博文
一. 在jwt的payload中加入自定义的一些信息 网上的看到很多是通过TokenEhancer添加, 跟踪源码后发现添加不进去;
二. jwt的过期时间设置 ;
对于第一个问题:在jwt的payload中加入自定义的一些信息
有2个解决方案,
1.1一个是原始的解决方案, 我是直接重写了DefaultUserAuthenticationConverter的convertUserAuthentication()方法
package com.gee.spring.boot.oauth2.auth.config.oauth2.token;
import com.gee.spring.boot.oauth2.auth.entity.AuthUser;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.oauth2.provider.token.DefaultUserAuthenticationConverter;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* desc:
*
* @author gee
* @date 2020/04/06 18:26
*/
public class GeeUserAuthenticationConverter extends DefaultUserAuthenticationConverter {
@Override
public Map<String, ?> convertUserAuthentication(Authentication authentication) {
AuthUser authUser = (AuthUser)authentication.getPrincipal();
Map<String, Object> response = new LinkedHashMap<>();
response.put("user_name", authUser.getUsername());
response.put("user_id", authUser.getId());
if (authentication.getAuthorities() != null && !authentication.getAuthorities().isEmpty()) {
response.put("authorities", AuthorityUtils.authorityListToSet(authentication.getAuthorities()));
}
return response;
}
}
然后在token的配置中,将自己的GeeUserAuthenticationConverter 设置在JwtAccessTokenConverter中
/**
* desc:
*
* @author gee
* @date 2020/04/06 16:27
*/
@Configuration
public class TokenConfig {
@Bean(value = "jwtTokenStore")
public JwtTokenStore jwtTokenStore(){
return new JwtTokenStore(jwtAccessTokenConverter());
}
@Bean
public JwtAccessTokenConverter jwtAccessTokenConverter(){
JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
converter.setAccessTokenConverter(geeAccessTokenConverter());
converter.setSigningKey(OauthConstant.OAUTH2_JWT_SIGN_KEY);
return converter;
}
private GeeAccessTokenConverter geeAccessTokenConverter(){
GeeAccessTokenConverter accessTokenConverter = new GeeAccessTokenConverter();
//如果要实现往jwt的payload里添加信息, 要设置UserAuthenticationConverter的实现类
GeeUserAuthenticationConverter userAuthenticationConverter = new GeeUserAuthenticationConverter();
accessTokenConverter.setUserTokenConverter(userAuthenticationConverter);
return accessTokenConverter;
}
}
然后Oauth2OuthorizationConig的配置基本没什么区别,这里也直接贴出来
/**
* desc:
*
* @author gee
* @date 2020/04/06 16:29
*/
@Configuration
@EnableAuthorizationServer
public class Oauth2AuthorizationConfig extends AuthorizationServerConfigurerAdapter {
@Resource
private DataSource dataSource;
@Resource
private AuthenticationManager authenticationManager;
@Resource
private JwtTokenStore jwtTokenStore;
@Resource
private JwtAccessTokenConverter jwtAccessTokenConverter;
private ClientDetailsService clientDetailsService(){
return new JdbcClientDetailsService(dataSource);
}
@Bean
public AuthorizationCodeServices authorizationCodeServices(){
return new JdbcAuthorizationCodeServices(dataSource);
}
private DefaultTokenServices tokenServices(){
DefaultTokenServices tokenServices = new DefaultTokenServices();
tokenServices.setTokenStore(jwtTokenStore);
tokenServices.setTokenEnhancer(tokenEnhancerChain());
tokenServices.setClientDetailsService(clientDetailsService());
tokenServices.setSupportRefreshToken(true);
//如果在client的配置中 已经设置了token/refreshToken的过期时间的话, tokenServices中设置的过期时间无效
tokenServices.setAccessTokenValiditySeconds(15*60);
tokenServices.setRefreshTokenValiditySeconds(7*24*60*60);
return tokenServices;
}
private TokenEnhancerChain tokenEnhancerChain(){
TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain();
tokenEnhancerChain.setTokenEnhancers(Collections.singletonList(jwtAccessTokenConverter));
return tokenEnhancerChain;
}
@Override
public void configure(AuthorizationServerSecurityConfigurer security){
security.allowFormAuthenticationForClients()
.checkTokenAccess("isAuthenticated()");
}
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.withClientDetails(clientDetailsService());
}
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
endpoints.authenticationManager(authenticationManager)
.authorizationCodeServices(authorizationCodeServices())
.tokenServices(tokenServices())
;
}
}
1.2第二种比较简单的处理,就是在UserDetailsService.loadUserByUsername()方法将username直接设置成包含需要添加信息的json字符串,属于比较偷懒的写法.
@Service
public class GeeUserDetailServiceImpl implements UserDetailsService {
@Autowired
private UserService userService;
@Autowired
private PasswordEncoder passwordEncoder;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = userService.getByUserName(username);
if (user == null){
return null;
}
Set<GrantedAuthority> authorities = new HashSet<>();
authorities.add(new SimpleGrantedAuthority("1"));
return new org.springframework.security.core.userdetails.User(Json.toString(user),user.getPassword(),authorities);
}
}
2.针对第二个问题, oauth2的配置类中也注释了,
如果在client的配置中 已经设置了token/refreshToken的过期时间的话, tokenServices中设置的过期时间无效
所以jwt中的过期时间会跟client中过期时间保持一致,本用例中是在数据库中配置.
lhttps://gitee.com/gepengjun/springboot-oauth2-jwt.