先从我们写的一个自定义Filter来看:

public class RoleOrFilter extends AuthorizationFilter {@Overrideprotected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception {Subject subject = getSubject(request,response);String[] roles = (String[])mappedValue;if(roles == null || roles.length ==0){return true;}for(String role:roles){if(subject.hasRole(role)){return true;}}return false;}
}
复制代码

我们写的自定义RoleOrFilter表示有多个角色要求时,只需要满足一个即可通过。 我们顺着RoleOrFilter的实现,了解他的父类

NameableFilter
NameableFilter给Filter起个名字,如果没有设置默认就是FilterName;还记得之前的如authc吗?当我们组装拦截器链时会根据这个名字找到相应的拦截器实例;

OncePerRequestFilter
OncePerRequestFilter用于防止多次执行Filter的;也就是说一次请求只会走一次拦截器链;另外提供enabled属性,表示是否开启该拦截器实例,默认enabled=true表示开启,如果不想让某个拦截器工作,可以设置为false即可。

AdviceFilter
AdviceFilter提供了AOP风格的支持,类似于SpringMVC中的Interceptor

1.  boolean preHandle(ServletRequest request, ServletResponse response) throws Exception
2.  void postHandle(ServletRequest request, ServletResponse response) throws Exception
3.  void afterCompletion(ServletRequest request, ServletResponse response, Exception exception) throws Exception;
复制代码

preHandler:类似于AOP中的前置增强;在拦截器链执行之前执行;如果返回true则继续拦截器链;否则中断后续的拦截器链的执行直接返回;进行预处理(如基于表单的身份验证、授权) postHandle:类似于AOP中的后置返回增强;在拦截器链执行完成后执行;进行后处理(如记录执行时间之类的); afterCompletion:类似于AOP中的后置最终增强;即不管有没有异常都会执行;可以进行清理资源(如接触Subject与线程的绑定之类的);

PathMatchingFilter

PathMatchingFilter提供了基于Ant风格的请求路径匹配功能及拦截器参数解析的功能,如“roles[admin,user]”自动根据“,”分割解析到一个路径参数配置并绑定到相应的路径:

1.  boolean pathsMatch(String path, ServletRequest request)
2.  boolean onPreHandle(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception
复制代码

pathsMatch:该方法用于path与请求路径进行匹配的方法;如果匹配返回true
onPreHandle:在preHandle中,当pathsMatch匹配一个路径后,会调用opPreHandler方法并将路径绑定参数配置传给mappedValue;然后可以在这个方法中进行一些验证(如角色授权),如果验证失败可以返回false中断流程;默认返回true;也就是说子类可以只实现onPreHandle即可,无须实现preHandle。如果没有path与请求路径匹配,默认是通过的(即preHandle返回true)。

AccessControlFilter

AccessControlFilter提供了访问控制的基础功能;比如是否允许访问/当访问拒绝时如何处理等:

1.  abstract boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception;
2.  boolean onAccessDenied(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception;
3.  abstract boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception;
复制代码

isAccessAllowed:表示是否允许访问;mappedValue就是[urls]配置中拦截器参数部分,如果允许访问返回true,否则false;
onAccessDenied:表示当访问拒绝时是否已经处理了;如果返回true表示需要继续处理;如果返回false表示该拦截器实例已经处理了,将直接返回即可。

onPreHandle会自动调用这两个方法决定是否继续处理:

boolean onPreHandle(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception {  return isAccessAllowed(request, response, mappedValue) || onAccessDenied(request, response, mappedValue);
}
复制代码

另外AccessControlFilter还提供了如下方法用于处理如登录成功后/重定向到上一个请求:

1.  void setLoginUrl(String loginUrl) //身份验证时使用,默认/login.jsp
2.  String getLoginUrl()
3.  Subject getSubject(ServletRequest request, ServletResponse response) //获取Subject实例
4.  boolean isLoginRequest(ServletRequest request, ServletResponse response)//当前请求是否是登录请求
5.  void saveRequestAndRedirectToLogin(ServletRequest request, ServletResponse response) throws IOException //将当前请求保存起来并重定向到登录页面
6.  void saveRequest(ServletRequest request) //将请求保存起来,如登录成功后再重定向回该请求
7.  void redirectToLogin(ServletRequest request, ServletResponse response) //重定向到登录页面
复制代码

比如基于表单的身份验证就需要使用这些功能。 到此基本的拦截器就完事了,如果我们想进行访问访问的控制就可以继承AccessControlFilter;如果我们要添加一些通用数据我们可以直接继承PathMatchingFilter。

AuthorizationFilter
AuthorizationFilter实现了AccessControlFilter的onAccessDenied方法

//访问拒绝才会进来此方法
protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws IOException {Subject subject = getSubject(request, response);if (subject.getPrincipal() == null) {// 如果未登录,保存当前页面,重定向到登录页面saveRequestAndRedirectToLogin(request, response);} else {//匿名访问地址String unauthorizedUrl = getUnauthorizedUrl();if (StringUtils.hasText(unauthorizedUrl)) {//如果匿名访问地址存在,则跳转去匿名访问地址WebUtils.issueRedirect(request, response, unauthorizedUrl);} else {//不存在则返回404WebUtils.toHttp(response).sendError(HttpServletResponse.SC_UNAUTHORIZED);}}return false;}
复制代码

ShiroFilterFactoryBean
当我们写好了自定义Filter后,如何在Shiro中使用它呢?在config类中注入ShiroFilter的bean

     /*** ShiroFilter主要配置* @param securityManager* @return*/@Beanpublic ShiroFilterFactoryBean shiroFilter (SecurityManager securityManager){ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();shiroFilterFactoryBean.setSecurityManager(securityManager);//自定义拦截器Map<String, Filter> filtersMap = new LinkedHashMap<String, Filter>();filtersMap.put("roleOrFilter", roleOrFilter());shiroFilterFactoryBean.setFilters(filtersMap);Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>();//注意过滤器配置顺序 不能颠倒//配置退出 过滤器,其中的具体的退出代码Shiro已经替我们实现了,登出后跳转配置的loginUrlfilterChainDefinitionMap.put("/logout", "logout");// 配置不会被拦截的链接 顺序判断//filterChainDefinitionMap.put("/hello", "anon");filterChainDefinitionMap.put("/ajaxLogin", "anon");filterChainDefinitionMap.put("/testRole", "anon");filterChainDefinitionMap.put("/**", "roleOrFilter[admin,admin1]");//自动跳去登录的地址shiroFilterFactoryBean.setLoginUrl("/login");//上面提到的匿名地址//shiroFilterFactoryBean.setUnauthorizedUrl();shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);return shiroFilterFactoryBean;}
复制代码

这样我们在访问对应的请求时,就会先调用shiro的filter。

默认拦截器名 拦截器类 说明(括号里的表示默认值)
身份验证相关的
authc org.apache.shiro.web.filter.authc.FormAuthenticationFilter 基于表单的拦截器;如“/**=authc”,如果没有登录会跳到相应的登录页面登录;主要属性:usernameParam:表单提交的用户名参数名( username); passwordParam:表单提交的密码参数名(password); rememberMeParam:表单提交的密码参数名(rememberMe); loginUrl:登录页面地址(/login.jsp);successUrl:登录成功后的默认重定向地址; failureKeyAttribute:登录失败后错误信息存储key(shiroLoginFailure);
authcBasic org.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter Basic HTTP身份验证拦截器,主要属性: applicationName:弹出登录框显示的信息(application);
logout org.apache.shiro.web.filter.authc.LogoutFilter 退出拦截器,主要属性:redirectUrl:退出成功后重定向的地址(/)
user org.apache.shiro.web.filter.authc.UserFilter 用户拦截器,用户已经身份验证/记住我登录的都可;
anon org.apache.shiro.web.filter.authc.AnonymousFilter 匿名拦截器,即不需要登录即可访问;一般用于静态资源过滤;示例“/static/**=anon”
授权相关的
roles org.apache.shiro.web.filter.authz.RolesAuthorizationFilter 角色授权拦截器,验证用户是否拥有所有角色;主要属性: loginUrl:登录页面地址(/login.jsp);unauthorizedUrl:未授权后重定向的地址;示例“/admin/**=roles[admin]”
perms org.apache.shiro.web.filter.authz.PermissionsAuthorizationFilter 权限授权拦截器,验证用户是否拥有所有权限;属性和roles一样;示例“/user/**=perms["user:create"]”
port org.apache.shiro.web.filter.authz.PortFilter 端口拦截器,主要属性:port(80):可以通过的端口;示例“/test= port[80]”,如果用户访问该页面是非80,将自动将请求端口改为80并重定向到该80端口,其他路径/参数等都一样
rest org.apache.shiro.web.filter.authz.HttpMethodPermissionFilter rest风格拦截器,自动根据请求方法构建权限字符串(GET=read, POST=create,PUT=update,DELETE=delete,HEAD=read,TRACE=read,OPTIONS=read, MKCOL=create)构建权限字符串;示例“/users=rest[user]”,会自动拼出“user:read,user:create,user:update,user:delete”权限字符串进行权限匹配(所有都得匹配,isPermittedAll);
ssl org.apache.shiro.web.filter.authz.SslFilter SSL拦截器,只有请求协议是https才能通过;否则自动跳转会https端口(443);其他和port拦截器一样;

####自定义filter异常 此外,我在查找资料的时候,看到一个问题Shiro 自定义 filter 匹配异常,问题主要说在使用自定义filter定义的时候,使用@Bean模式注入自定义filter之后,会导致自定义filter的调用在shiroFilter的前面,具体解决方案可以点开原文看。 我在我本地测试后发现没有问题,可能是新版本已经修复了这个bug。当前版本1.3.2

SpringBoot+Shiro学习(七):Filter过滤器管理相关推荐

  1. Shiro笔记五:Shiro内置Filter过滤器

    Shiro笔记五:Shiro内置Filter过滤器 shiro内置的过滤器 核心过滤器类:DefaultFilter,配置哪个路径对应哪个拦截器进行处理. authc:org.apache.shiro ...

  2. SpringBoot+Shiro学习(一):主要模块介绍

    这篇文章是我最近对SpringBoot+Shiro+mybatis+redis一个练手项目的记录. 我是按照慕课网的一篇课程+百度进行练手的 慕课课程 练手项目Github地址 跟着开涛学Shiro ...

  3. SpringBoot+Shiro学习(八):RememberMe

    这一章比较简单,就不多说了,上代码: /** * cookie对象; * rememberMeCookie()方法是设置Cookie的生成模版,比如cookie的name,cookie的有效时间等等. ...

  4. 【SpringBoot】之自定义 Filter 过滤器

    目录 一.Filter 介绍 二.Filter 的拦截过程 三.自定义 Filter 一.Filter 介绍 Filter 过滤器主要用来过滤用户的请求,允许用户对请求进行前置处理和后置处理,比如实现 ...

  5. SpringBoot+Shiro学习(四):Realm授权

    上一节我们讲了自定义Realm中的认证(doGetAuthenticationInfo),这节我们继续讲另一个方法doGetAuthorizationInfo授权 授权流程 流程如下: 首先调用Sub ...

  6. shiro 学习(一)

    title: shiro学习(一) date: 2020-11-13 tags: spring springboot shiro categories: spring springboot shiro ...

  7. shiro学习系列:shiro自定义filter过滤器

    shiro学习系列:shiro自定义filter过滤器 自定义JwtFilter的hierarchy(层次体系) 上代码 package com.finn.springboot.common.conf ...

  8. 全程配图超清晰的Springboot权限控制后台管理项目实战第二期(Springboot+shiro+mybatis+redis)

    全程配图超清晰的Springboot权限控制后台管理项目实战第二期(Springboot+shiro+mybatis+redis) 众所周知,作为一个后端新手学习者,通过项目来学习,增长项目经验,是一 ...

  9. SpringBoot中AOP实现落地——Filter(过滤器)、Intercepter(拦截器)、Aspect(Spring AOP)

    文章目录 一.一切要从Servlet说起 1.1什么是Servlet 1.2为什么需要Servlet 1.3Servlet如何响应用户请求 1.4Servlet与Tomcat处理请求的流程 1.5Se ...

  10. 一篇搞定 SpringBoot+Mybatis+Shiro 实现多角色权限管理

    初衷:我在网上想找整合springboot+mybatis+shiro并且多角色认证的博客,发现找了好久也没有找到想到的,现在自己会了,就打算写个博客分享出去,希望能帮到你. 原创不易,请点赞支持! ...

最新文章

  1. 阿里某程序员:我级别P7,工资待遇不比协和主治医师差
  2. 简单几段python代码_如何用python跑一段鸿蒙最简单代码?
  3. Spring框架中的设计模式(五)
  4. 能直接挂在iis的动静态网站_网站优化思路总结之前端
  5. svn导出java项目_【SVN】导出项目后报错汇总
  6. 云计算管理工具:根植热土
  7. autocad完全应用指南_如何提高CAD画图的速度?有哪些途径和技法?【AutoCAD教程】...
  8. Spring的IoC解析
  9. 学习Python大数据之后,将来主要能做什么?
  10. 32 道常见的 Kafka 面试题
  11. 传统形态抗锯齿 2.0
  12. 汇佳学校|李昕桐:“世界顶尖设计院校自由”?18岁,我实现了!
  13. vue:无法加载文件..
  14. 笔记本加装固态和内存条教程(超详细)
  15. 想成为挣钱的游戏程序员要经历多少阶段?
  16. 我的python世界 豆瓣_python系列之(4)豆瓣图书《平凡的世界》书评及情感分析...
  17. World Locking Tools for Unity (五)安装部分
  18. 十年HRD总结3个逆向思维的招聘方法
  19. 基于SuperMap Idesktop 进行白膜拉伸的方式
  20. 从实现原理谈谈低代码

热门文章

  1. 机器学习入门——K近邻算法
  2. Netty in action—codec框架
  3. 放之四海皆适用的设计原则(一)
  4. 写给《我也能做CTO》作者的一封信
  5. 理解x86架构的捷径
  6. 在ASP.NET中加密页面机制
  7. 更新小红伞antivirus失败:生成更新结构失败。更新库生成错误 556
  8. 【医疗影像处理】Erosion and Dilation of medical images masks using scipy.ndimage in python
  9. postgresql 集合类型_PostgreSQL数据类型-时间数据类型
  10. sm4 前后端 加密_7 个开源的 Spring Boot 前后端分离优质项目