- 新增一个UserDetailsExpand,继承User(注意是Spring Security的User),添加一些想要扩展的字段
@Getter
@Setter
public class UserDetailsExpand extends User {
public UserDetailsExpand(String username, String password, Collection<? extends GrantedAuthority> authorities) {
super(username, password, authorities);
}
//扩展的信息写这
private String id;
//电子邮箱
private String email;
//手机号
private String mobile;
private String nickname;
}
- 在UserDetailsService中返回定义的扩展UserDetailsExpand
@Component("UsernamePasswordUserDetailService")
public class UsernamePasswordUserDetailService implements UserDetailsService {
@Autowired
private UserMapper userMapper;
@Override
public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
User user = userMapper.loadUserByUsername(s);
List<String> permissions = new ArrayList<>();
permissions.add("p1");
String[] authorities = permissions.toArray(new String[0]);
UserDetails userDetails = org.springframework.security.core.userdetails.User.withUsername(user.getUsername()).password(user.getPassword()).authorities(authorities).build();
UserDetailsExpand userDetailsExpand = new UserDetailsExpand(userDetails.getUsername(), userDetails.getPassword(), userDetails.getAuthorities());
userDetailsExpand.setId(user.getId());
userDetailsExpand.setEmail(user.getEmail());
userDetailsExpand.setMobile(user.getMobile());
userDetailsExpand.setNickname(user.getNickname());
return userDetailsExpand;
}
}
- 新增一个TokenEnhancer
/**
* @ClassName MyTokenEnhancer
* @Description TODO
* @Author CY
* @Date 2023/11/22 16:02
* @Version 1.0
*/
@Slf4j
@Component("MyTokenEnhancer")
public class MyTokenEnhancer implements TokenEnhancer {
@Autowired
private ObjectMapper objectMapper;
@Override
public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentication authentication) {
Map<String,Object> additionalInfo = new HashMap<>();
Object principal = authentication.getPrincipal();
try {
String s = objectMapper.writeValueAsString(principal);
log.info("{}",s);
Map map = objectMapper.readValue(s, Map.class);
//将一些不想要的字段剔除
map.remove("password");
map.remove("authorities");
map.remove("accountNonExpired");
map.remove("accountNonLocked");
map.remove("credentialsNonExpired");
map.remove("enabled");
additionalInfo.put("user_info",map);
((DefaultOAuth2AccessToken)accessToken).setAdditionalInformation(additionalInfo);
} catch (IOException e) {
log.error("",e);
}
return accessToken;
}
}
- 在配置AuthorizationServerTokenServices时添加定义的TokenEnhancer:
@Bean(name="authorizationServerTokenServicesCustom")
public AuthorizationServerTokenServices tokenService() {
DefaultTokenServices service=new DefaultTokenServices();
service.setSupportRefreshToken(true);//支持刷新令牌
service.setTokenStore(tokenStore);//令牌存储策略
TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain();
//配置扩展信息,一定要将自定义的TokenEnhancer放在前面,否则无效
tokenEnhancerChain.setTokenEnhancers(Arrays.asList(myTokenEnhancer,accessTokenConverter));
service.setTokenEnhancer(tokenEnhancerChain);
service.setClientDetailsService(clientDetails());//设置客户端信息
service.setAccessTokenValiditySeconds(7200); // 令牌默认有效期2小时
service.setRefreshTokenValiditySeconds(259200); // 刷新令牌默认有效期3天
return service;
}
//配置扩展信息,一定要将自定义的TokenEnhancer放在前面,否则无效
这是为什么呢?
因为JwtAccessTokenConverter也是一个TokenEnhancer,他会从map中取出值,然后生成token。如果自定义的tokenEnhancer放在了JwtAccessTokenConverter的后面,那token已经生成了,所以就无效了。
public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentication authentication) {
DefaultOAuth2AccessToken result = new DefaultOAuth2AccessToken(accessToken);
Map<String, Object> info = new LinkedHashMap<String, Object>(accessToken.getAdditionalInformation());
String tokenId = result.getValue();
if (!info.containsKey(TOKEN_ID)) {
info.put(TOKEN_ID, tokenId);
}
else {
tokenId = (String) info.get(TOKEN_ID);
}
result.setAdditionalInformation(info);//将自定义的放入
result.setValue(encode(result, authentication));//将自定义的信息一起生成token