How to automatically login as a user using Spring

2019-02-07 04:16发布

问题:

My application uses Spring Security, and my client requires:

  • users to be able to automatically login after signup.
  • an admin to login as any user without knowing their password.

So I need to figure out how to login as any user automatically without knowing their password.

How can this be accomplished using Spring Security.

回答1:

To get this to work, I had to:

Configure a reference to the UserDetailsService (jdbcUserService)

<authentication-manager>
<authentication-provider>
<jdbc-user-service id="jdbcUserService" data-source-ref="dataSource"
  users-by-username-query="select username,password, enabled from users where username=?" 
  authorities-by-username-query="select u.username, ur.authority from users u, user_roles ur where u.user_id = ur.user_id and u.username =?  " 
/>
</authentication-provider>
</authentication-manager>

Autowire my userDetailsManager in my controller:

@Autowired
@Qualifier("jdbcUserService")  // <-- this references the bean id
public UserDetailsManager userDetailsManager;

In the same controller, authenticate my user like so:

@RequestMapping("/automatic/login/test")
public @ResponseBody String automaticLoginTest(HttpServletRequest request) 
{
    String username = "anyUserName@YourSite.com";

    Boolean result = authenticateUserAndInitializeSessionByUsername(username, userDetailsManager, request);

    return result.toString();
}

public boolean authenticateUserAndInitializeSessionByUsername(String username, UserDetailsManager userDetailsManager, HttpServletRequest request)
{
    boolean result = true;

    try
    {
        // generate session if one doesn't exist
        request.getSession();

        // Authenticate the user
        UserDetails user = userDetailsManager.loadUserByUsername(username);
        Authentication auth = new UsernamePasswordAuthenticationToken(user, null, user.getAuthorities());
        SecurityContextHolder.getContext().setAuthentication(auth);
    }
    catch (Exception e)
    {
      System.out.println(e.getMessage());

      result = false;
    }

    return result;
}

Note that a good precursor to just using spring security for your app can be found here.



回答2:

for second problem

an admin to login as any user without knowing their password.

you should use switch user feature from spring. javadoc and article



回答3:

This is answer to above question In Controller:

@RequestMapping(value = "/registerHere", method = RequestMethod.POST)
    public ModelAndView registerUser(@ModelAttribute("user") Users user, BindingResult result,
            HttpServletRequest request, HttpServletResponse response) {
        System.out.println("register 3");

        ModelAndView mv = new ModelAndView("/home");
        mv.addObject("homePagee", "true");

        String uname = user.getUsername();

        if (userDAO.getUserByName(uname) == null) {

            String passwordFromForm = user.getPassword();
            userDAO.saveOrUpdate(user);

            try {
                authenticateUserAndSetSession(user, passwordFromForm, request);
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }


        }

        System.out.println("register 4");

        log.debug("Ending of the method registerUser");
        return mv;
    }

Further above method in controller is defined as:

`private void authenticateUserAndSetSession(Users user, String passwor`dFromForm, HttpServletRequest request){

        String username = user.getUsername();
        System.out.println("username:  " + username + " password: " + passwordFromForm);                        

        UserDetails userDetails = userDetailsService.loadUserByUsername(user.getUsername());

        UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(username, passwordFromForm, userDetails.getAuthorities());
        request.getSession();

        System.out.println("Line Authentication 1");

        usernamePasswordAuthenticationToken.setDetails(new WebAuthenticationDetails(request));

        System.out.println("Line Authentication 2");

        Authentication authenticatedUser = authenticationManager.authenticate(usernamePasswordAuthenticationToken);

        System.out.println("Line Authentication 3");


        if (usernamePasswordAuthenticationToken.isAuthenticated()) {
            SecurityContextHolder.getContext().setAuthentication(authenticatedUser);
            System.out.println("Line Authentication 4");

        }

     request.getSession().setAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY, SecurityContextHolder.getContext());// creates context for that session.

        System.out.println("Line Authentication 5");

        session.setAttribute("username", user.getUsername());

        System.out.println("Line Authentication 6");

        session.setAttribute("authorities", usernamePasswordAuthenticationToken.getAuthorities());

        System.out.println("username:  " + user.getUsername() + "password: " + user.getPassword()+"authorities: "+ usernamePasswordAuthenticationToken.getAuthorities());

        user = userDAO.validate(user.getUsername(), user.getPassword());
        log.debug("You are successfully register");

    }

Other answers didnt suggest to put it in try/catch so one does not realize why logic is not working as code runs...and nothing is there neither error or exception on console. So if you wont put it in try catch you wont get exception of bad credentials.