每个Spring Security会话使用具有专用数据源连接的Hibernate会话

是否可以在运行时更改Hibernate Session的数据库身份validation(或创建新的Hibernate Session ),并将其链接到当前登录的Web用户?

例如,当特定的Spring Security管理用户登录时,使用不同的数据库角色重新连接它,并在该会话的http会话的整个生命周期内使用该连接?

hibernate会话和http会话没有关系,我有点难以理解你的问题。 如果您要在http会话中存储用户详细信息(例如角色),则在描述角色已更改但用户仍具有旧权限时会出现此问题,因为Spring Security正在从会话中读取用户详细信息数据库。 但是,如果您只是存储用户ID而不在http会话中保留有关用户的任何信息,则不会出现刷新问题。 通常,您甚至不会将用户存储在会话中,因为您只能访问Spring中的主体。 Hibernate会话是根据事务创建和关闭的。 您应该使用事务,以便数据库为您处理所有并发问题,并且您不必担心是否例如用户密码被更改而其他事务将要使用它。

通常,您不应该在Http会话中存储数据库中的任何内容。 这是你追求的吗?

编辑还有点不清楚你在问什么,我会猜测。 您是否希望为数据库创建新的数据库凭据,具有类似于mysql workbench中的特权,然后在用户登录时使用与这些凭据的数据库连接进行每个Http会话?

Spring中没有机制来执行此操作,因为这将依赖于数据库。 不建议每个Http会话创建一个数据库连接,因为你将丢失你的漂亮的小连接池优化Hibernate和Spring。 如果你的应用程序有很多用户,那么很多连接都会遭受重大性能损失,如果有很多用户,甚至可能会冻结。 而且我需要澄清一下你可能与数据库有一个开放的连接,但是你不要让hibernate会话长时间打开,它们只是你需要时与数据库连接交谈的包装器。 虽然我不建议你这样做,如果你在我的团队中,橄榄球会阻止你阻止你,我想有两种方法:

首先,您必须通过Java运行某些脚本来在命令行上创建凭据。 然后,您将需要创建一个会话数据源,并将其连接到您的所有Daos。 您将无法使用任何Spring的东西,如@Transactional或@PreAuthorize等。 (尽管你仍然可以使用@PreAuthorize,但不要使用hasRole,或任何与错误的数据源通信的函数)。 您只需手动执行权限逻辑,并手动编程您的hibernate会话。

如果这对你来说还不够好,那么你可以完全疯狂,并购买一台function非常强大的服务器并为每个http会话启动一个完整的其他’克隆’Spring Webapp,除非它有不同的根目录,否则完全相同url和新的连接配置。 然后将该用户重定向到他们的个人webapp,谈论一流的服务。

老实说,无论哪种方式,这都是一个非常糟糕的主意,您可以使用Spring Security实现相同的用户体验。 数据库连接只是最佳使用的资源。 我不会给每个webapp用户提供他们自己的连接,只不过我会给公司的每个员工自己的私人厕所。 相反,我会给他们一张钥匙卡,允许共享可用的厕所,你应该这样做。

我不确定每个用户拥有一个专用的数据库会话是否可行。 即使技术上可行,具有大量用户群的应用程序也不会很好地扩展。 另一种方法是配置标准连接池,并在每次从池中签出时将连接与特定Web应用程序用户相关联。

这里有一些讨论(从Oracle的角度来看,但无论RDBMS如何,相同的原则都适用):

许多应用程序使用会话池来设置多个会话以供多个应用程序用户重用。 用户向中间层应用程序进行身份validation,该应用程序使用单个身份登录数据库并维护所有用户连接。 在此模型中,应用程序用户是对应用程序的中间层进行身份validation但是数据库不知道的用户……在这些情况下,应用程序通常作为单个数据库用户连接并且所有操作都采取作为那个用户。 由于所有用户会话都是作为同一用户创建的,因此该安全模型使得为每个用户实现数据分离变得非常困难。 这些应用程序可以使用CLIENT_IDENTIFIER属性将实际应用程序用户身份保留到数据库。

https://docs.oracle.com/cd/B19306_01/network.102/b14266/apdvprxy.htm#i1010372

您将如何实现这一点将在下面的Spring文档的8.2节中讨论。 请注意,虽然这是在特定于Spring的Oracle扩展的部分中隐藏的,但8.2节(与8.1不同)中没有任何内容是特定于Oracle的(除了执行的语句之外),并且只需指定相关程序调用或SQL:

http://docs.spring.io/spring-data/jdbc/docs/current/reference/html/orcl.connection.html

我对Postgres不太熟悉,但我想你想在每个Connection checkout上做的调用会是这样的:

https://www.postgresql.org/docs/8.4/static/sql-set-role.html

Spring文档中给出的示例使用XML配置。 如果您使用的是Java配置,那么它看起来像:

 @Component @Aspect public class ClientIdentifierConnectionPreparer implements ConnectionPreparer { @AfterReturning(pointcut = "execution(* *.getConnection(..))", returning = "connection") public Connection prepare(Connection connection) throws SQLException { SecurityContextHolder.getContext().getAuthentication().getPrincipal(); String webAppUser = //; CallableStatement cs = connection.prepareCall("my postgres statement"); cs.setString(1, webAppUser); cs.execute(); cs.close(); return connection; } } @Configuration @EnableAspectJAutoProxy public class SomeConfigurationClass { }