我是Spring Security的新手,并且已经遵循了一些基本的方法来让Spring Security在我的应用程序中运行,但是现在我正在尝试查看是否有办法将我自己的User对象添加到登录/身份验证时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中检索Principal
对象并获取用户名并重新查询给定用户名的数据库,但我认为简单地存储我的整个User
对象会更容易在SecurityContext中,只要我在整个应用程序中需要它,就可以轻松访问它,而不是只在UserDetails
对象中存储用户名,密码和已启用的字段。
我查看了UserDetailsService,更具体地说是JdbcDaoImpl
类,但不完全确定最佳的继续方法。如果我只是通过调用super.loadUserByUsername
来覆盖/扩展loadUserByUsername
方法来返回我自己的UserDetails对象就够了吗?那么我能够做SecurityContextHolder.getContext().getAuthentication().getDetails()
并将其投射到我自己的对象上吗?
我在StackOverflow上发现了与此相关的其他帖子,但大多数帖子似乎忽略了与从DB检索到的权限和角色有关的任何内容,因此我不确定这是否是最佳方式。
答案 0 :(得分:2)
答案简短: 是的,你可以按计划完成。请记住,某些功能(如“hasRole”)会检查权限列表,而不是默认情况下的用户详细信息。
答案很长: 将用户对象保存在会话中保存的securitycontext中可能会产生一些副作用。 使用休眠时尤其如此。懒惰的例外吗? ;) 我们首先走了这条路线,后来几次打电话给一些LIE发生了,跟进起来非常棘手。使用OpenSessionInView过滤器,我们认为我们是安全的,但这是错误的,因为在下一个请求中会话消失了。所以我们从用户那里加载了更多相关的对象,但它仍然存在。稍后:)
我们有三种选择。要么在每个请求上合并用户对象,要在用户详细信息中创建仅包含必要安全信息的pojo,要么只保留主体(登录)在安全上下文中,并在需要时加载用户对象。
我们选择了第三个解决方案,因为hibernate使用二级缓存做得很好。 作为副作用,安全性现在更加可靠,因为Spring安全性现在在每个请求上获得用户的最新版本,并且不适用于“陈旧”用户角色。
因此,如果您不使用休眠,或者您可以保证不会发生任何LIE,请选择解决方案一或两个。否则我会推荐我们的方法。