在我们的微服务中,每个经过身份验证的Spring Security用户都有一个关联的特定于应用程序的数据结构。 在思考我们如何能够轻松地将这些数据与用户一起缓存时,我们认为如果能够像这样完成这样做会很好:
在创建用户时将缓存数据添加到内存中身份验证中:
public void configureGlobal(AuthenticationManagerBuilder auth) {
auth.inMemoryAuthentication().withUser("user").password("123").roles("ROLE");
auth.inMemoryAuthentication().withUser("user").cache(appDate);
...
}
在@RestController方法中提取数据:
@RequestMapping("/foo")
public void foo() {
User user = (User)SecurityContextHolder.getContext().getAuthentication().getPrincipal();
Object details = SecurityContextHolder.getContext().getAuthentication().getDetails();
Object cachedAppDate= SecurityContextHolder.getContext().getAuthentication().getCachedData();
}
显然,粗体方法是愿望清单,不存在。 有关如何使用现有Spring Security框架轻松完成此任务的建议吗?
谢谢!
答案 0 :(得分:0)
如果只使用用户名(无需密码)可以获取缓存数据,则可以使用实现org.springframework.security.core.userdetails.UserDetailsService
,它只有一个方法 - UserDetails loadUserByUsername(String username)
,并将所需数据作为自定义UserDetail对象返回。在实现接口之后,只需将其传递给AuthenticationManagerBuilder的UserDetailService。
如果您需要密码来获取缓存数据,事情会变得有点复杂。 您应该创建自己的AuthenticationProvider并将缓存的数据放在Principal或UserDetails中。例如,在Principal中设置附加数据的代码:
public class MyProvider implements org.springframework.security.authentication.AuthenticationProvider {
@Override
public boolean supports(Class<? extends Object> authentication) {
return (UsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication));
}
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
UsernamePasswordAuthenticationToken token = (UsernamePasswordAuthenticationToken) authentication;
... // check login/password
Object cachedAppDate = "i'm cached data!";
MyUser user = new MyUser(token, cachedData);
UsernamePasswordAuthenticationToken output = new UsernamePasswordAuthenticationToken(user, authentication.getCredentials(), user.getAuthorities());
output.setDetails(authentication.getDetails());
return output;
}
}
public static class MyUser extends org.springframework.security.core.userdetails.User {
private final Object cachedData;
public User(UsernamePasswordAuthenticationToken token, Object cachedData) {
super(token.getName(), "", token.getAuthorities());
this.cachedData = cachedData;
}
public Object getCachedData() {
return this.cachedData;
}
}
并将缓存的数据作为((MyUser)SecurityContextHolder.getContext().getAuthentication().getPrincipal()).getCachedData();