前言
Shiro使用了与Servlet一样的Filter接口进行扩展,还有拦截器是基于java的反射机制,如利用动态代理实现,而平时说的过滤器是基于回调函数的实现,在实现原理上有着本质的区别
拦截器介绍
NameableFilter
顾名思义,就是根据相应拦截器链组装拦截器的名字找到相应的拦截器实例
OncePerRequestFilter
该拦截器用于控制一次请求只能走一次拦截器链,默认是开启拦截的
ShiroFilter
是整个shiro的入口点,用于拦截需要安全控制的请求进行处理
AdviceFilter
该拦截器非常类似于struct中拦截器,同时支持AOP拦截
boolean preHandle(ServletRequest request, ServletResponse response) throws Exception
void postHandle(ServletRequest request, ServletResponse response) throws Exception
void afterCompletion(ServletRequest request, ServletResponse response, Exception exception) throws Exception;
preHandler:类似于AOP中的前置增强;在拦截器链执行之前执行;如果返回true则继续拦截器链;否则中断后续的拦截器链的执行直接返回;进行预处理(如基于表单的身份验证、授权)
postHandle:类似于AOP中的后置返回增强;在拦截器链执行完成后执行;进行后处理(如记录执行时间之类的);
afterCompletion:类似于AOP中的后置最终增强;即不管有没有异常都会执行;可以进行清理资源(如解除Subject与线程的绑定之类的);
PathMatchingFilter
提供了基于Ant风格的请求路径匹配功能及拦截器参数解析的功能,如“roles[admin,user]”自动根据“,”分割解析到一个路径参数配置并绑定到相应的路径:
boolean pathsMatch(String path, ServletRequest request)
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
提供了访问控制的基础功能
abstract boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception; boolean onAccessDenied(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception; abstract boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception;
isAccessAllowed:表示是否允许访问;mappedValue就是[urls]配置中拦截器参数部分,如果允许访问返回true,否则false;
onAccessDenied:表示当访问拒绝时是否已经处理了;如果返回true表示需要继续处理;如果返回false表示该拦截器实例已经处理了,将直接返回即可。
同时它还有一些扩展的功能
void setLoginUrl(String loginUrl) //身份验证时使用,默认/login.jsp
String getLoginUrl()
Subject getSubject(ServletRequest request, ServletResponse response) //获取Subject实例
boolean isLoginRequest(ServletRequest request, ServletResponse response)//当前请求是否是登录请求
void saveRequestAndRedirectToLogin(ServletRequest request, ServletResponse response) throws IOException //将当前请求保存起来并重定向到登录页面
void saveRequest(ServletRequest request) //将请求保存起来,如登录成功后再重定向回该请求
void redirectToLogin(ServletRequest request, ServletResponse response) //重定向到登录页面
拦截器链
在web容器中,先执行shiro的filter链,再执行servlet容器的filter链,同时shiro的ProxiedFilterChain对Servlet容器的FilterChain进行了代理
FilterChain getChain(ServletRequest request, ServletResponse response, FilterChain originalChain);
自定义拦截器
通过自定义拦截器可以扩展一些功能,如动态url-角色/权限访问控制,根据Subject身份信息获取用户信息绑定到Request(即设置通用数据)、验证码验证、在线用户信息的保存等等
扩展OncePerRequestFilter
OncePerRequestFilter保证一次请求只调用一次doFilterInternal
对应的ini配置文件中
[filters]
myFilter1=com.shiro.web.MyOncePerRequestFilter
[urls]
/**=myFilter1
其中[filters]声明拦截器,[urls]执行拦截器
扩展AdviceFilter
preHandle:进行请求的预处理,然后根据返回值决定是否继续处理(true:继续过滤器链);可以通过它实现权限控制;
postHandle:执行完拦截器链之后正常返回后执行;
afterCompletion:不管最后有没有异常,afterCompletion都会执行,完成如清理资源功能。
扩展PathMatchingFilter
提供了url模式过滤的功能
preHandle:会进行url模式与请求url进行匹配,如果匹配会调用onPreHandle;如果没有配置url模式/没有url模式匹配,默认直接返回true;
onPreHandle:如果url模式与请求url匹配,那么会执行onPreHandle,并把该拦截器配置的参数传入。默认什么不处理直接返回true。
扩展AccessControlFilter
isAccessAllowed:即是否允许访问,返回true表示允许;
onAccessDenied:表示访问拒绝时是否自己处理,如果返回true表示自己不处理且继续拦截器链执行,返回false表示自己已经处理了(比如重定向到另一个页面)
其中如果isAccessAllowed返回true,onAccessDenied将不执行,反之执行
默认拦截器
Shiro内置了很多默认的拦截器,比如身份验证、授权等相关的