在我的控制器中,当我需要活动(登录)用户时,我正在执行以下操作以获取UserDetails实现:
User activeUser = (User)SecurityContextHolder.getContext().getAuthentication().getPrincipal();
log.debug(activeUser.getSomeCustomField());
它工作正常,但我认为Spring在这种情况下可以使生活更轻松。有没有办法将UserDetails自动接线连接到控制器或方法中?
例如,类似:
public ModelAndView someRequestHandler(Principal principal) { ... }
但是UsernamePasswordAuthenticationToken
我得到了,UserDetails
而不是得到了?
我正在寻找一种优雅的解决方案。有任何想法吗?
序言:从Spring-Security 3.2开始@AuthenticationPrincipal,此答案的末尾描述了一个不错的注释。当你使用Spring-Security> = 3.2时,这是最好的方法。
当你:
使用较旧版本的Spring-Security,
需要通过存储在主体中的某些信息(例如登录名或ID)从数据库加载你的自定义用户对象,
想要了解a HandlerMethodArgumentResolver
或如何WebArgumentResolver
以一种优雅的方式解决此问题,或者只是想要了解@AuthenticationPrincipaland
的背景AuthenticationPrincipalArgumentResolver
(因为它基于HandlerMethodArgumentResolver
)
然后继续阅读-否则,请使用@AuthenticationPrincipal
并感谢Rob Winch
(的作者@AuthenticationPrincipal
)和Lukas Schmelzeisen
(的回答)。
(顺便说一句:我的回答有点老(2012年1月),因此是Lukas Schmelzeisen作为第一个使用@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
这将获取Web请求(第二个参数),并且User如果感觉对方法参数(第一个参数)负责,则必须返回。
从Spring 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>
@See:学习自定义Spring MVC @Controller方法参数
应该注意的是,如果你使用的是Spring 3.1,他们建议使用HandlerMethodArgumentResolver而不是WebArgumentResolver。-见周杰伦的评论
与HandlerMethodArgumentResolverSpring 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接口
Spring-Security 3.2解决方案
spring安全3.2(不使用Spring 3.2混淆)在溶液中有自己的编译:@AuthenticationPrincipal(org.springframework.security.web.bind.annotation.AuthenticationPrincipal)。Lukas Schmelzeisen的回答对此进行了很好的描述。
只是在写
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解决方案
它的工作方式类似于Spring 3.2解决方案,但在Spring 4.0中,@AuthenticationPrincipal和AuthenticationPrincipalArgumentResolver
被“移动”到另一个软件包中:
org.springframework.security.core.annotation.AuthenticationPrincipal
org.springframework.security.web.method.annotation.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>
问题内容: 在我的控制器中,当我需要活动(登录)用户时,我正在执行以下操作以获取UserDetails实现: 它工作正常,但我认为Spring在这种情况下可以使生活更轻松。有没有办法将自动接线连接到控制器或方法中? 例如,类似: 但是我得到了,而不是得到了? 我正在寻找一种优雅的解决方案。有任何想法吗? 问题答案: 序言:从Spring-Security 3.2开始,此答案的末尾描述了一个不错的注
问题内容: 我试图用Java升级我的应用程序,使其仅在具有特定名称的进程窗口处于活动状态时才能工作。我发现使用JNI可以做到这一点,但是我不知道该怎么做。我只是找不到任何可以解释它的描述或示例。我的问题是- 如何获取Windows中当前活动窗口的进程名称(通过JNI或其他方式-我接受任何其他解决方案)? 问题答案: 减轻您的痛苦,并使用JNA。您将需要下载 Win32 API的 jna.jar 和
本文向大家介绍Android 使用Fence API获取用户活动的更改,包括了Android 使用Fence API获取用户活动的更改的使用技巧和注意事项,需要的朋友参考一下 示例 如果要检测用户何时开始或完成活动(例如步行,跑步或该DetectedActivityFence课程的其他任何活动),则可以为要检测的活动创建围栏,并在用户开始/结束时得到通知这项活动。通过使用BroadcastRece
如何在我的活动android java中获取viewpager数据 我想在我的活动中查看页面的当前数据 我的活动 我的适配器 } 我的数据类 我想访问主活动中的另外两个文本视图 如何在活动中设置的文本 其他两个字段如何进入活动 我想在活动中设置此字段
所以我要做的是让我的Java找到windows用来登录的用户名,所以当我说这样的方法时,它会返回用户名,就像我在名为Noah的用户中使用它一样,Java会返回“Noah”,如果我在用户Amanda上,Java会返回“Amanda”。我该怎么做?
问题内容: 有人知道在Swift中获取用户时区的方法吗? 我正在从数据库中取出电视上的特定时间,然后需要从它们所在的位置减去/添加,以显示它们的正确时间。 问题答案: 编辑/更新: Xcode 8或更高版本•Swift 3或更高版本 如果需要缩写: 如果您需要时区标识符: 要了解所有可用的时区缩写: 要了解所有可用的时区名称(标识符): 您可能还需要一些其他信息: TimeZone- Apple开