使用 Apache Shiro 从 session/authenticationtoken/cache 中检索用户信息

Posted

技术标签:

【中文标题】使用 Apache Shiro 从 session/authenticationtoken/cache 中检索用户信息【英文标题】:Retrieving user information from session/authenticationtoken/cache using Apache Shiro 【发布时间】:2014-05-31 22:38:33 【问题描述】:

我正在尝试使用 JPA 数据源通过 Apache Shiro 构建动态 Allowance/Permission。

最后,一切都回到了这个类:

public class CustomAuthorizationFilter extends HttpMethodPermissionFilter 

 @Override
 public boolean isAccessAllowed(ServletRequest r, ServletResponse r, Object m) throws IOException 
  //Somehow get the user stored somewhere in the servlet memory
  SysUser loggedUser = %some_code_here%
  for (String allowance : loggedUser.getAllowances()) 
   // Do many validations
   if (pathsMatch(allowance, request)) 
    return true;
   
  

  return super.isAccessAllowed(request, response, mappedValue);
 


每个请求都会触发 isAccessAllowed() 方法,因此我不想从数据库中获取信息。 Shiro 构建了许多关于用户的对象,其中之一是 AuthorizationInfo。我构建了一个 CustomAuthorizationInfo ,其中 Permissions 和 Allowances 列表位于其中...但是如何在不重新访问数据库的情况下检索它们?

是否可以在不访问数据库的情况下使用 shiro 从经过身份验证的用户那里存储/检索信息?

(PS.: isPermitted 之类的方法并不能解决问题,因为我需要权限本身才能使用 pathsMatch() 方法)。

【问题讨论】:

【参考方案1】:

Shiro 具有内置的缓存机制,因此当用户登录时,所有建立的凭据都存储在缓存中,并且只要用户没有注销,每次后续调用都会在缓存中检索。

如果您查看 AuthorizingRealm.getAuthorizationInfo 的源代码,您可以看到它从缓存中检索 AuthorizationInfo,在配置缓存时

http://svn.apache.org/repos/asf/shiro/tags/shiro-root-1.2.3/core/src/main/java/org/apache/shiro/realm/AuthorizingRealm.java

在此处查看有关缓存的文档:https://shiro.apache.org/caching.html

快速的解决方案是配置一个简单的内存缓存:

cacheManager = org.apache.shiro.cache.MemoryConstrainedCacheManager
securityManager.cacheManager = $cacheManager

这应该会导致每个用户会话只有一个数据库操作来检索凭据。

【讨论】:

以上是关于使用 Apache Shiro 从 session/authenticationtoken/cache 中检索用户信息的主要内容,如果未能解决你的问题,请参考以下文章

细说shiro之六:session管理

B 不能转换为 org.apache.shiro.session.Session

解决org.apache.shiro.session.UnknownSessionException: There is no session with id的问题

org.apache.shiro.session.InvalidSessionException: java.lang.IllegalStateException: getAttribute: Ses

使用shiro的session时出现不能登陆

关于org.apache.shiro.SecurityUtils.getSubject().getSession()