鍍金池/ 問答/Java  Linux/ shiro自定義過濾器對(duì)restful風(fēng)格實(shí)現(xiàn)攔截的問題

shiro自定義過濾器對(duì)restful風(fēng)格實(shí)現(xiàn)攔截的問題

前提

現(xiàn)在做一個(gè)前后端分離的應(yīng)用,后臺(tái)用shiro做權(quán)限控制,用jwt代替session的無狀態(tài)web應(yīng)用,自定義了一個(gè)shiro filter.url用restful風(fēng)格.所有的接口url都以/api開頭,我想讓所有這種/api開頭的url,如果需要認(rèn)證就走我自定義的filter.

問題

現(xiàn)在我有四個(gè)rul:

  1. /api/user/1 --GET
  2. /api/user --POST
  3. /api/user --PATCH
  4. /api/user --PUT

我現(xiàn)在僅僅想對(duì)POST方法做權(quán)限控制,讓他走我自定義的那個(gè)filter,shiro不知道如何控制.

我的自定義filter在shiro.xml中的配置如下:

<bean id="JWTFilter" class="com.test.web.shiro.stateless.JWTStatelessFilter"/>

<!-- Shiro的Web過濾器 -->
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
    <property name="securityManager" ref="securityManager"/>
    <property name="filters">
        <util:map>
            <entry key="jwt" value-ref="JWTFilter"/>
        </util:map>
    </property>
    <property name="filterChainDefinitions">
        <value>
            /api/**=jwt
            /**=anon
        </value>
    </property>
</bean>

我剛開始想過不配置/api/**=jwt,然后在方法上加@RequiresAuthentication注解,但是這樣子,那個(gè)方法不走我的JWTFilter,如何讓這個(gè)需要認(rèn)證的url走我的自定義filter,該如何配置,求解.謝謝.

回答
編輯回答
喜歡你

可以看看這個(gè)https://github.com/Smith-Crui...

2017年3月17日 03:33
編輯回答
安若晴

我也遇到這個(gè)問題了,我是想著對(duì)外的api接口都要提供賬號(hào)、密碼來驗(yàn)證,這個(gè)怎么做?是在自定義的JWTFilter中,驗(yàn)證賬號(hào)密碼是否正確,是么?方便簡單給兩行代碼看下么?
追問:自定義的JWTFilter你繼承的是shiro的哪個(gè)filter??

2018年8月4日 09:42
編輯回答
情皺

按照tomsun28/bootshiro這里的提示,閱讀了他的文章:基于shiro的改造集成真正支持restful請(qǐng)求

  1. 重寫了PathMatchingFilterChainResolvergetChain方法:
public class RestPathMatchingFilterChainResolver extends PathMatchingFilterChainResolver {

    private static final Logger log = LoggerFactory.getLogger(RestPathMatchingFilterChainResolver.class);

    public RestPathMatchingFilterChainResolver() {
        super();
    }

    public RestPathMatchingFilterChainResolver(FilterConfig filterConfig) {
        super(filterConfig);
    }

    @Override
    public FilterChain getChain(ServletRequest request, ServletResponse response, FilterChain originalChain) {
        FilterChainManager filterChainManager = getFilterChainManager();
        if (!filterChainManager.hasChains()) {
            return null;
        }

        String requestURI = getPathWithinApplication(request);
        String[] urls = null;
        for (String pathPattern : filterChainManager.getChainNames()) {
            urls = pathPattern.split("--");
            if (urls.length == 2) {
                // 分割出url+httpMethod,判斷httpMethod和request請(qǐng)求的method是否一致,不一致直接false
                if (WebUtils.toHttp(request).getMethod().toUpperCase().equals(urls[1].toUpperCase())) {
                    pathPattern = urls[0];
                }
            }
            if (pathMatches(pathPattern, requestURI)) {
                if (log.isTraceEnabled()) {
                    log.trace("Matched path pattern [" + pathPattern + "] for requestURI [" + requestURI + "].  " +
                            "Utilizing corresponding filter chain...");
                }
                if (urls.length == 2) {
                    pathPattern = pathPattern.concat("--").concat(WebUtils.toHttp(request).getMethod().toUpperCase());
                }
                return filterChainManager.proxy(originalChain, pathPattern);
            }
        }
        return null;
    }

}
  1. 重寫了ShiroFilterFactoryBeancreateInstance方法:
public class RestShiroFilterFactoryBean extends ShiroFilterFactoryBean {

    private static final Logger logger = LoggerFactory.getLogger(RestShiroFilterFactoryBean.class);

    public RestShiroFilterFactoryBean() {
        super();
    }

    @Override
    protected AbstractShiroFilter createInstance() throws Exception {
        logger.debug("Creating Shiro Filter instance.");
        SecurityManager securityManager = this.getSecurityManager();
        String msg;
        if (securityManager == null) {
            msg = "SecurityManager property must be set.";
            throw new BeanInitializationException(msg);
        } else if (!(securityManager instanceof WebSecurityManager)) {
            msg = "The security manager does not implement the WebSecurityManager interface.";
            throw new BeanInitializationException(msg);
        } else {
            FilterChainManager manager = this.createFilterChainManager();
            RestPathMatchingFilterChainResolver chainResolver = new RestPathMatchingFilterChainResolver();
            chainResolver.setFilterChainManager(manager);
            return new RestShiroFilterFactoryBean.SpringShiroFilter((WebSecurityManager)securityManager, chainResolver);
        }
    }

    private static final class SpringShiroFilter extends AbstractShiroFilter {

        protected SpringShiroFilter(WebSecurityManager webSecurityManager, FilterChainResolver resolver) {
            super();
            if (webSecurityManager == null) {
                throw new IllegalArgumentException("WebSecurityManager property cannot be null.");
            }
            setSecurityManager(webSecurityManager);
            if (resolver != null) {
                setFilterChainResolver(resolver);
            }
        }
    }

}

然后更改shiro配置文件使用自定義的RestShiroFilterFactoryBean:

    <bean id="shiroFilter" class="com.web.shiro.stateless.config.RestShiroFilterFactoryBean">
        <property name="securityManager" ref="securityManager"/>
        <property name="filters">
            <util:map>
                <entry key="jwt" value-ref="JWTFilter"/>
            </util:map>
        </property>
        <property name="filterChainDefinitions">
            <value>
                /api/user/test--POST=anon
                /api/**=jwt
                /**=anon
            </value>
        </property>
    </bean>

在這里由于我是寫在配置文件中的,所以==的格式不行,換成了--的格式.測試了兩個(gè)方法,/api/user/test分別有getpost請(qǐng)求,然后post添加不用認(rèn)證,如上xml配置文件所示,測試通過,暫時(shí)只用到認(rèn)證,以上可以解決認(rèn)證的問題.
基于shiro的改造集成真正支持restful請(qǐng)求還重寫了RestPathMatchingFilterpathsMatch方法,在他的文章中這個(gè)類主要是給BJwtFilter繼承做授權(quán)使用,我現(xiàn)在暫時(shí)只用到認(rèn)證,所以還沒有深入了解.
以上已經(jīng)能夠解決同一個(gè)url不同的httpMethod請(qǐng)求時(shí)的授權(quán)問題,如有什么問題,還請(qǐng)大家指出.

2018年9月10日 16:46