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

本文深入探讨了在使用Shiro框架时,用户访问无权限页面导致的异常问题及解决策略。通过分析源码,明确了unauthorizedUrl配置仅对特定过滤器生效的原因,并提供了异常统一处理的实现方式。

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

既上一篇博客,当用户在登陆之后,访问没有权限的页面时,没有跳转到指定页面,并且后台报错。我们之前在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 "权限认证失败";
    }
}

总结:

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

评论 17
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值