前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >细说shiro之自定义filter

细说shiro之自定义filter

作者头像
编程随笔
发布2019-09-11 16:06:51
2.8K0
发布2019-09-11 16:06:51
举报
文章被收录于专栏:后端开发随笔

写在前面

我们知道,shiro框架在Java Web应用中使用时,本质上是通过filter方式集成的。 也就是说,它是遵循过滤器链规则的:filter的执行顺序与在web.xml中定义的顺序一致,如下所示:

代码语言:javascript
复制
<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实现

代码语言:javascript
复制
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

代码语言:javascript
复制
<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

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2017-11-16 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 写在前面
  • 项目实践
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档