2012-05-30 14 views
8

Estamos desarrollando una aplicación móvil con jQuery móvil y quiere autenticar al usuario mediante programación en un backend 3.1.x primavera configurar correctamente con la seguridad de la primavera.primavera: programáticamente ingrese

Una solicitud POST se envía al backend (usando jQuery's $ .post) que contiene un nombre de usuario y contraseña, el servidor luego verifica si las credenciales son correctas e inicia sesión en el usuario.

El servidor parece configurar correctamente la autenticación en SecurityContext, sin embargo, cuando realizamos una segunda solicitud al servidor (un $ .get a una página que requiere inicio de sesión) los detalles de seguridad no parecen recordarse y es anónimo token parece estar en el contexto.

Este es el método en el controlador que maneja el (comprobación de la contraseña eliminado por razones de brevedad) entrada:

@RequestMapping(value = "/login", method = RequestMethod.POST, produces = "application/json") 
@ResponseBody 
public Map<String, String> login(@RequestParam String username, @RequestParam String password, HttpServletRequest request) { 
    Map<String, String> response = new HashMap<String, String>(); 

    User u = userService.findByAccountName(username); 

    if (u != null && u.hasRole("inspector")) { 
     UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(username, password); 
     try { 
      Authentication auth = authenticationManager.authenticate(token); 
      SecurityContextHolder.getContext().setAuthentication(auth); 

      response.put("status", "true"); 
      return response; 
     } catch (BadCredentialsException ex) { 
      response.put("status", "false"); 
      response.put("error", "Bad credentials"); 
      return response; 
     } 
    } else { 
     response.put("status", "false"); 
     response.put("error", "Invalid role"); 
     return response; 
    } 
} 

Este es el otro método en el que se obtienen los DetallesUsuario fuera del contexto:

@RequestMapping(value = "/project", method = RequestMethod.GET) 
@ResponseBody 
public String getProjects(HttpSession session) { 

    Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); 
    User u = userService.findByAccountName(((UserDetails) authentication.getPrincipal()).getUsername()); 
... 
configuración de seguridad

primavera:

<global-method-security pre-post-annotations="enabled"/> 
<http use-expressions="true" auto-config="true"> 

    <form-login login-processing-url="/static/j_spring_security_check" login-page="/" 
       authentication-failure-url="/?login_error=t"/> 

    ... 
    <intercept-url pattern="/api/**" access="permitAll"/> 
    ... 
    <remember-me key="biKey" token-validity-seconds="2419200"/> 
    <logout logout-url="/logout"/> 
</http> 

<authentication-manager alias="authenticationManager"> 
    <authentication-provider user-service-ref="udm"> 
     <password-encoder hash="md5"/> 
    </authentication-provider> 
</authentication-manager> 

Esto debería funcionar de acuerdo a la documentación de seguridad de primavera y otros recursos en línea. ¿Alguna idea sobre lo que podría estar mal?

+0

La política de mantenimiento predeterminada de SecurityContextHolder es ThreadLocal. Cada solicitud se procesa en un nuevo hilo (en realidad no todos en el caso de grupos de hilos, pero esto no importa) y tiene su propia copia del contexto que contiene threadlocal. Por lo tanto, no se puede acceder a su Autenticación que está configurada en el método de inicio de sesión en el método getProjects (porque está en otro hilo). Debería guardar su información de autenticación en algún lugar (por ejemplo de sesión HTTP) y restaurar objetos de autenticación cada vez que la nueva solicitud llega al servidor (probablemente en filtro de servlet) –

+1

Comprobar http://stackoverflow.com/questions/3923296/user-granted -autoridades-son-siempre-papel-anónima – axtavt

+0

he implementado esta funcionalidad exacta utilizando la excelente respuesta unidos por axtavt. –

Respuesta

11

Estoy confundido por su configuración. Ha implementado su propio controlador de inicio de sesión, pero parece estar utilizando el formulario de inicio de sesión de Spring Security. Recientemente implementé el inicio de sesión de jax con Spring Security + jquery. En lugar de escribir mi propio controlador, simplemente implementé mi propio AuthenticationSuccessHandler y AuthenticationFailureHandler para devolver las respuestas json que necesitaba. Sólo se extienden SimpleUrlAuthenticationSuccessHandler y SimpleUrlAuthenticationFailureHandler sustituyendo los métodos onAuthenticationSuccess y onAuthenticationFailure en cada clase, algo tan simple como ....

public void onAuthenticationSuccess(HttpServletRequest request, 
     HttpServletResponse response, Authentication authentication) 
     throws IOException, ServletException { 
    response.getWriter().println("{\"success\": true}"); 
} 

public void onAuthenticationFailure(HttpServletRequest request, 
     HttpServletResponse response, AuthenticationException exception) 
     throws IOException, ServletException { 
    response.getWriter().println("{\"success\": false}"); 
} 

A continuación, puede configurar el elemento de formulario de acceso con algo como ...

<form-login login-processing-url="/static/j_spring_security_check" login-page="/" 
      authentication-success-handler-ref="ajaxAuthenticationSuccessHandler" 
      authentication-failure-handler-ref="ajaxAuthenticationFailureHandler" 
      authentication-failure-url="/?login_error=t"/> 
+0

Esto funcionó perfectamente ... gracias. – HDave

+0

Estamos encantados de que ayudó, por favor marque mi respuesta como aceptada – hyness

+0

lo haría si pudiera .... – HDave

Cuestiones relacionadas