java—我可以将自己的用户对象推入spring的securitycontext吗?

jhiyze9q  于 2021-07-09  发布在  Java
关注(0)|答案(1)|浏览(184)

我对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>

我意识到我可以找回 Principal 从securitycontext获取用户名并重新查询给定用户名的数据库,但是我认为简单地存储整个数据库会更容易 User 对象,使其在整个应用程序中需要时易于访问,而不是仅将用户名、密码和启用字段存储在 UserDetails 对象。
我研究了userdetails服务,更具体地说是 JdbcDaoImpl 类,但不完全确定的最佳方式进行。如果我通过调用 super.loadUserByUsername 这个 loadUserByUsername 方法返回我自己的userdetails对象,这样就足够了吗?那我能做什么呢 SecurityContextHolder.getContext().getAuthentication().getDetails() 把它扔到我自己的物体上?
我在stackoverflow上发现了其他与此相关的帖子,但大多数似乎忽略了与从db中检索到的权限和角色有关的任何内容,因此我不确定这是否是最好的方法。

hyrbngr7

hyrbngr71#

简而言之:是的,你可以完全按照你的计划去做。请记住,某些功能(如“hasrole”)默认检查权限列表,而不是用户详细信息。
答案很长:将用户对象保存在会话中的securitycontext中可能会产生一些副作用。使用hibernate时尤其如此。(有人吗?;)我们先走了这条路,后来打了几个电话,说了一些谎话,这很难回答。使用opensessioninview过滤器,我们认为我们是安全的,但这是错误的,因为在下一个请求中,会话已经结束。所以我们从用户那里加载了更多相关的对象,结果还是发生了。稍后:)
我们有三个选择。在每个请求中合并用户对象,创建一个pojo,其中只包含userdetails中必需的安全信息,或者只将主体(登录名)保留在安全上下文中,并在需要时加载用户对象。
我们使用了第三种解决方案,因为hibernate很好地使用了二级缓存。作为一个副作用,现在的安全性更加可靠,因为Spring Security 在每个请求上都获得了用户的最新版本,并且不适用于“过时”的用户角色。
所以,如果你不使用hibernate或者你可以保证不会发生谎言,那就去找一两个解决方案。否则我会推荐我们的方法。

相关问题