[英]Can I push my own User object into Spring's SecurityContext?
I'm new to Spring Security and have followed some basic recipes to get Spring Security working in my application, but now I'm trying to see if there is a way to get my own User object added to Spring's SecurityContext upon login/authentication. 我是Spring Security的新手,并且已经按照一些基本的食谱来使Spring Security在我的应用程序中运行,但是现在我正在尝试查看是否有一种方法可以在登录/身份验证时将自己的User对象添加到Spring的SecurityContext中。
My security is currently configured to use the JdbcDaoImpl: 我的安全性当前配置为使用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>
I realize that I can retrieve the Principal
object from the SecurityContext and get the username and requery the DB given the username, but was thinking it would be easier to simple store the my entire User
object in the SecurityContext to have it easily accessible whenever I need it throughout my application as opposed to just storing the username, password and enabled fields in the UserDetails
object. 我意识到我可以从SecurityContext中检索
Principal
对象并获取用户名,然后使用给定的用户名重新查询数据库,但是我认为将我的整个User
对象简单地存储在SecurityContext中以便在需要时可以轻松访问它会更容易它遍及我的整个应用程序,而不仅仅是在UserDetails
对象中存储用户名,密码和启用的字段。
I've looked into the UserDetailsService, and more specifically the JdbcDaoImpl
class, but not entirely sure of the best way to proceed. 我已经研究了UserDetailsService,更具体地说是
JdbcDaoImpl
类,但并不完全确定最佳方法。 If I simply override/extend by calling super.loadUserByUsername
the loadUserByUsername
method to return my own UserDetails object is that sufficient? 如果我只是简单地通过调用
super.loadUserByUsername
覆盖/扩展,则loadUserByUsername
方法返回我自己的UserDetails对象就足够了吗? Then would I just be able to do SecurityContextHolder.getContext().getAuthentication().getDetails()
and cast it to my own object? 然后,我是否能够执行
SecurityContextHolder.getContext().getAuthentication().getDetails()
并将其SecurityContextHolder.getContext().getAuthentication().getDetails()
为我自己的对象?
I've found other posts on StackOverflow that relate to this, but most seem to be ignoring anything to do with Authorities and Roles that are retrieved from the DB, so I'm not sure if this is the best way to proceed. 我在StackOverflow上找到了与此相关的其他帖子,但是大多数帖子似乎都忽略了与从数据库中检索到的Authorities和Roles有关的任何内容,因此我不确定这是否是最好的处理方法。
The short answer: Yes you can do exactly as you planned. 简短的答案:是的,您可以完全按照计划进行。 Keep in mind that some functionality like "hasRole" checks the authorities list and not the user details by default.
请记住,默认情况下,某些功能(例如“ hasRole”)会检查权限列表,而不是用户详细信息。
The long answer: Keeping a user object in the securitycontext, which is held in the session can have some side effects. 很长的答案:将用户对象保留在会话中保留的securitycontext中可能会有一些副作用。 This is particularly true when you are using hibernate.
使用休眠模式时尤其如此。 Lazy exceptions anyone?
懒惰的例外有人吗? ;) We went this route first and several calls later some LIEs happend which was quite tricky to follow up.
;)我们先走了这条路线,然后打了几个电话,发生了一些LIE,要跟进它非常棘手。 Using the OpenSessionInView filter, we thought we are safe, but that's just wrong as in the next request the session is gone.
使用OpenSessionInView过滤器,我们认为我们很安全,但这是错误的,因为在下一个请求中会话已消失。 So we loaded more related objects from the user and it still happend.
因此,我们从用户那里加载了更多相关对象,并且这种情况仍然发生。 Just later :)
稍后:)
We had three options. 我们有三个选择。 Either merge the user object on each request, create a pojo holding just the neccessary security information in the userdetails, or just keep the principal (login) in the security context and load the user object once it's needed.
要么在每个请求上合并用户对象,要么创建一个pojo,仅在用户详细信息中保存必要的安全性信息,要么仅将主体(登录名)保留在安全性上下文中,并在需要时加载用户对象。
We went with the third solution as hibernate does a good job using the second level cache. 我们采用了第三种解决方案,因为休眠状态使用第二级缓存可以很好地完成工作。 As a side effect the security is now more reliable as spring security gets now the latest version of a user on each request and does not work with "stale" user roles.
副作用是,安全性现在更加可靠,因为Spring Security会在每个请求上获取用户的最新版本,并且不适用于“过时的”用户角色。
So if you dont use hibernate or you can guarantee that no LIEs will happen go for solution one or two. 因此,如果您不使用休眠模式,或者可以保证不会发生任何LIE,请选择解决方案一或二。 Else i would recommend our approach.
否则我会推荐我们的方法。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.