重写了PathMatchingFilterChainResolver的getChain方法:
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;
}
}
重写了ShiroFilterFactoryBean的createInstance方法:
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:
/api/user/test--POST=anon
/api/**=jwt
/**=anon
在这里由于我是写在配置文件中的,所以==的格式不行,换成了--的格式.测试了两个方法,/api/user/test分别有get和post请求,然后post添加不用认证,如上xml配置文件所示,测试通过,暂时只用到认证,以上可以解决认证的问题.
看基于shiro的改造集成真正支持restful请求还重写了RestPathMatchingFilter的pathsMatch方法,在他的文章中这个类主要是给BJwtFilter继承做授权使用,我现在暂时只用到认证,所以还没有深入了解.
以上已经能够解决同一个url不同的httpMethod请求时的授权问题,如有什么问题,还请大家指出.