Мы разрабатываем мобильное приложение с мобильным устройством 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>
Это должно работать в соответствии к весенней документации по безопасности и другим онлайн-ресурсам. Любые идеи о том, что может быть неправильным?
Политика безопасности по умолчанию для SecurityContextHolder - ThreadLocal. Каждый запрос обрабатывается в новом потоке (фактически не каждый в случае пулов потоков, но это не имеет значения), и у него есть собственная копия контекста, содержащая threadlocal. Таким образом, ваша аутентификация, установленная в методе входа, не может быть доступна в методе getProjects (потому что она находится в другом потоке). Вы должны сохранить информацию об аутентификации в каком-либо месте (например, http-сеанс) и восстановить объект аутентификации каждый раз, когда на сервер приходит новый запрос (возможно, в фильтр сервлетов) –
Проверьте http://stackoverflow.com/questions/3923296/user-granted -authorities-are-always-role-anonymous – axtavt
Я реализовал эту точную функциональность, используя отличный ответ, связанный с axtavt. –