Преамбула: Начиная с Spring-Security 3.2, @AuthenticationPrincipal
в конце этого ответа есть хорошая аннотация . Это лучший способ, когда вы используете Spring-Security> = 3.2.
Когда ты:
- использовать старую версию Spring-Security,
- необходимо загрузить пользовательский объект пользователя из базы данных с помощью некоторой информации (например, имени входа или идентификатора), хранящейся в основной или
- хотите узнать, как
HandlerMethodArgumentResolver
или WebArgumentResolver
может решить эту проблему элегантным способом, или просто хотите изучить фон @AuthenticationPrincipal
и AuthenticationPrincipalArgumentResolver
(потому что он основан на HandlerMethodArgumentResolver
)
затем продолжайте читать - иначе просто используйте @AuthenticationPrincipal
и поблагодарите Роба Винча (Автор @AuthenticationPrincipal
) и Лукаса Шмельцайзена (за его ответ).
(Кстати: мой ответ немного старше (январь 2012 г.), поэтому именно Лукас Шмельцайзен выступил первым с @AuthenticationPrincipal
базой решений для аннотаций в Spring Security 3.2.)
Тогда вы можете использовать в своем контроллере
public ModelAndView someRequestHandler(Principal principal) {
User activeUser = (User) ((Authentication) principal).getPrincipal();
...
}
Это нормально, если вам это нужно один раз. Но если вам это нужно в несколько раз, это уродливо, потому что оно загрязняет ваш контроллер деталями инфраструктуры, что обычно должно быть скрыто платформой.
Так что вы действительно хотите иметь такой контроллер:
public ModelAndView someRequestHandler(@ActiveUser User activeUser) {
...
}
Поэтому вам нужно только реализовать WebArgumentResolver
. У него есть метод
Object resolveArgument(MethodParameter methodParameter,
NativeWebRequest webRequest)
throws Exception
Он получает веб-запрос (второй параметр) и должен возвращать User
if, если он чувствует себя ответственным за аргумент метода (первый параметр).
С весны 3.1 появилась новая концепция HandlerMethodArgumentResolver
. Если вы используете Spring 3.1+, то вам следует использовать его. (Это описано в следующем разделе этого ответа))
public class CurrentUserWebArgumentResolver implements WebArgumentResolver{
Object resolveArgument(MethodParameter methodParameter, NativeWebRequest webRequest) {
if(methodParameter is for type User && methodParameter is annotated with @ActiveUser) {
Principal principal = webRequest.getUserPrincipal();
return (User) ((Authentication) principal).getPrincipal();
} else {
return WebArgumentResolver.UNRESOLVED;
}
}
}
Вам необходимо определить пользовательскую аннотацию - вы можете пропустить ее, если каждый экземпляр User всегда должен быть взят из контекста безопасности, но никогда не является объектом команды.
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ActiveUser {}
В конфигурации вам нужно только добавить это:
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"
id="applicationConversionService">
<property name="customArgumentResolver">
<bean class="CurrentUserWebArgumentResolver"/>
</property>
</bean>
@ См. Научитесь настраивать аргументы метода Spring MVC @Controller.
Следует отметить, что если вы используете Spring 3.1, они рекомендуют HandlerMethodArgumentResolver вместо WebArgumentResolver. - см. комментарий от Джея
То же самое с HandlerMethodArgumentResolver
для весны 3.1+
public class CurrentUserHandlerMethodArgumentResolver
implements HandlerMethodArgumentResolver {
@Override
public boolean supportsParameter(MethodParameter methodParameter) {
return
methodParameter.getParameterAnnotation(ActiveUser.class) != null
&& methodParameter.getParameterType().equals(User.class);
}
@Override
public Object resolveArgument(MethodParameter methodParameter,
ModelAndViewContainer mavContainer,
NativeWebRequest webRequest,
WebDataBinderFactory binderFactory) throws Exception {
if (this.supportsParameter(methodParameter)) {
Principal principal = webRequest.getUserPrincipal();
return (User) ((Authentication) principal).getPrincipal();
} else {
return WebArgumentResolver.UNRESOLVED;
}
}
}
В настройку нужно добавить это
<mvc:annotation-driven>
<mvc:argument-resolvers>
<bean class="CurrentUserHandlerMethodArgumentResolver"/>
</mvc:argument-resolvers>
</mvc:annotation-driven>
@ См. Использование интерфейса Spring MVC 3.1 HandlerMethodArgumentResolver
Решение Spring-Security 3.2
Spring Security 3.2 (не путайте с Spring 3.2) имеет собственное встроенное решение: @AuthenticationPrincipal
( org.springframework.security.web.bind.annotation.AuthenticationPrincipal
). Это хорошо описано в ответе Лукаса Шмельцайзена
Просто пишу
ModelAndView someRequestHandler(@AuthenticationPrincipal User activeUser) {
...
}
Чтобы это работало, вам нужно зарегистрировать AuthenticationPrincipalArgumentResolver
( org.springframework.security.web.bind.support.AuthenticationPrincipalArgumentResolver
): либо «активировать», @EnableWebMvcSecurity
либо зарегистрировать этот bean-компонент внутри mvc:argument-resolvers
- так же, как я описал это с помощью решения Spring 3.1 выше.
@ См. Spring Security 3.2. Ссылка, глава 11.2. @AuthenticationPrincipal
Решение Spring-Security 4.0
Он работает как 3.2 решения Spring, но весной 4.0, @AuthenticationPrincipal
и AuthenticationPrincipalArgumentResolver
был «перемещен» на другой пакет:
(Но старые классы в старых пакетах все еще существуют, поэтому не смешивайте их!)
Просто пишу
import org.springframework.security.core.annotation.AuthenticationPrincipal;
ModelAndView someRequestHandler(@AuthenticationPrincipal User activeUser) {
...
}
Чтобы это работало, вам нужно зарегистрировать ( org.springframework.security.web.method.annotation.
) AuthenticationPrincipalArgumentResolver
: либо «активировать», @EnableWebMvcSecurity
либо зарегистрировать этот bean-компонент внутри mvc:argument-resolvers
- так же, как я описал это с помощью решения Spring 3.1 выше.
<mvc:annotation-driven>
<mvc:argument-resolvers>
<bean class="org.springframework.security.web.method.annotation.AuthenticationPrincipalArgumentResolver" />
</mvc:argument-resolvers>
</mvc:annotation-driven>
@ См. Spring Security 5.0 Справочник, Глава 39.3 @AuthenticationPrincipal