首页 > 解决方案 > @Transactional 的 AOP 问题

问题描述

在我的 spring 5 MVC 应用程序中,我在调度程序 servlet xml 中使用<aop:aspectj-autoproxy />. 控制器类的方法用@PreAuthorize("hasAuthority('SOME_AUTH')").

如果我启用 AOP,hasAuthority() 方法会调用数据库来检查权限。

如果我禁用 AOP,hasAuthority() 方法不会调用数据库来检查权限,而是从上下文本身检查权限。

(这是我通过在 TRACE 级别启用日志的观察结果。启用 AOP 后,我会看到用于检查控制台权限的查询。禁用 AOP 后,我看不到控制台上的查询。)

当 hasAuthority() 开始与数据库交互时,我必须注释控制器方法,@Transactional以便关闭当前数据库会话。如果我不这样做,应用程序会在几次成功请求后停止工作,因为所有连接都被消耗,因为数据库会话没有关闭。

现在的问题是我不想with @PreAuthorize()用@Transactional 注释控制器()的所有方法。此外,我不想将所有 hasAuthority() 方法移动到自定义 SecurityUtil 类,然后将 hasAuthority() 替换为@securityUtil.hasAuthority().

有没有其他方法可以在我的控制器方法上不使用@Transactional 来实现这一点,或者是否有某种方法可以强制 Spring Security 在启用 AOP 时从上下文而不是从数据库中检查权限?

更新

hasAuthority() 生成的查询如下:

select this_.type as y0_, this_.key_id as y1_ from permission_master this_ where this_.status=? and this_.key_id in()

SecurityExpressionRoot.java 类有方法 hasAuthority(),它依次调用以下方法: hasAuthority() -> hasAnyAuthority() -> hasAnyAuthorityName -> getAuthoritySet() -> roleHierarchy.getReachableGrantedAuthorities()

在我们的代码库中,调用 roleHierarchy.getReachableGrantedAuthorities() 被覆盖,因此我将 @Transactional 添加到覆盖调用并解决了我的问题。但我的问题是为什么启用 AOP 会使 hasAuthority() 调用数据库而禁用 AOP 不会。

标签: spring-securityaopaspectjtransactional

解决方案


推荐阅读