2012-05-30 14 views
8

Rozwijamy aplikację mobilną z jQuery mobile i chcemy programowo uwierzytelniać użytkownika na wiosennym repozytorium 3.1.x poprawnie skonfigurowanym z bezpieczeństwem sprężynowym.Bezpieczeństwo wiosenne: programowane logowanie

Żądanie POST jest wysyłane do zaplecza (za pomocą jQuery $ .post) zawierającego nazwę użytkownika i hasło, serwer następnie sprawdza, czy poświadczenia są poprawne i zalogować się do użytkownika.

Serwer wydaje się poprawnie ustawić uwierzytelnianie w SecurityContext, jednak gdy wykonamy drugie żądanie do serwera (a .get na stronę, która wymaga logowania) dane bezpieczeństwa nie wydają się być zapamiętywane i anonimowe token wydaje się być w kontekście.

Jest to metoda, w sterowniku, który obsługuje (sprawdź hasło usunięte dla zwięzłość) logowanie:

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

To jest inna metoda, w której otrzymujemy userdetails z kontekstu:

@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()); 
... 
konfiguracja zabezpieczeń

Wiosna:

<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> 

ten powinien działać zgodnie do wiosennej dokumentacji bezpieczeństwa i innych zasobów online. Jakieś pomysły na coś, co może być nie tak?

+0

SecurityContextHolder domyślna polityka przechowywania to ThreadLocal. Każde żądanie przetwarzane jest w nowym wątku (właściwie nie w przypadku wszystkich pul wątków, ale to nie ma znaczenia) i ma własną kopię kontekstu zawierającego threadlocal. W związku z tym nie można uzyskać dostępu do uwierzytelniania ustawionego w metodzie logowania w metodzie getProjects (ponieważ znajduje się on w innym wątku). Powinieneś zapisać informacje uwierzytelniające w pewnym miejscu (na przykład sesję http) i przywrócić obiekt uwierzytelniania za każdym razem, gdy nowe żądanie dotrze do serwera (prawdopodobnie w filtrze serwletów) –

+1

Sprawdź http://stackoverflow.com/questions/3923296/user-granted -Authorities-are-always-role-anonymous – axtavt

+0

Zaimplementowałem tę dokładną funkcjonalność, korzystając z doskonałej odpowiedzi powiązanej przez axtavt. –

Odpowiedz

11

Jestem zdezorientowany twoją konfiguracją. Zaimplementowałeś swój własny kontroler logowania, ale wydaje się, że korzystasz z formularza logowania Spring Security. Niedawno zaimplementowałem login ajaxowy z Spring Security + jquery. Zamiast pisać własny kontroler, po prostu zaimplementowałem mój własny AuthenticationSuccessHandler i AuthenticationFailureHandler, aby zwrócić potrzebne mi odpowiedzi JSON. Wystarczy przedłużyć SimpleUrlAuthenticationSuccessHandler i SimpleUrlAuthenticationFailureHandler przesłanianie metod onAuthenticationSuccess i onAuthenticationFailure w każdej klasie, coś tak prostego jak ....

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

Następnie można skonfigurować element formularza-login z czymś takim ...

<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

To działało idealnie ... dzięki. – HDave

+0

Cieszę się, pomógł, proszę oznaczyć moją odpowiedź jako zaakceptowana – hyness

+0

Chciałbym, gdybym mógł .... – HDave

Powiązane problemy