NutzCN Logo
问答 shiro RequiresPermissions 无权限 返回登录页面
发布于 1835天前 作者 Hamming 14214 次浏览 复制 上一个帖子 下一个帖子
标签:

@RequiresPermissions("sys:user:view")
无权限 setStringPermissions 有对应值 提示 无权限;
如果 无权限 如何指定 页面 提示 无权限 若 未登录 则跳转登录呢

package io.nutz.nutzsite.common.shiro;

import io.nutz.nutzsite.common.exception.EmptyCaptchaException;
import io.nutz.nutzsite.common.exception.IncorrectCaptchaException;
import io.nutz.nutzsite.module.sys.models.User;
import io.nutz.nutzsite.module.sys.services.UserService;
import org.apache.commons.lang3.math.NumberUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authc.credential.CredentialsMatcher;
import org.apache.shiro.authz.AuthorizationException;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.cache.CacheManager;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.nutz.dao.Cnd;
import org.nutz.integration.shiro.AbstractSimpleAuthorizingRealm;
import org.nutz.integration.shiro.SimpleShiroToken;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.lang.Lang;
import org.nutz.lang.Strings;

import java.util.Set;

/**
 * 自定义Realm 处理登录 权限
 */
@IocBean(name = "shiroRealm", fields = "dao")
public class UserRealm extends AbstractSimpleAuthorizingRealm {
    @Inject
    private UserService userService;

    /**
     * 授权
     * @param principals
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        // null usernames are invalid
        if (principals == null) {
            throw new AuthorizationException("PrincipalCollection method argument cannot be null.");
        }
        User user = (User) principals.getPrimaryPrincipal();
        if (user == null) {
            return null;
        }
        // 角色列表
        Set<String> roles =userService.getRoleCodeList(user);
        // 功能列表
        Set<String> menus = userService.getMenuPermsList(user.getId());

        SimpleAuthorizationInfo auth = new SimpleAuthorizationInfo();
		auth.setRoles(roles);
		auth.setStringPermissions(menus);
        return auth;
    }

    /**
     * 登录验证
     * @param token
     * @return
     * @throws AuthenticationException
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        CaptchaToken authcToken = (CaptchaToken) token;
        String loginname = authcToken.getUsername();
        String captcha = authcToken.getCaptcha();
        if (Strings.isBlank(loginname)) {
            throw Lang.makeThrow(AuthenticationException.class, "Account name is empty");
        }
        User user = dao().fetch(User.class, Cnd.where("login_name","=",loginname));
        if (Lang.isEmpty(user)) {
            throw Lang.makeThrow(UnknownAccountException.class, "Account [ %s ] not found", loginname);
        }
        int errCount = NumberUtils.toInt(Strings.sNull(SecurityUtils.getSubject().getSession(true).getAttribute("errCount")));
        if (errCount > 2) {
            //输错三次显示验证码窗口
            if (Strings.isBlank(captcha)) {
                throw Lang.makeThrow(EmptyCaptchaException.class, "Captcha is empty");
            }
            String _captcha = Strings.sBlank(SecurityUtils.getSubject().getSession(true).getAttribute("captcha"));
            if (!authcToken.getCaptcha().equalsIgnoreCase(_captcha)) {
                throw Lang.makeThrow(IncorrectCaptchaException.class, "Captcha is error");
            }
        }
        if (user.isStatus()) {
            throw Lang.makeThrow(LockedAccountException.class, "Account [ %s ] is locked.", loginname);
        }
        //设置验证码次数为零
        SecurityUtils.getSubject().getSession(true).setAttribute("errCount", 0);
        SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user, user.getPassword(), getName());
        info.setCredentialsSalt(ByteSource.Util.bytes(user.getSalt()));
        return info;
    }

    public UserRealm() {
        this(null, null);
    }

    public UserRealm(CacheManager cacheManager, CredentialsMatcher matcher) {
        super(cacheManager, matcher);
        // 设置token类型是关键!!!
        setAuthenticationTokenClass(CaptchaToken.class);
    }

    public UserRealm(CacheManager cacheManager) {
        this(cacheManager, null);
    }

    public UserRealm(CredentialsMatcher matcher) {
        this(null, matcher);
    }

    /**
     * 清理缓存权限
     */
    public void clearCachedAuthorizationInfo()
    {
        this.clearCachedAuthorizationInfo(SecurityUtils.getSubject().getPrincipals());
    }
}

23 回复

单个url入口方法定制?还是全局?

指向一个入口方法,在里面判断吧

或者自定义个注解

问题在这里 org.nutz.integration.shiro.NutShiroProcessor

@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
public @interface NutzShiroAuthUrl {

    String noLogin() default "";
    
    String noPermission() default "";
    
    String noRole() default "";
    
    String noUser() default "";
    
    String handler() default "";
}

弄个注解如何?

我可以重写 这个方法 没有权限 跳转 返回 503么

package org.nutz.integration.shiro;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.Collection;

import org.apache.shiro.authz.UnauthenticatedException;
import org.apache.shiro.authz.UnauthorizedException;
import org.apache.shiro.authz.aop.AuthorizingAnnotationMethodInterceptor;
import org.apache.shiro.web.util.WebUtils;
import org.nutz.lang.util.NutMap;
import org.nutz.mvc.ActionContext;
import org.nutz.mvc.ActionInfo;
import org.nutz.mvc.NutConfig;
import org.nutz.mvc.View;
import org.nutz.mvc.impl.processor.AbstractProcessor;
import org.nutz.mvc.view.ServerRedirectView;

/**
 * 处理Shiro注解及异常, 如果使用ioc方式放入动作链,必须使用非单例模式.
 * 
 * @author wendal<wendal1985@gmail.com>
 * @author rekoe<koukou890@gmail.com>
 * 
 *         如果是ajax请求的可以通过header 增加的状态属性做友好提示
 * 
 *         $(document).ajaxComplete(function(event, request, settings) { var
 *         loginStatus = request.getResponseHeader("loginStatus"); if
 *         (loginStatus == "accessDenied") { $.message("warn", "登录超时,请重新登录");
 *         setTimeout(function() { location.reload(true); }, 2000); } else if
 *         (loginStatus == "unauthorized") { $.message("warn", "对不起,您无此操作权限!");
 *         }else{ $.message("warn", "系统错误"); } });
 * 
 *         完整插件代码 插件开始//********************************* (function($) { var
 *         zIndex = 100; var $message=null; var messageTimer=null; $.message =
 *         function() { var message = {}; if ($.isPlainObject(arguments[0])) {
 *         message = arguments[0]; } else if (typeof arguments[0] === "string"
 *         && typeof arguments[1] === "string") { message.type = arguments[0];
 *         message.content = arguments[1]; } else { return false; } if
 *         (message.type == null || message.content == null) { return false; }
 *         if ($message == null) { $message = $('<div class="xxMessage"><div
 *         class
 *         ="messageContent message' + message.type + 'Icon"><\/div><\/div>');
 *         if (!window.XMLHttpRequest) { $message.append('<iframe
 *         class="messageIframe"><\/iframe>'); } $message.appendTo("body"); }
 * 
 *         $message.children("div").removeClass(
 *         "messagewarnIcon messageerrorIcon messagesuccessIcon"
 *         ).addClass("message" + message.type + "Icon").html(message.content);
 *         $message.css({"margin-left": - parseInt($message.outerWidth() / 2),
 *         "z-index": zIndex ++}).show(); clearTimeout(messageTimer);
 *         messageTimer = setTimeout(function() { $message.hide(); }, 3000);
 *         return $message; };
 * 
 *         $(document).ajaxComplete(function(event, request, settings) { var
 *         loginStatus = request.getResponseHeader("loginStatus"); if
 *         (loginStatus == "accessDenied") { $.message("warn", "登录超时,请重新登录");
 *         setTimeout(function() { location.reload(true); }, 2000); } else if
 *         (loginStatus == "unauthorized") { $.message("warn", "对不起,您无此操作权限!");
 *         }else { $.message("warn", "系统错误"); } }); })(jQuery);
 */
public class NutShiroProcessor extends AbstractProcessor {

	protected NutShiroMethodInterceptor interceptor;

	protected String loginUri;

	protected String noAuthUri;

	protected boolean match;

	protected boolean init;

	protected Class<? extends Annotation>[] annotations;
	
	public NutShiroProcessor(Collection<AuthorizingAnnotationMethodInterceptor> interceptors) {
        interceptor = new NutShiroMethodInterceptor(interceptors);
    }

	public NutShiroProcessor(Collection<AuthorizingAnnotationMethodInterceptor> interceptors, Class<? extends Annotation>... annotations) {
		interceptor = new NutShiroMethodInterceptor(interceptors);
		this.annotations = annotations;
	}

	public NutShiroProcessor() {
		interceptor = new NutShiroMethodInterceptor();
	}

	@Override
	public void init(NutConfig config, ActionInfo ai) throws Throwable {
		if (init) // 禁止重复初始化,常见于ioc注入且使用了单例
			throw new IllegalStateException("this Processor have bean inited!!");
		super.init(config, ai);
		if (annotations == null || annotations.length == 0) {
			match = NutShiro.match(ai.getMethod());
		} else {
			match = NutShiro.match(ai.getMethod()) || hasAuthAnnotion(ai.getMethod(), annotations);
		}
		init = true;
	}

	/**
	 * @param method
	 * @param annotations2
	 * @return
	 */
	private boolean hasAuthAnnotion(Method method, Class<? extends Annotation>[] annotations) {
		for (Class<? extends Annotation> clazz : annotations) {
			if (method.getAnnotation(clazz) != null) {
				return true;
			}
		}
		return false;
	}

	@Override
	public void process(ActionContext ac) throws Throwable {
		if (match) {
			try {
				interceptor.assertAuthorized(new NutShiroInterceptor(ac));
			} catch (Exception e) {
				whenException(ac, e);
				return;
			}
		}
		doNext(ac);
	}

	protected void whenException(ActionContext ac, Exception e) throws Throwable {
		Object val = ac.getRequest().getAttribute("shiro_auth_error");
		if (val != null && val instanceof View) {
			((View) val).render(ac.getRequest(), ac.getResponse(), null);
			return;
		}
		WebUtils.saveRequest(ac.getRequest());
		if (e instanceof UnauthenticatedException) {
			whenUnauthenticated(ac, (UnauthenticatedException) e);
		} else if (e instanceof UnauthorizedException) {
			whenUnauthorized(ac, (UnauthorizedException) e);
		} else {
			whenOtherException(ac, e);
		}
	}

	protected void whenUnauthenticated(ActionContext ac, UnauthenticatedException e) throws Exception {
		if (NutShiro.isAjax(ac.getRequest())) {
			ac.getResponse().addHeader("loginStatus", "accessDenied");
			NutShiro.rendAjaxResp(ac.getRequest(), ac.getResponse(), NutShiro.DefaultUnauthenticatedAjax);
		} else {
			new ServerRedirectView(loginUri()).render(ac.getRequest(), ac.getResponse(), null);
		}
	}

	protected NutMap ajaxFail(String msg, String type) {
		return new NutMap().setv("ok", false).setv("msg", msg).setv("type", type);
	}

	protected void whenUnauthorized(ActionContext ac, UnauthorizedException e) throws Exception {
		if (NutShiro.isAjax(ac.getRequest())) {
			ac.getResponse().addHeader("loginStatus", "unauthorized");
			NutShiro.rendAjaxResp(ac.getRequest(), ac.getResponse(), NutShiro.DefaultUnauthorizedAjax);
		} else {
			new ServerRedirectView(noAuthUri()).render(ac.getRequest(), ac.getResponse(), null);
		}
	}

	protected void whenOtherException(ActionContext ac, Exception e) throws Exception {
		if (NutShiro.isAjax(ac.getRequest())) {
			ac.getResponse().addHeader("loginStatus", "accessDenied");
			NutShiro.rendAjaxResp(ac.getRequest(), ac.getResponse(), NutShiro.DefaultOtherAjax);
		} else {
			new ServerRedirectView(loginUri()).render(ac.getRequest(), ac.getResponse(), null);
		}
	}

	protected String loginUri() {
		if (loginUri == null)
			return NutShiro.DefaultLoginURL;
		return loginUri;
	}

	protected String noAuthUri() {
		if (noAuthUri == null)
			return NutShiro.DefaultNoAuthURL == null ? NutShiro.DefaultLoginURL : NutShiro.DefaultNoAuthURL;
		return noAuthUri;
	}
}

这个方法是做什么的呢

	@Override
	public void process(ActionContext ac) throws Throwable {
		if (match) {
			try {
				interceptor.assertAuthorized(new NutShiroInterceptor(ac));
			} catch (Exception e) {
				whenException(ac, e);
				return;
			}
		}
		doNext(ac);
	}

NutShiro 这个方法是做什么的 没有执行


@SuppressWarnings("unchecked") public static Set<String>[] scanRolePermissionInPackage(String pkg, boolean publicOnly) { Set<String> roles = new HashSet<String>(); Set<String> permissions = new HashSet<String>(); for (Class<?> klass : Scans.me().scanPackage(pkg)) { Method[] methods = publicOnly ? klass.getMethods() : klass.getDeclaredMethods(); for (Method method : methods) { RequiresRoles rr = method.getAnnotation(RequiresRoles.class); if (rr != null && rr.value().length > 0) { for (String role : rr.value()) { roles.add(role); } } RequiresPermissions pr = method.getAnnotation(RequiresPermissions.class); if (pr != null && pr.value().length > 0) { for (String permission : pr.value()) { permissions.add(permission); } } NutzRequiresPermissions pr2 = method.getAnnotation(NutzRequiresPermissions.class); if (pr2 != null && pr2.value().length > 0) { for (String permission : pr2.value()) { permissions.add(permission); } } } } return new Set[]{roles, permissions}; }

自定义注解 如何确定 有没有权限呢
比如@RequiresPermissions("sys:user:view")
nutzboot 怎么解决呢

package io.nutz.nutzsite.common.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
public @interface NutzShiroAuthUrl {
    String noLogin() default "";

    String noPermission() default "http:503";

    String noRole() default "";

    String noUser() default "";

    String handler() default "";
}

要么替换NutShiroProcessor, 要么在它前面判断

用户访问 shiro 需要有权限的页面

@IocBean
@At("/sys/user")
public class UserController {
	private static final Log log = Logs.get();

	
	@RequiresPermissions("sys:user:view")
	@At("")
	@Ok("th:/sys/user/user.html")
	public void index(HttpServletRequest req) {

	}
}

match ==true是什么原因呢 如何判断 是否shrio 有这个权限呢

	@Override
	public void process(ActionContext ac) throws Throwable {
		if (match) {
			try {
				interceptor.assertAuthorized(new NutShiroInterceptor(ac));
			} catch (Exception e) {
				whenException(ac, e);
				return;
			}
		}
		doNext(ac);
	}

match是有没有注解, 如果没权限,assertAuthorized会抛出异常,whenException处理

异常信息
interceptor.assertAuthorized(new NutShiroInterceptor(ac));
这段代码是做什么呢
这里应该判断 是否登录 再判断 是否有权限
SecurityUtils.getSubject() 如果为空
则跳转登录 非空 判断 跳转503

This subject is anonymous - it does not have any identifying principals and authorization operations require an identity to check against.  A Subject instance will acquire these identifying principals automatically after a successful login is performed be executing org.apache.shiro.subject.Subject.login(AuthenticationToken) or when 'Remember Me' functionality is enabled by the SecurityManager.  This exception can also occur when a previously logged-in Subject has logged out which makes it anonymous again.  Because an identity is currently not known due to any of these conditions, authorization is denied.

已经 下载 nutzmore 准备修复这个BUG

那么 问题 来了 怎么解决呢

会有几个问题的:
shiro的注解有要求登录的, 也有要求未登录的

所以, 还是得在whenException里面,按不同的异常类型(登录和权限不足对应的异常不同)来处理

如何 让shrio自己判断 处理
org.apache.shiro.realm AuthorizingRealm isPermitted
再执行 次方法

	@Override
	public void process(ActionContext ac) throws Throwable {
		if (match) {
			try {
				interceptor.assertAuthorized(new NutShiroInterceptor(ac));
			} catch (Exception e) {
				whenException(ac, e);
				return;
			}
		}
		doNext(ac);
	}

如此 调整 不会一来就跳转 登录 但是 如何跳转到 503呢

	/**
	 * match是有没有注解, 如果没权限,assertAuthorized会抛出异常,whenException处理
	 * @param ac
	 * @throws Throwable
	 */
	@Override
	public void process(ActionContext ac) throws Throwable {
		if (match) {
			try {
				interceptor.assertAuthorized(new NutShiroInterceptor(ac));
			} catch (Exception e) {
				whenException(ac, e);
				if(Lang.isNotEmpty(SecurityUtils.getSubject())){
					//如何跳转503呢
//					View.render(ac.getRequest(), ac.getResponse(), null);
					return;
				}
				return;
			}
		}
		doNext(ac);
	}

	/**
	 * 判断异常
	 * @param ac
	 * @param e
	 * @throws Throwable
	 */
	protected void whenException(ActionContext ac, Exception e) throws Throwable {
		WebUtils.saveRequest(ac.getRequest());
		if (e instanceof UnauthenticatedException) {
			whenUnauthenticated(ac, (UnauthenticatedException) e);
		} else if (e instanceof UnauthorizedException) {
			whenUnauthorized(ac, (UnauthorizedException) e);
		} else {
			whenOtherException(ac, e);
		}
		Object val = ac.getRequest().getAttribute("shiro_auth_error");
		if (val != null && val instanceof View) {
			((View) val).render(ac.getRequest(), ac.getResponse(), null);
			return;
		}
	}

有问题 正常情况 会报错没有权限 现在都不报错了

INFO  c.r.f.s.w.s.OnlineWebSessionManager - [validateSessions,145] - Finished invalidation session. No sessions were stopped.
16:25:22.945 [http-nio-80-exec-27] ERROR c.r.f.w.e.DefaultExceptionHandler - [handleAuthorizationException,30] - Subject does not have permission [system:role:edit]
org.apache.shiro.authz.UnauthorizedException: Subject does not have permission [system:role:edit]
	at org.apache.shiro.authz.ModularRealmAuthorizer.checkPermission(ModularRealmAuthorizer.java:323)
	at org.apache.shiro.mgt.AuthorizingSecurityManager.checkPermission(AuthorizingSecurityManager.java:137)
	at org.apache.shiro.subject.support.DelegatingSubject.checkPermission(DelegatingSubject.java:209)
	at org.apache.shiro.authz.aop.PermissionAnnotationHandler.assertAuthorized(PermissionAnnotationHandler.java:74)
	at org.apache.shiro.authz.aop.AuthorizingAnnotationMethodInterceptor.assertAuthorized(AuthorizingAnnotationMethodInterceptor.java:84)
	at org.apache.shiro.authz.aop.AnnotationsAuthorizingMethodInterceptor.assertAuthorized(AnnotationsAuthorizingMethodInterceptor.java:100)
	at org.apache.shiro.authz.aop.AuthorizingMethodInterceptor.invoke(AuthorizingMethodInterceptor.java:38)
	at org.apache.shiro.spring.security.interceptor.AopAllianceAnnotationsAuthorizingMethodInterceptor.invoke(AopAllianceAnnotationsAuthorizingMethodInterceptor.java:115)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
	at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:93)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
	at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:688)
	at com.ruoyi.project.system.role.controller.RoleController$$EnhancerBySpringCGLIB$$599116e6.editSave(<generated>)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:189)
	at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138)
	at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:102)
	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:895)
	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:800)
	at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
	at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1038)
	at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:942)
	at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1005)
	at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:908)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:660)
	at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:882)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:741)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.apache.shiro.web.servlet.AdviceFilter.executeChain(AdviceFilter.java:108)
	at org.apache.shiro.web.servlet.AdviceFilter.doFilterInternal(AdviceFilter.java:137)
	at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:125)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:112)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:112)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.apache.shiro.web.servlet.ProxiedFilterChain.doFilter(ProxiedFilterChain.java:61)
	at org.apache.shiro.web.servlet.AdviceFilter.executeChain(AdviceFilter.java:108)
	at org.apache.shiro.web.servlet.AdviceFilter.doFilterInternal(AdviceFilter.java:137)
	at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:125)
	at org.apache.shiro.web.servlet.ProxiedFilterChain.doFilter(ProxiedFilterChain.java:66)
	at org.apache.shiro.web.servlet.AdviceFilter.executeChain(AdviceFilter.java:108)
	at org.apache.shiro.web.servlet.AdviceFilter.doFilterInternal(AdviceFilter.java:137)
	at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:125)
	at org.apache.shiro.web.servlet.ProxiedFilterChain.doFilter(ProxiedFilterChain.java:66)
	at org.apache.shiro.web.servlet.AdviceFilter.executeChain(AdviceFilter.java:108)
	at org.apache.shiro.web.servlet.AdviceFilter.doFilterInternal(AdviceFilter.java:137)
	at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:125)
	at org.apache.shiro.web.servlet.ProxiedFilterChain.doFilter(ProxiedFilterChain.java:66)
	at org.apache.shiro.web.servlet.AbstractShiroFilter.executeChain(AbstractShiroFilter.java:449)
	at org.apache.shiro.web.servlet.AbstractShiroFilter$1.call(AbstractShiroFilter.java:365)
	at org.apache.shiro.subject.support.SubjectCallable.doCall(SubjectCallable.java:90)
	at org.apache.shiro.subject.support.SubjectCallable.call(SubjectCallable.java:83)
	at org.apache.shiro.subject.support.DelegatingSubject.execute(DelegatingSubject.java:387)
	at org.apache.shiro.web.servlet.AbstractShiroFilter.doFilterInternal(AbstractShiroFilter.java:362)
	at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:125)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at com.alibaba.druid.support.http.WebStatFilter.doFilter(WebStatFilter.java:124)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at com.ruoyi.common.xss.XssFilter.doFilter(XssFilter.java:66)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:92)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:93)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:200)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:199)
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
	at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:490)
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139)
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
	at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:408)
	at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
	at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:791)
	at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1417)
	at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
	at java.lang.Thread.run(Thread.java:748)
Caused by: org.apache.shiro.authz.AuthorizationException: Not authorized to invoke method: public com.ruoyi.framework.web.domain.AjaxResult com.ruoyi.project.system.role.controller.RoleController.editSave(com.ruoyi.project.system.role.domain.Role)
	at org.apache.shiro.authz.aop.AuthorizingAnnotationMethodInterceptor.assertAuthorized(AuthorizingAnnotationMethodInterceptor.java:90)
	... 101 common frames omitted

代码 应该没问题 但是
异常信息

org.apache.shiro.authz.UnauthorizedException: Subject does not have permission [sys:user:edit]

代码 未执行if (e instanceof UnauthorizedException) {

	protected void whenException(ActionContext ac, Exception e) throws Throwable {
		Object val = ac.getRequest().getAttribute("shiro_auth_error");
		if (val != null && val instanceof View) {
			((View) val).render(ac.getRequest(), ac.getResponse(), null);
			return;
		}
		WebUtils.saveRequest(ac.getRequest());
		if (e instanceof UnauthenticatedException) {
			whenUnauthenticated(ac, (UnauthenticatedException) e);
		} else if (e instanceof UnauthorizedException) {
			whenUnauthorized(ac, (UnauthorizedException) e);
		} else {
			whenOtherException(ac, e);
		}
	}

自己的问题 已经处理
查询 权限 有一个权限为空字符串 “”导致异常

添加回复
请先登陆
回到顶部