Java 如何在servlet容器中使用ApacheShiro仅在http请求期间缓存数据?

Java 如何在servlet容器中使用ApacheShiro仅在http请求期间缓存数据?,java,jakarta-ee,servlets,shiro,Java,Jakarta Ee,Servlets,Shiro,更具体地说,我发现我正在实现一个定制的authorizationrealm,它分别声明了用于返回AuthorizationInfo和AuthorizationInfo对象的模板方法doGetAuthorizationInfo() 但是,当我在doGetAuthenticationInfo()中检索AuthenticationInfo(JPA实体)的数据时,我发现我已经拥有必要的AuthorizationInfo。唉,没有明显的好方法来保存这些数据,所以我不得不扔掉它,只是为了在授权过滤器最终在过

更具体地说,我发现我正在实现一个定制的
authorizationrealm
,它分别声明了用于返回
AuthorizationInfo
AuthorizationInfo
对象的模板方法
doGetAuthorizationInfo()

但是,当我在doGetAuthenticationInfo()中检索AuthenticationInfo(JPA实体)的数据时,我发现我已经拥有必要的AuthorizationInfo。唉,没有明显的好方法来保存这些数据,所以我不得不扔掉它,只是为了在授权过滤器最终在过滤器链中轮到它时执行另一个JPA查找

瞧:

public class CustomRealm extends AuthorizingRealm {

  @Override
  protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) {
    UsernamePasswordToken userPassToken = (UsernamePasswordToken) token;
    String username = userPassToken.getUsername()

    User user; // Contains username, password, and roles
    // Perform JPA lookup by username...
    return constructSimpleAuthenticationInfoFromUser(user);
  }

  @Override
  protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
    // Look up user again? :(
    ...
  }
}
我考虑了许多可能性:

  • 使用领域缓存。应用程序将在分布式环境中运行,因此可以运行任意数量的JVM。默认的领域缓存管理器实现不能解决所有固有的问题,设置企业实现似乎超出了本项目的范围
  • 使用主题会话。没有服务器端状态,如果可能的话,我希望保持这种状态。也许您可以强制会话的行为类似于请求范围,但我不知道如何这样做,这可能会导致混淆
  • 实现我自己的主题。每个请求通常都有一个主题实例,但不清楚如何引导它,我会冒着失去很多潜在功能的风险
  • 使用Shiro ThreadContext对象。我可以将数据作为threadlocal属性附加到ThreadContext。Servlet容器通常遵循每请求一个线程的模型,主题实例本身似乎在这里冷静下来,等待其不可避免的垃圾收集。Shiro似乎也能自动建立和分解上下文。然而,关于这方面的文档并不多,源代码对我来说很难理解
  • 最后,默认的WebSecurityManager保留CustomRealm的单例实例,看起来每个JVM一个。简单地设置一些本地实例属性不是线程安全的

    这似乎是一个常见的数据检索选项和典型的部署场景。那么,我错过了什么


    谢谢

    我会选择选项4-使用
    ThreadLocal
    对象,因为您的需求明确指出对象的生存期必须是http请求

    请看下面的讨论:

    本地文件: