从OAuth授权服务器发送一些其他信息,这是Resource Server上的自定义UserDetails
类内(最好是SpringSecurity Principal内)所需的。
当前方法是将用户名设置为Principal,并添加其他信息作为Authentication对象的其他详细信息。
public class CustomAccessTokenConverter extends JwtAccessTokenConverter{
@Override
public OAuth2Authentication extractAuthentication(Map<String, ?> claims) {
OAuth2Authentication authentication = super.extractAuthentication(claims);
CustomUserDetails userDetails = new CustomUserDetails ();
userDetails.setUserId(((Integer)claims.get("id")).longValue());
userDetails.setName((String) claims.get("name"));
userDetails.setLastName((String) claims.get("lastName"));
authentication.setDetails(userDetails);
return authentication;
}
}
这种方法的好处是我们可以从应用程序内的任何位置访问自定义UserDetails。糟糕的是,Pricipal对象被限制为仅用户名,而我们需要更多代码来访问自定义UserDetails。
// preferable way
(UserAuthDetails) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
// current solution
(UserAuthDetails) ((OAuth2AuthenticationDetails) SecurityContextHolder.getContext().getAuthentication().getDetails()).getDecodedDetails();
是否有使用JwtAccessTokenConverter
的更干净的解决方案,但仍然可以将Principal设置为自定义UserDetails,而不是将其设置为(无用的)用户名并发送其他信息作为Authentication对象的详细信息?
答案 0 :(得分:0)
我不能说这是否是首选的解决方案,但是我自己尝试解决相同的问题后,我最终扩展了DefaultUserAuthenticationConverter
。
所以你可以做这样的事情
@Bean
public JwtAccessTokenConverter accessTokenConverter() {
DefaultAccessTokenConverter defaultConverter = new DefaultAccessTokenConverter();
defaultConverter.setUserTokenConverter(new CustomUserAuthenticationConverter());
JwtAccessTokenConverter jwtConverter = new JwtAccessTokenConverter();
converter.setAccessTokenConverter(defaultConverter);
return converter;
}
然后DefaultUserAuthenticationConverter不能很好地扩展,因为大多数方法和属性都是私有的。但这是一个例子
public class CustomUserAuthenticationConverter extends DefaultUserAuthenticationConverter {
private static final String CUST_PROP = "custProp";
@Override
public Authentication extractAuthentication(Map<String, ?> map) {
if (map.containsKey(USERNAME) && map.containsKey(CUST_PROP)) {
String username = (String) map.get(USERNAME);
String custProp = (String) map.get(CUST_PROP);
CustomPrincipal principal = new CustomPrincipal();
pricipal.setUsername(username);
pricipal.setCustomProp(custProp);
Collection<? extends GrantedAuthority> authorities = getAuthorities(map);
return new UsernamePasswordAuthenticationToken(user, "N/A", authorities);
}
return null;
}
private Collection<? extends GrantedAuthority> getAuthorities(Map<String, ?> map) {
//Copy this method from DefaultUserAuthenticationConverter or create your own.
}
}