shiro无权限,不跳转到指定页面。setUnauthorizedUrl无效

既上一篇博客,当用户在登陆之后,访问没有权限的页面时,没有跳转到指定页面,并且后台报错。我们之前在ShiroConfig中已经设置了无权限的跳转页面,那么为什么没起作用呢?

问题复现:

org.apache.shiro.authz.AuthorizationException: Not authorized to invoke method: public java.lang.String com.cj.shirodemo.controller.UserController.showUser()
	at org.apache.shiro.authz.aop.AuthorizingAnnotationMethodInterceptor.assertAuthorized(AuthorizingAnnotationMethodInterceptor.java:90) ~[shiro-core-1.3.2.jar:1.3.2]
	at org.apache.shiro.authz.aop.AnnotationsAuthorizingMethodInterceptor.assertAuthorized(AnnotationsAuthorizingMethodInterceptor.java:100) ~[shiro-core-1.3.2.jar:1.3.2]
	at org.apache.shiro.authz.aop.AuthorizingMethodInterceptor.invoke(AuthorizingMethodInterceptor.java:38) ~[shiro-core-1.3.2.jar:1.3.2]
	at org.apache.shiro.spring.security.interceptor.AopAllianceAnnotationsAuthorizingMethodInterceptor.invoke(AopAllianceAnnotationsAuthorizingMethodInterceptor.java:115) ~[shiro-spring-1.3.2.jar:1.3.2]
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.1.4.RELEASE.jar:5.1.4.RELEASE]
	at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:688) ~[spring-aop-5.1.4.RELEASE.jar:5.1.4.RELEASE]

对于这种问题,我们要从设置跳转页面开始看,我开发工具用的idea。可以按住ctrl+鼠标点击进入源码(idea好-。-)。
进入到ShiroFilterFactoryBean类中,我们可以大概浏览下类的基本构成(包括方法和属性),找到setUnauthorizedUrl方法:

 public void setUnauthorizedUrl(String unauthorizedUrl) {
        this.unauthorizedUrl = unauthorizedUrl;
    }

咦,很简单啊,就是赋值操作,ok。那我们再来看看unauthorizedUrl这个参数在整个实体类中在哪个地方使用的。
一共找到下面几个地方:

	 public String getUnauthorizedUrl() {
        return this.unauthorizedUrl;
    }

    public void setUnauthorizedUrl(String unauthorizedUrl) {
        this.unauthorizedUrl = unauthorizedUrl;
    }
    ..........
      private void applyUnauthorizedUrlIfNecessary(Filter filter) {
        String unauthorizedUrl = this.getUnauthorizedUrl();
        if (StringUtils.hasText(unauthorizedUrl) && filter instanceof AuthorizationFilter) {
            AuthorizationFilter authzFilter = (AuthorizationFilter)filter;
            String existingUnauthorizedUrl = authzFilter.getUnauthorizedUrl();
            if (existingUnauthorizedUrl == null) {
                authzFilter.setUnauthorizedUrl(unauthorizedUrl);
            }
        }

    }

    private void applyGlobalPropertiesIfNecessary(Filter filter) {
        this.applyLoginUrlIfNecessary(filter);
        this.applySuccessUrlIfNecessary(filter);
        this.applyUnauthorizedUrlIfNecessary(filter);
    }

到这里,我们已经找到关键的地方 :

   private void applyUnauthorizedUrlIfNecessary(Filter filter) {
        String unauthorizedUrl = this.getUnauthorizedUrl();
        if (StringUtils.hasText(unauthorizedUrl) && filter instanceof AuthorizationFilter) {
            AuthorizationFilter authzFilter = (AuthorizationFilter)filter;
            String existingUnauthorizedUrl = authzFilter.getUnauthorizedUrl();
            if (existingUnauthorizedUrl == null) {
                authzFilter.setUnauthorizedUrl(unauthorizedUrl);
            }
        }
    }

applyUnauthorizedUrlIfNecessary就是设置无权限访问的url的方法。其中有一行很重要filter instanceof AuthorizationFilter 这个过滤器必须要是AuthorizationFilter过滤器才行,那么什么才是AuthorizationFilter类型的过滤器呢?
我们可以点进AuthorizationFilter的源码看一下。
AuthorizationFilter是一个抽象类,抽象类没什么好看的,我们看看他的具体的类:
在这里插入图片描述
这些才是具体的类。换句话说只有这些过滤器才可以使设置生效。
这些过滤器到底是什么呢?
看过我之前博客的都知道在ShiroConfig设置权限的时候,我曾经叫大家看下package org.apache.shiro.web.filter.mgt.DefaultFilter,这个是shiro默认提供给我们的过滤器,不知道大家有没有看-。-,荣老夫截个图吧:
在这里插入图片描述
这是个啥?不对,稍微等一等,HttpMethodPermissionFilterSslFilterPermissionsAuthorizationFilterRolesAuthorizationFilter这几个貌似就是能使setUnauthorizedUrl这个方法生效的过滤器耶。

原因:

只有perms,roles,ssl,rest,port才是属于AuthorizationFilter,而anon,authcBasic,auchc,user是AuthenticationFilter,所以unauthorizedUrl设置后页面不跳转。

解决方案:

  1. 既然不是属于AuthorizationFilter,那就改为AuthorizationFilter。(这种方法没试过,不做评价,感兴趣的同学可以试一试)。
  2. 对抛出的异常进行统一处理跳转。

方案一:

略略略略略略略略略略略略略略略-。-

方案二:

package com.cj.shirodemo.exceptions;

import org.apache.shiro.authz.AuthorizationException;
import org.apache.shiro.authz.UnauthorizedException;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

/**
 * 描述:
 *
 * @author caojing
 * @create 2019-01-27-17:12
 */
@ControllerAdvice
public class NoPermissionException {
    @ResponseBody
    @ExceptionHandler(UnauthorizedException.class)
    public String handleShiroException(Exception ex) {
        return "无权限";
    }
    @ResponseBody
    @ExceptionHandler(AuthorizationException.class)
    public String AuthorizationException(Exception ex) {
        return "权限认证失败";
    }
}

总结:

我该说点啥呢?其实有问题的话不要慌,先找出问题产生的原因,从根本上去解决问题,而不是一遇到问题去百度(或者你先解决问题,在回来看一眼为什么会产生这个问题),只有这样,你才能在下次遇到相同问题的时候才不又去问百度。

  • 29
    点赞
  • 54
    收藏
    觉得还不错? 一键收藏
  • 17
    评论
根据提供的引用内容,Shiro权限管理器可以根据realm的授权信息判断是否拥有某个权限,如果没有权限跳转到响应页面。如果需要放行某个页面,则可以在Shiro的配置文件中进行相应的配置。具体步骤如下: 1. 在Shiro的配置文件中,找到`<shiro:filter>`标签,添加一个新的`<shiro:filter>`标签,例如: ```xml <shiro:filter> <shiro:filter-name>myFilter</shiro:filter-name> <shiro:filter-class>com.example.MyFilter</shiro:filter-class> </shiro:filter> ``` 2. 在`<shiro:filter>`标签中,设置`<shiro:perms>`标签,指定需要放行的页面权限,例如: ```xml <shiro:filter> <shiro:filter-name>myFilter</shiro:filter-name> <shiro:filter-class>com.example.MyFilter</shiro:filter-class> <shiro:perms> /index.html = myPermission </shiro:perms> </shiro:filter> ``` 上述配置表示,放行`/index.html`页面,并且需要具有`myPermission`权限。 3. 在Shiro的配置文件中,找到`<shiro:filter-mapping>`标签,添加一个新的`<shiro:filter-mapping>`标签,例如: ```xml <shiro:filter-mapping> <shiro:filter-name>myFilter</shiro:filter-name> <shiro:url-pattern>/index.html</shiro:url-pattern> </shiro:filter-mapping> ``` 上述配置表示,将`myFilter`过滤器映射到`/index.html`页面。 通过上述配置,可以实现对某个页面的放行。需要注意的是,如果需要放行的页面需要具有多个权限,则可以使用逗号分隔多个权限,例如: ```xml <shiro:perms> /index.html = myPermission1, myPermission2 </shiro:perms> ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 17
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值