【问题标题】:Spring security guest userSpring安全访客用户
【发布时间】:2017-11-17 09:16:55
【问题描述】:

我有一个自定义的 UserDetails 实现,它有一个购物车属性。

class MyUserDetails implement UserDetails {
    private Cart cart;
    // getters & setters + other properties....
}

我也希望匿名用户成为 MyUserDetails 的一个实例,到目前为止我已经让它工作,但所有匿名用户都有相同的购物车!

@Override
protected void configure(HttpSecurity http) throws Exception {
    MyUserDetails anonymousUser = new MyUserDetails();
    anonymousUser.setUsername("anonymousUser");
    http.anonymous().principal(anonymousUser);
    ...
}

我如何能够为每个会话为匿名用户返回一个新的 MyUserDetails 实例?

【问题讨论】:

  • 我想说的写法是在你的会话中有购物车。您的身份验证不需要购物车。 UserDetails 应该只包含核心用户信息。
  • @dur 我认为购物车可能属于用户。例如,如果我希望注册用户的购物车在登录之间或不同设备之间持续存在。
  • 当然是用户的一部分,但这并不意味着它应该是UserDetails的一部分。您可以将购物车放入会话中或从数据库中加载它。这与UserDetails 无关。

标签: java spring spring-mvc spring-boot spring-security


【解决方案1】:

我很确定我设法通过创建这样的自定义 AnonymousAuthenticationFilter 使其工作:

public class MyAnonymousAuthenticationFilter extends AnonymousAuthenticationFilter {
    private static final String USER_SESSION_KEY = "user";
    private final String key;

    public MyAnonymousAuthenticationFilter(String key) {
        super(key);
        this.key = key;
    }

    @Override
    protected Authentication createAuthentication(HttpServletRequest req) {
        HttpSession httpSession = req.getSession();
        MyUserDetails user = Optional.ofNullable((MyUserDetails) httpSession.getAttribute(USER_SESSION_KEY))
                .orElseGet(() -> {
                    MyUserDetails anon = new MyUserDetails();
                    anon.setUsername("anonymousUser");
                    httpSession.setAttribute(USER_SESSION_KEY, anon);
                    return anon;
                });
        return new AnonymousAuthenticationToken(key, user, AuthorityUtils.createAuthorityList("ROLE_ANONYMOUS"));
    }
}

然后与http.anonymous().authenticationFilter(new MyAnonymousAuthenticationFilter(UUID.randomUUID().toString()));一起使用

如果这种方法有问题,或者如果您知道更好的方法,请告诉我!

【讨论】:

  • 用户总是匿名的吗?还是针对特定的 url 模式?
【解决方案2】:

我的第一句话是我倾向于同意@dur 的 cmets,但这是另一回事 :-)

如果你仍然喜欢坚持你的方法,那么我认为如果你不是过滤器,它会更符合 Spring 架构 实现您自己的AuthenticationProvider,它能够处理(验证)匿名令牌。像这样:

public class MyAuthenticationProvider implements AuthenticationProvider {

  @Override
  public Authentication authenticate(Authentication authentication) throws AuthenticationException {

    //enrich the authentication here.
  }


  @Override
  public boolean supports(Class<?> authentication) {
    return (AnonymousAuthenticationToken.class
        .isAssignableFrom(authentication));
  }
}

然后,您将在您的过滤器链中注册此提供程序,例如,可能由WebSecurityConfigurerAdapter 初始化。您将通过配置本地身份验证管理器来完成此操作。这看起来像这样:

@Override
protected void configure(
    AuthenticationManagerBuilder auth) throws Exception {
    auth.authenticationProvider(new MyAuthenticationProvider());
}

如需深入了解 Spring 安全架构,请参阅 here

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-10-31
    • 2012-06-30
    • 2013-12-15
    • 1970-01-01
    • 2016-06-27
    • 2018-11-17
    • 2016-12-27
    • 1970-01-01
    相关资源
    最近更新 更多