前面三篇文章分别整合了Spring Security 与 Oauth2.0 与Jwt,这篇文章主要记录在它们基础之上放一些自定义信息在Token里面
Springboot整合Spring Security Oauth2.0 + JWT (一)
Springboot整合Spring Security Oauth2.0 + JWT (二)
Springboot整合Spring Security Oauth2.0 + JWT (三)
修改UserDetailsServiceImpl
修改loadUserByUsername方法,这里返回我们自定义需要的信息,需要返回一个UserDetails的实现类
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = userService.getByUsername(username);
if (user == null)
return null;
List<Permission> permissionList = permissionService.queryByUserId(user.getId());
List<String> permissions = new ArrayList<>();
if (permissionList != null && !permissionList.isEmpty())
permissionList.stream().forEach(permission -> {
permissions.add(permission.getEnname());
});
return new CustomUserDetails(user.getId(), username, user.getPassword(), user.getName(), user.getPhone(), permissions);
}
自定义UserDetails
public class CustomUserDetails implements Serializable, UserDetails {
private static final long serialVersionUID = 3795011598734000565L;
@JsonFormat(shape = JsonFormat.Shape.STRING)
private Long id;
private String username;
private String password;
private String name;
private String phone;
private List<String> permissions;
public CustomUserDetails() {
}
public CustomUserDetails(Long id, String username, String password, String name, String phone, List<String> permissions) {
this.id = id;
this.username = username;
this.password = password;
this.name = name;
this.phone = phone;
this.permissions = permissions;
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
List<GrantedAuthority> grantedAuthorityList = new ArrayList<>();
if (this.getPermissions() != null && !this.getPermissions().isEmpty())
this.getPermissions().stream().forEach(permission -> {
grantedAuthorityList.add(new SimpleGrantedAuthority(permission));
});
return grantedAuthorityList;
}
@Override
@JsonIgnore
public String getPassword() {
return this.password;
}
@Override
public String getUsername() {
return this.username;
}
@Override
@JsonIgnore
public boolean isAccountNonExpired() {
return true;
}
@Override
@JsonIgnore
public boolean isAccountNonLocked() {
return true;
}
@Override
@JsonIgnore
public boolean isCredentialsNonExpired() {
return true;
}
@Override
@JsonIgnore
public boolean isEnabled() {
return true;
}
public Long getId() {
return id;
}
public String getName() {
return name;
}
public String getPhone() {
return phone;
}
public List<String> getPermissions() {
return permissions;
}
}
自定义TokenEnhancer令牌增强器,添加我们需要的信息
这里map尽量不要放返回结果已经存在的key,会覆盖
public class CustomTokenEnhancer implements TokenEnhancer {
@Override
public OAuth2AccessToken enhance(OAuth2AccessToken oAuth2AccessToken, OAuth2Authentication oAuth2Authentication) {
CustomUserDetails userInfo = (CustomUserDetails) oAuth2Authentication.getPrincipal();
Map<String, Object> additionalInfo = new HashMap<>();
additionalInfo.put("id", userInfo.getId().toString());
additionalInfo.put("permissions", userInfo.getPermissions());
additionalInfo.put("username", userInfo.getUsername());
additionalInfo.put("name", userInfo.getName());
additionalInfo.put("phone", userInfo.getPhone());
((DefaultOAuth2AccessToken) oAuth2AccessToken).setAdditionalInformation(additionalInfo);
return oAuth2AccessToken;
}
}
修改认证服务器令牌端点
获取token
调用check_token接口
资源服务器获取用户信息
通过刚才的TokenEnhancer可以看到信息是添加到 DefaultOAuth2AccessToken的additionalInformation 中,获取的话也可以通过获取到token,然后拿到Map里面存放的额外信息
这种方式是通过读取token然后解析获得的信息,还可以通过details的DecodeDetails端获取,使用这种方法前,需要在资源服务器中自定义一个 访问令牌转换器 CustomAccessTokenConverter,这个demo是认证服务器和资源服务器放在一起的,直接定义就好了,如果是如果是微服务架构的话,每一个资源服务如果要这样子获取的话,需要都定义
@Component
public class CustomAccessTokenConverter extends DefaultAccessTokenConverter {
@Override
public OAuth2Authentication extractAuthentication(Map<String, ?> claims) {
OAuth2Authentication authentication
= super.extractAuthentication(claims);
authentication.setDetails(claims);
return authentication;
}
}
然后在jwt令牌服务里面配置
注意如果是微服务架构的话,这个JwtTokenConfig和CustomAccessTokenConvert每一个资源服务都要有一个
测试decodeDetails方式获取