Programmatically log-in a user using spring securi

2019-01-10 10:01发布

问题:

The opposite of: How to manually log out a user with spring security?

In my app I have register new user screen, which posts to a controller which creates a new user within db (and does a few obvious checks).I then want this new user to be automatically logged in ... I kind of want somethign like this :

SecurityContextHolder.getContext().setPrincipal(MyNewUser);

Edit Well I have almost implemented based on the answer to How to programmatically log user in with Spring Security 3.1

 Authentication auth = new UsernamePasswordAuthenticationToken(MyNewUser, null);
 SecurityContextHolder.getContext().setPrincipal(MyNewUser);

However, when deployed the jsp can not access my MyNewUser.getWhateverMethods() whereas it does when normal login procedure followed. the code that works nomrally, but throws an error when logged in like above is below :

<sec:authentication property="principal.firstname" /> 

回答1:

In my controller i have this, which logs user in as normal :

Authentication auth = 
  new UsernamePasswordAuthenticationToken(user, null, user.getAuthorities());

SecurityContextHolder.getContext().setAuthentication(auth);

Where user is my custom user object(implementing UserDetails) that is newly created. The getAuthorities() method does this (just because all my users have the same role):

public Collection<GrantedAuthority> getAuthorities() {
        //make everyone ROLE_USER
        Collection<GrantedAuthority> grantedAuthorities = new ArrayList<GrantedAuthority>();
        GrantedAuthority grantedAuthority = new GrantedAuthority() {
            //anonymous inner type
            public String getAuthority() {
                return "ROLE_USER";
            }
        }; 
        grantedAuthorities.add(grantedAuthority);
        return grantedAuthorities;
    }


回答2:

You can also inject your spring security configured UserDetailsManager to your controller and use that to get the UserDetails which holds the principal and authorities to avoid duplicate code:

// inject

@Autowired
private UserDetailsManager manager; 

// use in your method

UserDetails userDetails = manager.loadUserByUsername (token.getUsername ());
Authentication auth = new UsernamePasswordAuthenticationToken (userDetails.getUsername (),userDetails.getPassword (),userDetails.getAuthorities ());
SecurityContextHolder.getContext().setAuthentication(auth);


回答3:

From the spring security source AbstractAuthenticationProcessingFilter:

protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response,
        Authentication authResult) throws IOException, ServletException {

    if (logger.isDebugEnabled()) {
        logger.debug("Authentication success. Updating SecurityContextHolder to contain: " + authResult);
    }

    // you need this
    SecurityContextHolder.getContext().setAuthentication(authResult);

    rememberMeServices.loginSuccess(request, response, authResult);

    if (this.eventPublisher != null) {
        eventPublisher.publishEvent(new InteractiveAuthenticationSuccessEvent(authResult, this.getClass()));
    }

    successHandler.onAuthenticationSuccess(request, response, authResult);
}

Note however that the SecurityContextHolder is usually cleared upon completion of the filter chain.