2010-09-28 16 views
26

Hola a todos quiero hacer un inicio de sesión automático después de un registro exitoso en primavera significado: tengo una página protegida que requiere inicio de sesión para acceder a ellos y quiero que después del registro para saltarse la página de registro y hacer un inicio de sesión automático para que el usuario pueda ver esa página protegida, ¿me entiendes? estoy usando la primavera 3.0, seguridad de primavera 3.0.2 cómo hacerlo?inicio de sesión automático después de un registro exitoso

Respuesta

38

Esto se puede hacer con la seguridad de primavera de la siguiente manera (semi-psuedocode):

import org.springframework.security.web.savedrequest.RequestCache; 
import org.springframework.security.web.savedrequest.SavedRequest; 

@Controller 
public class SignupController 
{ 

    @Autowired 
    RequestCache requestCache; 

    @Autowired 
    protected AuthenticationManager authenticationManager; 

    @RequestMapping(value = "/account/signup/", method = RequestMethod.POST) 
    public String createNewUser(@ModelAttribute("user") User user, BindingResult result, HttpServletRequest request, HttpServletResponse response) { 
     //After successfully Creating user 
     authenticateUserAndSetSession(user, request); 

     return "redirect:/home/"; 
    } 

    private void authenticateUserAndSetSession(User user, HttpServletRequest request) { 
     String username = user.getUsername(); 
     String password = user.getPassword(); 
     UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(username, password); 

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

     token.setDetails(new WebAuthenticationDetails(request)); 
     Authentication authenticatedUser = authenticationManager.authenticate(token); 

     SecurityContextHolder.getContext().setAuthentication(authenticatedUser); 
    } 
} 

Actualización: sólo para tener la forma de crear la sesión después del registro

+0

no es correcta, ya sé la página de destino pero requiere inicio de sesión para verlo y no quiero ir a la página de inicio de sesión y quiero hacer un inicio de sesión automático interno, me consiguió ? –

+0

He actualizado mi código para iniciar sesión automáticamente después del registro. –

+0

tengo la siguiente excepción ??? org.springframework.security.authentication.BadCredentialsException: credenciales erróneas –

-1

No estoy seguro de si está pidiendo esto, pero en su configuración de Spring Security puede agregar una etiqueta "recordarme". Esto administrará una cookie en su cliente, por lo que la próxima vez (si la cookie no ha expirado) se registrará automáticamente.

<http> 
    ... 
    <remember-me /> 
</http> 
+0

eso no es lo um preguntando por –

8

Sólo una comente en la primera respuesta sobre cómo autoaumentar authenticationManager.

Es necesario configurar un alias cuando se declara la autenticación de administrador, ya sea en su applicantion-servlet.xml o applicationContext-security.xml archivo:

<authentication-manager alias="authenticationManager> 
    <authentication-provider> 
     <user-service> 
      <user name="jimi" password="jimispassword" authorities="ROLE_USER, ROLE_ADMIN" /> 
      <user name="bob" password="bobspassword" authorities="ROLE_USER" /> 
     </user-service> 
    </authentication-provider> 
</authentication-manager> 

Además, cuando se autentica, se puede producir una AuthenticationException , por lo que necesita para atraparlo:

UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(user.getEmail(), user.getPassword()); 
request.getSession(); 

token.setDetails(new WebAuthenticationDetails(request)); 

try{ 
    Authentication auth = authenticationManager.authenticate(token); 

    SecurityContextHolder.getContext().setAuthentication(auth); 
} catch(Exception e){ 
     e.printStackTrace(); 
} 

return "redirect:xxxx.htm"; 
0

Spring Monkey's answer works great pero me encontré con un problema difícil en la aplicación de la misma.

Mi problema era porque establecer la página de registro para que "no hay seguridad", por ejemplo:

<http pattern="/register/**" security="none"/> 

Creo que esto no causa SecurityContext inicializado, y por lo tanto después de registros de usuario, la autenticación en el servidor, no puede ser salvado.

que tenía que cambiar el bypass página de registro mediante el establecimiento en IS_AUTHENTICATED_ANONYMOUSLY

<http authentication-manager-ref="authMgr"> 
    <intercept-url pattern="/register/**" access="IS_AUTHENTICATED_ANONYMOUSLY"/> 
    ... 
</http> 
2
  1. Web.xml Configurar para permitir la primavera de Seguridad para manejar hacia delante para una url de procesamiento de inicio de sesión.
  2. Manejar la solicitud de registro, p. crear usuario, actualizar ACL, etc.
  3. Reenviarlo con nombre de usuario y contraseña para iniciar sesión url de procesamiento para la autenticación.
  4. Obtenga los beneficios de toda la cadena de filtros de Spring Security, p. protección de fijación de sesión.

Como los forwards son internos, el usuario se dará cuenta de que están registrados y conectados durante la misma solicitud.

Si su formulario de registro no contiene los nombres correctos de nombre de usuario y contraseña, envíe una versión modificada de la solicitud (usando HttpServletRequestWrapper) al punto final de inicio de sesión de Spring Security.

Para que esto funcione, deberá modificar su web.xml para que la cadena del filtro Spring Security se adelante para el login-processing-url. Por ejemplo:

<filter> 
    <filter-name>springSecurityFilterChain</filter-name> 
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> 
</filter> 

<!-- Handle authentication for normal requests. --> 
<filter-mapping> 
    <filter-name>springSecurityFilterChain</filter-name> 
    <url-pattern>/*</url-pattern> 
</filter-mapping> 

<!-- Handle authentication via forwarding for internal/automatic authentication. --> 
<filter-mapping> 
    <filter-name>springSecurityFilterChain</filter-name> 
    <url-pattern>/login/auth</url-pattern> 
    <dispatcher>FORWARD</dispatcher> 
</filter-mapping> 

Source: mohchi blog

10

En servlet 3+ simplemente puede hacer request.login("username","password") y si tiene éxito, vuelven a dirigir a cualquier página que desee. Puede hacer lo mismo para el cierre de sesión automático.

Aquí está el enlace a la sección de la documentación relativa a este tema: http://docs.spring.io/spring-security/site/docs/current/reference/htmlsingle/#servletapi-3

+0

El método subyacente básicamente hace http://stackoverflow.com/a/3815189/1178781 bajo el capó. Entonces, ¡esto funcionó perfectamente para mí! – justderb

+0

Muchas gracias ... esto funcionó como un encanto para mí ... –

+0

Funciona perfectamente, y es mucho más simple que cualquiera de las otras respuestas. ¡Gracias! – LuTHieR

0

Esta es la respuesta a la pregunta anterior En Controlador:

@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; 
    } 

más arriba método en el controlador es definido como:

`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"); 

    } 

Otras respuestas no sugirieron ponerlo en try/catch para que uno no se dé cuenta de por qué la lógica no funciona mientras se ejecuta el código ... y no hay nada ni error ni excepción en la consola. Entonces, si no lo pones en try catch, no obtendrás excepción de malas credenciales.

1

Usando SecurityContextHolder.getContext(). SetAuthentication (Autenticación) hace el trabajo pero pasará por alto la cadena de filtro de seguridad de primavera que abrirá un riesgo de seguridad.

Por ej. digamos en mi caso cuando el usuario restableció la contraseña, quería que lo llevara al tablero sin iniciar sesión de nuevo. Cuando utilicé el enfoque mencionado anteriormente, me lleva al tablero, pero pasó por alto mi filtro de concurrencia que he aplicado para evitar el inicio de sesión simultáneo. Aquí está el trozo de código que hace el trabajo:

UsernamePasswordAuthenticationToken authToken = new UsernamePasswordAuthenticationToken(empId, password); 
Authentication auth = authenticationManager.authenticate(authToken); 
SecurityContextHolder.getContext().setAuthentication(auth); 

Uso atributo de inicio de sesión-procesamiento-url junto con un simple cambio en web.xml

seguridad en XML

<form-login login-page="/login" 
      always-use-default-target="false" 
      default-target-url="/target-url" 
      authentication-failure-url="/login?error" 
      login-processing-url="/submitLogin"/> 

web.xml

<filter-mapping> 
    <filter-name>springSecurityFilterChain</filter-name> 
    <url-pattern>/submitLogin</url-pattern> 
    <dispatcher>FORWARD</dispatcher> 
</filter-mapping> 

Al agregar este fragmento de código en web.xml, en realidad hace el trabajo de reenviar su solicitud explícita de reenvío que realizará durante el inicio de sesión automático y pasarla a la cadena de filtros de seguridad de primavera.

creo que sirve

0

Esta es una alternativa al servlet 3+ integración. Si usa el formulario de inicio de sesión de Spring Security, simplemente puede delegar en su página de inicio de sesión. Por ejemplo:

@PostMapping("/signup") 
public String signUp(User user) { 
    // encode the password and save the user 
    return "forward:/login"; 
} 

Asumiendo que tiene username y password los campos del formulario, entonces la 'hacia delante' enviaré de los parámetros y la primavera de Seguridad utilizará para autenticar.

El beneficio que encontré con este enfoque es que no duplica su formLogin 's defaultSuccessUrl (ejemplo de configuración de seguridad a continuación). También limpia su controlador al no requerir un parámetro HttpServletRequest.

@Override 
public void configure(HttpSecurity http) { 
    http.authorizeRequests() 
      .antMatchers("/", "/signup").permitAll() 
      .anyRequest().authenticated() 
      .and() 
     .formLogin() 
      .loginPage("/login") 
      .defaultSuccessUrl("/home", true) 
      .permitAll(); 
} 
Cuestiones relacionadas