shiro标签页点击报错: No SecurityManager accessible to the calling code...

本文介绍了解决在使用Apache Shiro进行按钮级别的权限控制时遇到的UnavailableSecurityManagerException异常问题。通过对项目配置的深入分析,找到了问题的根本原因在于未对JSP页面进行Shiro管理,提供了两种解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

shiro按钮配置标签报错问题

问题:

最近的项目需要将按钮也动态配置进去。我按照网上的步骤加上shiro的taglib标签

<%@ taglib prefix="shiro" uri="http://shiro.apache.org/tags" %>

然后在该页面的某个按钮上加上

<shiro:hasPermission name="user_authorize"><button id="user_limits">用户授权</button></shiro:hasPermission>

并且后台的方法里边也有如下操作

@Override

protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
 User user = (User)principals.getPrimaryPrincipal();
 SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
List<SysFunc> sysFuncList = sysFuncService.selectSysFuncByUserName(user.getUserName()); //获取所有按钮的功能记录
if(sysFuncList != null){
 Set<String> permissonSet = new HashSet<String>();
 for(SysFunc func:sysFuncList){
    if(!StringUtils.isEmpty(func.getFunc_Url())){
        permissonSet.add(func.getFunc_Url());
    };
 }    //如下,我也将当前用户有的按钮权限字符串放进去了。
    info.setStringPermissions(permissonSet);
 }
 return info;
}

但是我在这么配置好之后,一点击那个jsp页面就报

UnavailableSecurityManagerException: No SecurityManager accessible to the calling code, either bound to the org.apache.shiro.util.ThreadContext or as a vm static singleton.  This is an invalid application configuration.

从字面上来看,好像我没有配置securityManager的东西,但是!!!!,我登录是没有问题的。问题如下:

这里写图片描述

既然其他页面是可以的,那为什么一配置上这个标签就报错呢,网上有说过滤器的顺序原因,还有说是少配置了DispatcherType,但我并没有其他过滤器,也试过多配置几个dispatcherType,都不行。

问题最终原因:

  最后发现问题出在jsp页面上,上图我们的系统左边的树,那些用户管理、组织机构对应的页面,全部是直接点击访问的jsp页面,并没有经过controller那样返回给它,而我的shiro配置因为当初为了减少静态资源的过滤,而把所有带“.”的文件统统放开了,所以jsp页面在不登录也是可以访问的,这就导致在点击带shiro标签页面的时候,它在去调用权限验证方法的时候,就会报错,也就是上边的错误。

解决方法:
具体办法有两种:

1、一种是最容易想到的,就是将这些页面点击事件,从直接访问jsp页面变成访问接口,通过接口返回jsp页面。但是现在项目已经快结束,每个jsp页面都给写一个controller,我就疯了,当然在开始的话是可以这么搞的。
2、一种是最简单的,就是既然jsp不在shiro管理下,那想办法把它管理起来不就可以了嘛。
  首先找到你的shiroFilter配置的位置,我的是spring boot项目,spring boot项目是在shiroConfig类里,是下图这样:
这里写图片描述
  在shiroFilter配置有MShiroFilterFactoryBean类,进入到这个类里,你可能不叫这个名字,但肯定会有这么一个配置
进入到这个类中,添加如下变量
这里写图片描述

  同样在该类中的最下边:

这里写图片描述
  上图定义了一个开关,是用来,判断当前请求的带“.”的url中,是不是jsp,如果是jsp则走shiro的过滤,如果不是,则不走。
如上配置以后,再重启项目后,就不会有这个错误了。这个错误影响我好几天。唉,没想到是这个原因。。。

### 解决 Shiro 中 `UnavailableSecurityManagerException` 异常 当遇到 `No SecurityManager accessible to the calling code` 的异常时,通常是因为应用程序未能正确初始化或配置 `SecurityManager`。为了有效解决此问题,可以采取以下措施: #### 1. 配置 Spring Boot 应用程序中的 Shiro Bean 确保在 Spring Boot 应用程序上下文中定义并注册了 `SecurityManager` bean。这可以通过创建一个配置类来实现,在该类中标记为 `@Configuration` 并提供相应的bean定义。 ```java import org.apache.shiro.mgt.DefaultSecurityManager; import org.apache.shiro.realm.text.IniRealm; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class ShiroConfig { @Bean public DefaultSecurityManager securityManager() { DefaultSecurityManager manager = new DefaultSecurityManager(); manager.setRealm(new IniRealm("classpath:shiro.ini")); return manager; } } ``` 上述代码片段展示了如何声明一个 `DefaultSecurityManager` 实例,并将其关联到具体的 Realm 上下文[^1]。 #### 2. 初始化静态 Singleton SecurityManager 如果应用依赖于静态访问方式,则需保证 `SecurityUtils.setSecurityManager()` 方法被调用来设置全局唯一的 `SecurityManager` 实例。可以在启动阶段完成这项工作,比如在一个监听器或者事件处理器内执行。 ```java import org.apache.shiro.SecurityUtils; import org.apache.shiro.mgt.DefaultSecurityManager; import org.springframework.beans.factory.InitializingBean; import org.springframework.stereotype.Component; @Component public class ShiroInitializer implements InitializingBean { private final DefaultSecurityManager securityManager; public ShiroInitializer(DefaultSecurityManager securityManager) { this.securityManager = securityManager; } @Override public void afterPropertiesSet() throws Exception { SecurityUtils.setSecurityManager(securityManager); } } ``` 这段代码说明了怎样利用 Spring 生命周期接口 `InitializingBean` 来确保 `SecurityManager` 被及时注入给 `SecurityUtils` 工具类。 #### 3. 检查线程绑定机制 有时即使已经设置了静态的 `SecurityManager` 单例实例,但在某些情况下仍然会抛出同样的异常。此时应考虑是否存在多线程环境下的竞争条件,即不同线程之间共享同一个 `Subject` 或者未正确传播当前用户的认证状态。对于这种情况,建议启用Shiro自带的支持自动管理ThreadLocal变量的功能。 ```properties # application.properties 文件中添加如下配置项 shiro.subjectDAO.sessionStorageEvaluator.cacheName=shiro-activeSessionsCache shiro.subjectDAO.principalCollectionSerializer.class=com.example.MyPrincipalCollectionSerializer ``` 以上属性可以帮助改善跨请求间的安全主体信息传递效率以及减少潜在的竞争风险[^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

茁壮成长的凌大大

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值