在线观看不卡亚洲电影_亚洲妓女99综合网_91青青青亚洲娱乐在线观看_日韩无码高清综合久久

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

shiro自定義過濾器對restful風格實現(xiàn)攔截的問題

前提

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

問題

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

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

我現(xiàn)在僅僅想對POST方法做權限控制,讓他走我自定義的那個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注解,但是這樣子,那個方法不走我的JWTFilter,如何讓這個需要認證的url走我的自定義filter,該如何配置,求解.謝謝.

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

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

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

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

  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請求的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>

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

2018年9月10日 16:46