zoukankan      html  css  js  c++  java
  • shiro app

    写在前面

    我们知道,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

    https://www.cnblogs.com/ljdblog/p/6237683.html

  • 相关阅读:
    Django知识总结(一)
    Django知识总结(二)
    Django知识总结(三)
    机器学习领域主要术语的英文表达
    Python的进程与线程--思维导图
    MySQL数据库--思维导图
    5.18 每日小三练
    5.14 每日小三练
    5.12 每日小三练
    5.9 每日小三练
  • 原文地址:https://www.cnblogs.com/But-you/p/10688076.html
Copyright © 2011-2022 走看看