使用Spring Security缓存用户特定的应用程序数据

时间:2017-01-13 09:09:17

标签: spring spring-mvc spring-security

在我们的微服务中,每个经过身份验证的Spring Security用户都有一个关联的特定于应用程序的数据结构。 在思考我们如何能够轻松地将这些数据与用户一起缓存时,我们认为如果能够像这样完成这样做会很好:

  1. 在创建用户时将缓存数据添加到内存中身份验证中:

    public void configureGlobal(AuthenticationManagerBuilder auth) {
        auth.inMemoryAuthentication().withUser("user").password("123").roles("ROLE");
        auth.inMemoryAuthentication().withUser("user").cache(appDate);
        ...
    }
    
  2. 在@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();    
    }
    
  3. 显然,粗体方法是愿望清单,不存在。 有关如何使用现有Spring Security框架轻松完成此任务的建议吗?

    谢谢!

1 个答案:

答案 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();

进行访问