У меня есть приложение, которое использует Spring Security для управления доступом к страницам, для управления ролями пользователей (GrantedAuthority
) и для ACL. Приложение использует стандарт UsernamePasswordAuthenticationFilter
, который перехватывает запросы к /j_spring_security_check
(с параметрами запроса j_username
и j_password
), и, используя ProviderManager
, проверяет подлинность пользователя и в случае успеха сохраняет его в SecurityContextHolder
.
Вышеуказанное настроено в контексте безопасности с использованием настроенного UserDetailsService
:
<authentication-manager alias="authenticationManager">
<authentication-provider user-service-ref='myUserDetailsService'/>
</authentication-manager>
Приведенный выше подход в моем случае не является оптимальным по следующим причинам:
- Для добавления капчи требуются дополнительные фильтры
- Чтобы настроить логику входа в систему, мне также необходимо заменить
AuthenticationProvider
- показывать ошибки в форме входа в систему сложно, поскольку я не могу использовать формы Spring MVC
Моя идея - удалить вход в систему на основе перехватчика и поместить всю логику в контроллер Spring 3 MVC. Псевдокод выглядит следующим образом:
RequestMapping(value="/login/", method = RequestMethod.POST)
public String attemptLogin(HttpServletRequest request, HttpServletResponse response,
@ModelAttribute("login") LoginCmd login, Model model) {
// validate command (username, password, captcha)
// ...
// load user from DB
User user = userService.loadUserByUsername(login.getUsername());
// extra logic (check number of failed logins + other stuff)
// ...
// In case everything is fine, create a spring security User
/* Instead of creating the user, read it from DB */
org.springframework.security.core.userdetails.User authUser =
new org.springframework.security.core.userdetails.User(
login.getUsername() /*username*/,
login.getPassword() /*password*/,
true /*enabled*/,
true /*accountNonExpired */,
true /*credentialsNonExpired */,
true /*accountNonLocked*/,
new ArrayList<GrantedAuthority>() /*authorities*/
);
// build the AuthenticationToken
UsernamePasswordAuthenticationToken authResult =
new UsernamePasswordAuthenticationToken(authUser, login.getPassword(),
authUser.getAuthorities());
// use WebAuthenticationDetailsSource do build details
authResult.setDetails(detailsSource.buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(authResult);
return SUCCESS_VIEW;
}
Видите ли вы какие-либо проблемы с решением здесь выше? Достаточно ли установить аутентификацию внутри SecurityContextHolder
? Я что-то упустил?
Комментарии и предложения приветствуются ;-)
Большое спасибо всем
Andrea