12

What's the proper way to programmatically log a web visitor in under a particular username in Spring and Spring Security 3.1? It seems the way I was doing it under 2.5 has changed a little. I'm sure there's a much better way of doing this now.

Basically, when I create a new user, I need to also log them in at the same time.

at.
  • 50,922
  • 104
  • 292
  • 461

4 Answers4

19

Create an Authentication (usually a UsernamePasswordAuthenticationToken) and then call

SecurityContextHolder.getContext().setAuthentication(authentication)
sourcedelica
  • 23,940
  • 7
  • 66
  • 74
  • 1
    and set the password of a UsernamePasswordAuthenticationToken to an empty string? Seems so in-elegant for something I have to imagine is so commonly needed. What webapp nowadays doesn't auto-log you in when signing up? At least with limited permissions... – at. Sep 30 '11 at 23:28
  • Then implement your own Authentication, or subclass AbstractAuthenticationToken. – sourcedelica Oct 01 '11 at 01:03
  • curious why there isn't already a simple, even declarative, way to programmatically log people in? At least a password-less AuthenticationToken.. – at. Oct 01 '11 at 01:06
  • 1
    You don't have to use an empty string, you can use the password they registered with. – sourcedelica Oct 01 '11 at 01:30
  • 1
    I guess for the specific situation of a new user registration that makes sense, but otherwise like most websites I don't store plaintext passwords and even if I did it's an unnecessary lookup. – at. Oct 01 '11 at 03:08
  • I have tried this, however my custom user getter methods are available within principal, wheras they when logged in normally ... http://stackoverflow.com/q/7900994/106261 – NimChimpsky Oct 26 '11 at 13:35
  • @at. UsernamePasswordAuthenticationToken doesnt require password in plain text. It uses hashed password so you can just take it from database for any user. You can delete your comments because they can mislead people – jgr May 21 '15 at 20:18
4

This three lines of code do the work for me:

        Authentication request = new UsernamePasswordAuthenticationToken( username, password );
    Authentication result = authenticationManager.authenticate( request );
    SecurityContextHolder.getContext().setAuthentication( result );
Raul Luna
  • 1,945
  • 1
  • 17
  • 26
2

If you are interested in doing this for testing purposes you can do this:

    UserDetails user = _userService.loadUserByUsername(username);
    TestingAuthenticationToken token = new TestingAuthenticationToken(user,null);
    SecurityContextHolder.getContext().setAuthentication(token);

Where user service is your thing that implements UserDetailsService

JonnyRaa
  • 7,559
  • 6
  • 45
  • 49
0

You can write a custom UsernamePasswordAuthenticationFilter that extends Spring's UsernamePasswordAuthenticationFilter.

Here is the code:

import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.authentication.WebAuthenticationDetails;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class CustomUsernamePasswordAuthenticationFilter extends UsernamePasswordAuthenticationFilter {
    @Override
    protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, Authentication authResult) throws IOException, ServletException {
        super.successfulAuthentication(request, response, authResult);
        UsernamePasswordAuthenticationToken token = (UsernamePasswordAuthenticationToken) authResult;
        WebAuthenticationDetails details = (WebAuthenticationDetails) token.getDetails();
        String address = details.getRemoteAddress();
        User user = (User) authResult.getPrincipal();
        String userName = user.getUsername();
        System.out.println("Successful login from remote address: " + address + " by username: "+ userName);
    }

    @Override
    protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed) throws IOException, ServletException {
        super.unsuccessfulAuthentication(request, response, failed);
        UsernamePasswordAuthenticationToken token = (UsernamePasswordAuthenticationToken) failed.getAuthentication();
        WebAuthenticationDetails details = (WebAuthenticationDetails) token.getDetails();
        String address = details.getRemoteAddress();
        System.out.println("Failed login try from remote address: " + address);
    }
}
kamaci
  • 72,915
  • 69
  • 228
  • 366
  • I'm not understanding how this solves the problem of auto-logging in someone upon signup. – at. Sep 30 '11 at 23:28
  • Is this what you looking for: forum.springsource.org/showthread.php?28165-Automatic-login-after-user-registration – kamaci Oct 02 '11 at 08:34
  • I didn't know the authorities will automatically be looked up with `authenticationManager.authenticate(token)`. Thanks. – at. Oct 03 '11 at 00:01