2012-05-30 2 views
8

Мы разрабатываем мобильное приложение с мобильным устройством jQuery и хотим, чтобы он программным образом аутентифицировал пользователя на исходном сервере весны 3.1.x, правильно настроенном с весенней безопасностью.Spring security: programatically log in

Запрос POST отправляется на сервер (с использованием jQuery's $ .post), содержащего имя пользователя и пароль, затем сервер проверяет правильность учетных данных и вход в систему пользователя.

Сервер, похоже, правильно настроил аутентификацию в SecurityContext, однако, когда мы делаем второй запрос на сервер ($ .get на страницу, требующую входа в систему), данные безопасности, похоже, не запоминаются, а анонимный токен, похоже, находится в контексте.

Это метод в контроллере, который обрабатывает (проверку пароля удалены для краткости) Логин:

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

Это другой способ, в котором мы получаем UserDetails из контекста:

@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()); 
... 
конфигурация безопасности

Spring:

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

Это должно работать в соответствии к весенней документации по безопасности и другим онлайн-ресурсам. Любые идеи о том, что может быть неправильным?

+0

Политика безопасности по умолчанию для SecurityContextHolder - ThreadLocal. Каждый запрос обрабатывается в новом потоке (фактически не каждый в случае пулов потоков, но это не имеет значения), и у него есть собственная копия контекста, содержащая threadlocal. Таким образом, ваша аутентификация, установленная в методе входа, не может быть доступна в методе getProjects (потому что она находится в другом потоке). Вы должны сохранить информацию об аутентификации в каком-либо месте (например, http-сеанс) и восстановить объект аутентификации каждый раз, когда на сервер приходит новый запрос (возможно, в фильтр сервлетов) –

+1

Проверьте http://stackoverflow.com/questions/3923296/user-granted -authorities-are-always-role-anonymous – axtavt

+0

Я реализовал эту точную функциональность, используя отличный ответ, связанный с axtavt. –

ответ

11

Я смущен вашей конфигурацией. Вы внедрили свой собственный контроллер входа, но вы, похоже, используете форму входа в систему Spring Security. Недавно я реализовал вход ajax с помощью Spring Security + jquery. Вместо написания моего собственного контроллера я просто реализовал свой собственный AuthenticationSuccessHandler и AuthenticationFailureHandler, чтобы вернуть нужные ответы json. Просто расширить SimpleUrlAuthenticationSuccessHandler и SimpleUrlAuthenticationFailureHandler переопределение методов onAuthenticationSuccess и onAuthenticationFailure в каждом классе, как-то просто, как ....

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

Затем вы можете настроить вид-Логин элемент что-то вроде ...

<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

Это сработало отлично ... спасибо. – HDave

+0

Рад, что это помогло, пожалуйста, отметьте мой ответ, как принято – hyness

+0

Если бы я мог ... – HDave