Преамбула: З Spring-Security 3.2 @AuthenticationPrincipal
в кінці цієї відповіді є приємна примітка . Це найкращий шлях для використання Spring-Security> = 3.2.
Коли ти:
- використовувати старішу версію Spring-Security,
- потрібно завантажити свій користувальницький об’єкт користувача з бази даних якоюсь інформацією (наприклад, логіном або ідентифікатором), що зберігається в головному або
- хочете дізнатися, як
HandlerMethodArgumentResolver
або WebArgumentResolver
можна вирішити це елегантно, або просто захочете дізнатися передумови позаду @AuthenticationPrincipal
та AuthenticationPrincipalArgumentResolver
(тому що це засновано на HandlerMethodArgumentResolver
)
то продовжуйте читати - інше просто використовуйте @AuthenticationPrincipal
та дякуйте Роб Вінчу (Автору @AuthenticationPrincipal
) та Лукасу Шмельцейзену (за його відповідь).
(BTW: Моя відповідь трохи старша (січень 2012 р.), Тому саме Лукаш Шмельцейзен виступив першим із @AuthenticationPrincipal
базою рішень для анотації на Spring Security 3.2.)
Потім ви можете використовувати у своєму контролері
public ModelAndView someRequestHandler(Principal principal) {
User activeUser = (User) ((Authentication) principal).getPrincipal();
...
}
Це нормально, якщо вам це потрібно один раз. Але якщо вам це потрібно в кілька разів негарно, оскільки воно забруднює ваш контролер деталями інфраструктури, це, як правило, повинно бути приховано рамкою.
Тож, що ви можете дуже хотіти, це мати такий контролер:
public ModelAndView someRequestHandler(@ActiveUser User activeUser) {
...
}
Тому вам потрібно лише впровадити a WebArgumentResolver
. У ньому є метод
Object resolveArgument(MethodParameter methodParameter,
NativeWebRequest webRequest)
throws Exception
Він отримує веб-запит (другий параметр) і повинен повернути, User
якщо він відчуває відповідальність за аргумент методу (перший параметр).
З весни 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;
}
}
}
Вам потрібно визначити користувацьку анотацію - її можна пропустити, якщо кожен екземпляр користувача завжди повинен бути взято з контексту безпеки, але ніколи не є об'єктом команди.
@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>
@See: Дізнайтеся, як налаштувати аргументи методу Spring MVC @Controller
Слід зазначити, що якщо ви використовуєте Spring 3.1, вони рекомендують HandlerMethodArgumentResolver через WebArgumentResolver. - дивіться коментар Джея
Те саме з HandlerMethodArgumentResolver
Spring 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>
@See Використання інтерфейсу Spring MVC 3.1 HandlerMethodArgumentResolver
Весна-Безпека 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
або зареєструвавши цей квасоля в межах mvc:argument-resolvers
- так само, як я описав це з рішенням Spring Spring 3.1 вище.
@ Погляньте на Spring Spring Security 3.2 Посилання, розділ 11.2. @AuthenticationPrincipal
Spring-Security 4.0 Рішення
Він працює як рішення Spring 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
або зареєструвавши цей квасоля в межах mvc:argument-resolvers
- так само, як я описав це з рішенням Spring Spring 3.1 вище.
<mvc:annotation-driven>
<mvc:argument-resolvers>
<bean class="org.springframework.security.web.method.annotation.AuthenticationPrincipalArgumentResolver" />
</mvc:argument-resolvers>
</mvc:annotation-driven>
@See Spring Security 5.0 Посилання, розділ 39.3 @AuthenticationPrincipal