写在前面

我们知道,shiro框架在Java Web应用中使用时,本质上是通过filter方式集成的。

也就是说,它是遵循过滤器链规则的:filter的执行顺序与在web.xml中定义的顺序一致,如下所示:

<filter>
<filter-name>securityFilter</filter-name>
<filter-class>com.lenovo.iot.devicemanager.filter.SecurityFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>securityFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping> <!-- The filter-name matches name of a 'shiroFilter' bean inside applicationContext.xml -->
<filter>
<filter-name>shiroFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
<init-param>
<param-name>targetFilterLifecycle</param-name>
<param-value>true</param-value>
</init-param>
</filter> <!-- Make sure any request you want accessible to Shiro is filtered. /* catches all -->
<!-- requests. Usually this filter mapping is defined first (before all others) to -->
<!-- ensure that Shiro works in subsequent filters in the filter chain: -->
<filter-mapping>
<filter-name>shiroFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

显然,securityFilter定义在shiroFilter之前,那么securityFilter也是在shiroFilter之前被访问到。

根据这个原理,我们可以根据实际情况对shiro的filter进行扩展。

举个例子,shiro默认的org.apache.shiro.web.filter.authc.UserFilter会对请求进行过滤,在未登录时请求会被重定向到登录页面。

但是在API项目中,响应都是json格式,并不存在登录页面,此时就会返回404错误。

项目实践

在最新的项目中,前后端完全分离,通过API方式进行数据交换,并且在服务端集成了shiro进行权限控制,后端项目架构为:SpringMVC + Shiro。

为了在拦截那些未执行登录的请求时返回json格式的响应,对org.apache.shiro.web.filter.authc.UserFilter进行了扩展。

具体来说需要做2件事情:

1.扩展org.apache.shiro.web.filter.authc.UserFilter实现

public class ShiroUserFilter extends UserFilter {
private static final Logger logger = LoggerFactory.getLogger(ShiroUserFilter.class); @Override
protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
if(logger.isErrorEnabled()) {
logger.error("account need login for: {}", ((HttpServletRequest)request).getServletPath());
} // 请求被拦截后直接返回json格式的响应数据
response.getWriter().write(JsonResp.getJsonRespError(JsonResp.SC_NOT_LOGINED, "account not logined").toString());
response.getWriter().flush();
response.getWriter().close();
return false;
}
}

2.在spring中定义并使用自定义扩展的filter

<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<property name="securityManager" ref="securityManager"/>
<property name="filters">
<util:map>
<entry key="shiroUserFilter" value-ref="shiroUserFilter" />
</util:map>
</property>
<property name="filterChainDefinitions">
<value>
# some example chain definitions:
# /admin/** = authc, roles[admin]
# /docs/** = authc, perms[document:read]
/**/login.do = anon
/** = shiroUserFilter
# more URL-to-FilterChain definitions here
</value>
</property>
</bean> <!-- 定义扩展的filter实例 -->
<bean id="shiroUserFilter" class="com.lenovo.iot.devicemanager.filter.ShiroUserFilter" />

【参考】

https://shiro.apache.org/web.html#Web-FilterChainDefinitions

细说shiro之自定义filter的更多相关文章

  1. 解决Shiro+SpringBoot自定义Filter不生效问题

    在SpringBoot+Shiro实现安全框架的时候,自定义扩展了一些Filter,并注册到ShiroFilter,但是运行的时候发现总是在ShiroFilter之前就进入了自定义Filter,结果当 ...

  2. Shiro权限管理框架(五):自定义Filter实现及其问题排查记录

    明确需求 在使用Shiro的时候,鉴权失败一般都是返回一个错误页或者登录页给前端,特别是后台系统,这种模式用的特别多.但是现在的项目越来越多的趋向于使用前后端分离的方式开发,这时候就需要响应Json数 ...

  3. 解决shiro自定义filter后,ajax登录无法登录,并且无法显示静态资源的问题

    这个问题困扰了我一天,看了下面两个文章,豁然开朗: https://www.cnblogs.com/gj1990/p/8057348.html https://412887952-qq-com.ite ...

  4. 细说shiro之四:在web应用中使用shiro

    官网:https://shiro.apache.org/ 1. 下载在Maven项目中的依赖配置如下: <!-- shiro配置 --> <dependency> <gr ...

  5. Asp.net mvc自定义Filter简单使用

    自定义Filter的基本思路是继承基类ActionFilterAttribute,并根据实际需要重写OnActionExecuting,OnActionExecuted,OnResultExecuti ...

  6. Jinja2模版语言自定义filter的使用

    Jinja2模版语言,自带有一些filter,能够在前端的模版中控制数据按照相应的方式显示.比如以下两种filter,分别能在前端控制数字的近似精度显示和根据字符串长度补齐: round(value, ...

  7. HBase笔记--自定义filter

    自定义filter需要继承的类:FilterBase 类里面的方法调用顺序   方法名 作用 1 boolean filterRowKey(Cell cell) 根据row key过滤row.如果需要 ...

  8. Spring MVC 项目搭建 -6- spring security 使用自定义Filter实现验证扩展资源验证,使用数据库进行配置

    Spring MVC 项目搭建 -6- spring security使用自定义Filter实现验证扩展url验证,使用数据库进行配置 实现的主要流程 1.创建一个Filter 继承 Abstract ...

  9. Spring-Security 自定义Filter完成验证码校验

    Spring-Security的功能主要是由一堆Filter构成过滤器链来实现,每个Filter都会完成自己的一部分工作.我今天要做的是对UsernamePasswordAuthenticationF ...

随机推荐

  1. BZOJ 3514: Codechef MARCH14 GERALD07加强版(LCT + 主席树)

    题意 \(N\) 个点 \(M\) 条边的无向图,询问保留图中编号在 \([l,r]\) 的边的时候图中的联通块个数. \(K\) 次询问强制在线. \(1\le N,M,K \le 200,000\ ...

  2. 「NOI2016」优秀的拆分 解题报告

    「NOI2016」优秀的拆分 这不是个SAM题,只是个LCP题目 95分的Hash很简单,枚举每个点为开头和末尾的AA串个数,然后乘一下之类的. 考虑怎么快速求"每个点为开头和末尾的AA串个 ...

  3. failover swarm 故障转移

    #故障转移 Failover #当其中一个节点关闭宕机时,其节点中的service会转移到另一个节点上.Swarm会检测到node1发生故障并把此故障节点的状态标记为Down; docker node ...

  4. java ee Concurrency 并发编程

    https://www.javacodegeeks.com/2014/07/java-ee-concurrency-api-tutorial.html This is a sample chapter ...

  5. 如何查看本地电脑ip

    1.快捷键 win+R打开命令窗口 输入 ipconfig查看你电脑的ip 2.输入netstat -an ,查看当前所有连接端口,显示所有的有效连接信息列表,包括已建立的连接(ESTABLISHED ...

  6. Hadoop安装错误总结

    Master的NodeManager/DateNode未启动 日志中未出现任何错误 正常现象,如需在Master中启动可在slave文件中 slaves localhost slave01 slave ...

  7. 解题:NOI2018 你的名字(68pts暴力)

    题面 rt,如果省选没退役就补 SAM的优势:简单明了 先建S的SAM并标记所有节点,之后每次询问直接把T按广义SAM的方法插上去,统计新加的节点到根的状态代表的本质不同子串数,减掉被标记的部分就是T ...

  8. C语言进阶--Day2

    今天主要讲解的是函数的压栈与出栈 1. 要实现一个数组的逆置,用栈的压栈出栈观点: reverseArr(int *parr,int i,int len) { if(i != len-1) rever ...

  9. 爬虫之requests请求库高级应用

    1.SSL Cert Verification #证书验证(大部分网站都是https) import requests respone=requests.get('https://www.12306. ...

  10. shell脚本[] [[]] -n -z 的含义解析

    1.在中括号中,判断变量的值, 加不加双引号的问题?-z 判断 变量的值,是否为空: zero = 0 - 变量的值,为空,返回0,为true- 变量的值,非空,返回1,为false-n 判断变量的值 ...