一尘不染

如何在Spring Security / SpringMVC中手动设置经过身份验证的用户

spring-mvc

新用户提交“新帐户”表单后,我想手动登录该用户,这样他们就不必登录后续页面。

通过spring安全拦截器的普通表单登录页面工作正常。

在新帐户形式的控制器中,我将创建一个UsernamePasswordAuthenticationToken并在SecurityContext中手动进行设置:

SecurityContextHolder.getContext().setAuthentication(authentication);

稍后,我在同一页面上检查用户的登录身份:

SecurityContextHolder.getContext().getAuthentication().getAuthorities();

这将返回我之前在身份验证中设置的权限。一切都很好。

但是,在我加载的下一页上调用相同的代码时,身份验证令牌只是UserAnonymous。

我不清楚为什么它没有保留我在上一个请求中设置的身份验证。有什么想法吗?

  • 可能与会话ID设置不正确有关吗?
  • 是否有某种方式可能会覆盖我的身份验证?
  • 也许我还需要保存身份验证的另一步骤?
  • 还是我需要做一些事情来在整个会话中声明身份验证,而不是某种程度上的单个请求?

只是寻找一些想法可以帮助我了解这里发生的事情。


阅读 535

收藏
2020-06-01

共1个答案

一尘不染

不久前,我和您有同样的问题。我不记得详细信息,但是以下代码对我有用。该代码在Spring
Webflow流中使用,因此在RequestContext和ExternalContext类中使用。但是与您最相关的部分是doAutoLogin方法。

public String registerUser(UserRegistrationFormBean userRegistrationFormBean,
                           RequestContext requestContext,
                           ExternalContext externalContext) {

    try {
        Locale userLocale = requestContext.getExternalContext().getLocale();
        this.userService.createNewUser(userRegistrationFormBean, userLocale, Constants.SYSTEM_USER_ID);
        String emailAddress = userRegistrationFormBean.getChooseEmailAddressFormBean().getEmailAddress();
        String password = userRegistrationFormBean.getChoosePasswordFormBean().getPassword();
        doAutoLogin(emailAddress, password, (HttpServletRequest) externalContext.getNativeRequest());
        return "success";

    } catch (EmailAddressNotUniqueException e) {
        MessageResolver messageResolvable 
                = new MessageBuilder().error()
                                      .source(UserRegistrationFormBean.PROPERTYNAME_EMAIL_ADDRESS)
                                      .code("userRegistration.emailAddress.not.unique")
                                      .build();
        requestContext.getMessageContext().addMessage(messageResolvable);
        return "error";
    }

}


private void doAutoLogin(String username, String password, HttpServletRequest request) {

    try {
        // Must be called from request filtered by Spring Security, otherwise SecurityContextHolder is not updated
        UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(username, password);
        token.setDetails(new WebAuthenticationDetails(request));
        Authentication authentication = this.authenticationProvider.authenticate(token);
        logger.debug("Logging in with [{}]", authentication.getPrincipal());
        SecurityContextHolder.getContext().setAuthentication(authentication);
    } catch (Exception e) {
        SecurityContextHolder.getContext().setAuthentication(null);
        logger.error("Failure in autoLogin", e);
    }

}
2020-06-01