当Spring Security对用户进行身份验证时,它会创建一个UserDetail对象,并且可以在web-app中查找当前的UserId。但是,假设我想保留一个自定义用户对象,其中包含首选项和其他详细信息以及UserDetails或替换UserDetails。
因此,在Spring Security进行身份验证时如何向会话添加自定义用户对象 成功?以及如何在Spring Security注销登录用户时从会话中删除自定义用户对象。
或者有没有合适的方法来做到这一点?
答案 0 :(得分:18)
执行此操作的最佳方法IMO是让您的某个服务(可能是UserService)实现UserDetailsService,并在spring security XML中指定您希望使用自己的用户详细信息服务。
UserDetailsService需要做的是实现loadByUsername(String username)方法。此方法需要返回实现UserDetails的类。这可以是您自己的自定义对象存储您喜欢的任何内容。这样做的好处是,您可以通过spring security taglib从JSP访问对象的属性,并且它也始终可以从Spring Security Security中的SecurityContextHolder单例(线程安全)中获得。
以下是此文档的链接:spring security manual, chapter 8 这篇博客文章讨论了为密码加密实现自定义用户详细信息服务:example usage
希望这有帮助
编辑:忘记提及在注销时将从安全上下文和会话中删除该对象。这是最有用的,它完全由春季安全管理。
答案 1 :(得分:0)
你绝对需要自己编写UserDetailService
。在Principal对象中有用户,AuthenticationToken
中还有一个Details对象,您可以存储其他登录信息的Map(String,String)。
public class RequestFormDeatils extends SpringSecurityFilter {
protected void doFilterHttp(HttpServletRequest request, ...) {
SecurityContext sec = SecurityContextHolder.getContent();
AbstractAuthenticationToken auth = (AbstractAuthenticationToken)sec.getAuthentication();
Map<String, String> m = new HashMap<String, String>;
m.put("myCustom1", request.getParameter("myCustom1"));
m.put("myCustom2", request.getParameter("myCustom2"));
auth.setDetails(m);
}
现在,您的代码中的任何位置都可以使用SecurityContext
传播此安全相关信息,而无需将其与您的UserDetails
对象耦合,或将其作为参数传递。我在Spring安全过滤器链末尾的SecurityFilter
中执行此代码。
<bean id="requestFormFilter" class="...RequestFormDetails">
<custom-filter position="LAST" />
</bean>
删除用户时会删除此信息(例如在注销时)。