问题背景
1.使用
Shiro
对用户访问资源进行权限校验(授权)。
2.目的:当用户访问没有权限资源时,跳转到指定页面。
3.setUnauthorizedUrl(”/view/permission”)方法作用:当用户没有权限访问时跳转到”/view/permission”页面。
4.但是setUnauthorizedUrl配置没有生效。
@Bean //此对象中要配置一些访问规则(匿名访问的资源,认证的访问的资源)
public ShiroFilterFactoryBean shiroFilterFactory(SecurityManager securityManager) {
ShiroFilterFactoryBean factoryBean = new ShiroFilterFactoryBean();
factoryBean.setSecurityManager(securityManager);
factoryBean.setLoginUrl("/view/login");
factoryBean.setSuccessUrl("/view/index");
factoryBean.setUnauthorizedUrl("/view/permission");
Map<String, String> filterMap = new LinkedHashMap<>();
filterMap.put("/bootstrap/**", "anon");
filterMap.put("/view/index", "anon");
filterMap.put("/login/**", "anon");
filterMap.put("/**", "authc");
factoryBean.setFilterChainDefinitionMap(filterMap);
return factoryBean;
}
分析
1.
Shiro
有两个模块
认证
和
授权
,每个模块都有
独立
的过滤器和异常处理方式。
认证
过滤器:anon、authc、user、authcBasic
授权
过滤器:perms、roles、ssl、rest、port
2.我们的过滤器只配置了”anon”和”authc”,这两个都属于
认证
过滤器。
Map<String, String> filterMap = new LinkedHashMap<>();
filterMap.put("/bootstrap/**", "anon");
filterMap.put("/view/index", "anon");
filterMap.put("/login/**", "anon");
filterMap.put("/**", "authc");
3.看源码第3行(filter instanceof AuthorizationFilter),只有属于
授权
的过滤器才能触发setUnauthorizedUrl()配置。
private void applyUnauthorizedUrlIfNecessary(Filter filter) {
String unauthorizedUrl = getUnauthorizedUrl();
if (StringUtils.hasText(unauthorizedUrl) && (filter instanceof AuthorizationFilter)) {
AuthorizationFilter authzFilter = (AuthorizationFilter) filter;
//only apply the unauthorizedUrl if they haven't explicitly configured one already:
String existingUnauthorizedUrl = authzFilter.getUnauthorizedUrl();
if (existingUnauthorizedUrl == null) {
authzFilter.setUnauthorizedUrl(unauthorizedUrl);
}
}
}
4.所以我们这条代码白写
factoryBean.setUnauthorizedUrl("/view/permission");
解决
方法一
自定义异常处理类,不使用shiro进行页面跳转(推荐)
@ControllerAdvice
public class MyControllerAdvice {
@ExceptionHandler(UnauthorizedException.class)
public ModelAndView permission(){
//这个路径填写需要去掉mvc配置的路径
return new ModelAndView("/permission");
}
}
方法二
添加授权拦截器(没用过几次,也不太好用)
filterMap.put("/**", "perms[user:add]");
方法三
直接在mvc配置的路径下创建一个error.html页面(名字必须是error)不用任何配置,发生异常时会自动跳转到error页面(所有异常都跳转到这个页面,太宽泛也不太好用)