oauth2在jwt仅支持用户名和权限。
以下方法实现 token 中添加自定义的参数:
-
自定义 UserDetails
public class CustomerDetails implements UserDetails {
private String id;
private String username;
private String password;
private Set<GrantedAuthority> authorities;
private boolean accountNonExpired;
private boolean accountNonLocked;
private boolean credentialsNonExpired;
private boolean enabled;
public CustomerDetails() {
authorities = new HashSet<GrantedAuthority>();
}
public void isConfig() {
this.accountNonExpired = true;
this.accountNonLocked = true;
this.credentialsNonExpired = true;
this.enabled = true;
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return authorities;
}
public void addAuthorities(GrantedAuthority authority) {
authorities.add(authority);
}
public void setAuthorities(Collection<? extends GrantedAuthority> authorities) {
this.authorities = Collections.unmodifiableSet(sortAuthorities(authorities));
}
private static SortedSet<GrantedAuthority> sortAuthorities(Collection<? extends GrantedAuthority> authorities) {
Assert.notNull(authorities, "Cannot pass a null GrantedAuthority collection");
SortedSet<GrantedAuthority> sortedAuthorities = new TreeSet<>(new AuthorityComparator());
for (GrantedAuthority grantedAuthority : authorities) {
Assert.notNull(grantedAuthority, "GrantedAuthority list cannot contain any null elements");
sortedAuthorities.add(grantedAuthority);
}
return sortedAuthorities;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
@Override
public String getPassword() {
return this.password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public String getUsername() {
return this.username;
}
public void setUsername(String username) {
this.username = username;
}
@Override
public boolean isEnabled() {
return this.enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
@Override
public boolean isAccountNonExpired() {
return this.accountNonExpired;
}
public void setAccountNonExpired(boolean accountNonExpired) {
this.accountNonExpired = accountNonExpired;
}
@Override
public boolean isAccountNonLocked() {
return this.accountNonLocked;
}
public void setAccountNonLocked(boolean accountNonLocked) {
this.accountNonLocked = accountNonLocked;
}
@Override
public boolean isCredentialsNonExpired() {
return true; //this.credentialsNonExpired;
}
public void setCredentialsNonExpired(boolean credentialsNonExpired) {
this.credentialsNonExpired = credentialsNonExpired;
}
private static class AuthorityComparator implements Comparator<GrantedAuthority>, Serializable {
private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID;
@Override
public int compare(GrantedAuthority g1, GrantedAuthority g2) {
// Neither should ever be null as each entry is checked before adding it to
// the set. If the authority is null, it is a custom authority and should
// precede others.
if (g2.getAuthority() == null) {
return -1;
}
if (g1.getAuthority() == null) {
return 1;
}
return g1.getAuthority().compareTo(g2.getAuthority());
}
}
}
2. UserDetailsService 中使用上面的 CustomerDetails
@Service
public class UserDaoSecurityService implements UserDetailsService{
@Autowired
private UserDao userDao;
@Autowired
private PermissionDao pDao;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
//读取数据库中的用户信息创建 UserDetails
PiUser user = userDao.findByUsername(username);
CustomerDetails userDetails = new CustomerDetails();
if(user != null) {
List<PiPermission> permissions = pDao.findUserPermissions(user.id);
List<GrantedAuthority> authList = new ArrayList<GrantedAuthority>();
for (PiPermission per : permissions) {
authList.add(new SimpleGrantedAuthority(per.getCode()));
}
userDetails.setId("" + user.id);
userDetails.setUsername(user.username);
userDetails.setPassword(user.password);
userDetails.setAuthorities(authList);
userDetails.isConfig();
//userDetails = User.withUsername(user.username).password(user.password).authorities(authList).build();
}else {
throw new BadCredentialsException("用户名不存在");
}
return userDetails;
}
}
3. 自定义 DefaultAccessTokenConverter
public class JwtCustomerAccessTokenConverter extends DefaultAccessTokenConverter {
public JwtCustomerAccessTokenConverter() {
super.setUserTokenConverter(new CustomerUserAuthenticationConverter());
}
private class CustomerUserAuthenticationConverter extends DefaultUserAuthenticationConverter {
@Override
public Map<String, ?> convertUserAuthentication(Authentication authentication) {
LinkedHashMap<String, Object> response = new LinkedHashMap<String, Object>();
//这里添加你的参数
response.put("id", ((PiUserDetails) authentication.getPrincipal()).getId());
response.put("username", ((PiUserDetails) authentication.getPrincipal()).getUsername());
if (authentication.getAuthorities() != null && !authentication.getAuthorities().isEmpty()) {
response.put("authorities", AuthorityUtils.authorityListToSet(authentication.getAuthorities()));
}
return response;
}
}
}
4. 配置 token 生成策略
@Configuration
public class JwtTokeStoreConfig {
private String KEY = "aaa";
@Bean
public JwtTokenStore tokenStore() {
return new JwtTokenStore(accessTokenConverter());
}
@Bean
public JwtAccessTokenConverter accessTokenConverter() {
JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
converter.setSigningKey(KEY);
//使用自定义的 TokenConverter
converter.setAccessTokenConverter(new JwtCustomerAccessTokenConverter());
return converter;
}
}