Java 我可以将自己的用户对象推送到Spring的SecurityContext中吗?

Java 我可以将自己的用户对象推送到Spring的SecurityContext中吗?,java,spring,spring-security,Java,Spring,Spring Security,我是Spring Security的新手,并遵循了一些基本的方法来让Spring Security在我的应用程序中工作,但现在我尝试看看是否有办法在登录/身份验证时将我自己的用户对象添加到Spring的SecurityContext中 我的安全性当前配置为使用JdbcDaoImpl: <authentication-manager alias="authenticationManager"> <authentication-provider user-service-r

我是Spring Security的新手,并遵循了一些基本的方法来让Spring Security在我的应用程序中工作,但现在我尝试看看是否有办法在登录/身份验证时将我自己的用户对象添加到Spring的SecurityContext中

我的安全性当前配置为使用JdbcDaoImpl:

<authentication-manager alias="authenticationManager">
    <authentication-provider user-service-ref="com.ia.security.SpringSecurityDao" />
</authentication-manager>

<beans:bean id="com.ia.security.SpringSecurityDao" class="org.springframework.security.core.userdetails.jdbc.JdbcDaoImpl">
    <beans:property name="usersByUsernameQuery">
        <beans:value>select username,password,enabled 
        from user 
        where username = ?
        </beans:value>
    </beans:property>
    <beans:property name="dataSource" ref="dataSource" />
    <beans:property name="enableGroups" value="true" />
    <beans:property name="enableAuthorities" value="false" />
    <beans:property name="groupAuthoritiesByUsernameQuery">
        <beans:value>SELECT R.ID, R.NAME, P.NAME
            FROM ROLE R
            JOIN USER_ROLE UR on R.id = UR.role_id
            JOIN USER U on U.id = UR.user_id
            JOIN ROLE_PERMISSION RP ON RP.role_id = R.id
            JOIN PERMISSION P ON P.id = RP.permission_id
            WHERE U.username=?
        </beans:value>
    </beans:property>
</beans:bean>
我意识到我可以从SecurityContext中检索主体对象并获取用户名,然后根据用户名重新查询数据库,但是,我认为在SecurityContext中简单地存储我的整个用户对象会更容易,以便在整个应用程序中需要时可以轻松访问它,而不仅仅是在UserDetails对象中存储用户名、密码和启用字段

我已经研究了UserDetailsService,更具体地说是JdbcDaoImpl类,但还不能完全确定最好的方法。如果我只是通过调用super.loadUserByUsername重写/扩展loadUserByUsername方法来返回我自己的UserDetails对象,这就足够了吗?那么,我是否能够执行SecurityContextHolder.getContext.getAuthentication.getDetails并将其强制转换到我自己的对象

我在StackOverflow上发现了与此相关的其他帖子,但大多数帖子似乎忽略了与从DB中检索到的权限和角色有关的任何内容,因此我不确定这是否是最好的继续方式。

简单回答: 是的,你可以完全按照你的计划去做。请记住,默认情况下,某些功能(如hasRole)会检查权限列表,而不是用户详细信息

答案很长: 将用户对象保留在会话中的securitycontext中可能会产生一些副作用。 使用hibernate时尤其如此。有人吗; 我们先走了这条路,后来打了几个电话,说了一些谎话,这很难跟进。使用OpenSessionInView过滤器,我们认为我们是安全的,但这是错误的,因为在下一个请求中,会话已经结束。所以我们从用户那里加载了更多相关的对象,但仍然发生了。稍后:

我们有三个选择。或者在每个请求上合并用户对象,创建一个pojo,在userdetails中只保存必要的安全信息,或者只在安全上下文中保留主体登录,并在需要时加载用户对象

我们使用了第三种解决方案,因为hibernate在使用二级缓存方面做得很好。 作为一个副作用,由于spring security现在可以在每个请求中获得用户的最新版本,并且不能处理过时的用户角色,因此安全性现在更加可靠


所以,如果您不使用hibernate,或者您可以保证不会发生谎言,请选择解决方案一或两。否则我会推荐我们的方法。

谢谢你的提醒。虽然我必须承认我不熟悉首字母缩略词LIE;我认为这和延迟初始化异常或类似的东西有关。事实上,我正在使用Hibernate,并希望将用户对象保留在SecurityContext中以供参考。更具体地说,我有需要当前登录用户的审计字段,我认为只使用SecurityContext的用户对象检索该字段要比每次从DB检索该字段容易得多。你能告诉我更多关于你所遇到的谎言的细节/经历吗?我只是重新阅读了你的答案,我感到困惑的是…更可靠,因为spring security现在在每个请求上都获得了用户的最新版本。。。。怎么样?SpringSecurity将在您登录时查询数据库,并将该信息存储在SecurityContext中,包括任何权限。由于SecurityContext中数据的陈旧性,您是否在UserDetails中保留整个用户实体会有什么区别?因为我们只在安全上下文中保留登录,所以必须在每个请求中加载用户实体。由于这会获取用户的最新版本,而这现在是一个附加实体,因此我们不会遇到延迟异常。现在谈谈自动城市;回想起来,我不确定我们是否改变了权限检查的行为,从用户实体分配的角色中查找它,或者我们是否也做了其他事情来使用正确的版本。很高兴讨论这一点,但不是在这里的评论:在阅读了你的评论和建议后,我最终遵循了你的建议。我没有将整个用户对象推送到SecurityContext中,而是简单地存储了userId,以便于缓存和加快二级缓存中的查找。谢谢