package com.ycl.component; import com.ycl.config.IgnoreUrlsConfig; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpMethod; import org.springframework.security.access.SecurityMetadataSource; import org.springframework.security.access.intercept.AbstractSecurityInterceptor; import org.springframework.security.access.intercept.InterceptorStatusToken; import org.springframework.security.web.FilterInvocation; import org.springframework.util.AntPathMatcher; import org.springframework.util.PathMatcher; import javax.servlet.*; import javax.servlet.http.HttpServletRequest; import java.io.IOException; /** * 动态权限过滤器,用于实现基于路径的动态权限过滤 */ public class DynamicSecurityFilter extends AbstractSecurityInterceptor implements Filter { @Autowired private DynamicSecurityMetadataSource dynamicSecurityMetadataSource; @Autowired private IgnoreUrlsConfig ignoreUrlsConfig; @Autowired public void setMyAccessDecisionManager(DynamicAccessDecisionManager dynamicAccessDecisionManager) { super.setAccessDecisionManager(dynamicAccessDecisionManager); } @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest) servletRequest; FilterInvocation fi = new FilterInvocation(servletRequest, servletResponse, filterChain); //OPTIONS请求直接放行 if(request.getMethod().equals(HttpMethod.OPTIONS.toString())){ fi.getChain().doFilter(fi.getRequest(), fi.getResponse()); return; } //白名单请求直接放行 PathMatcher pathMatcher = new AntPathMatcher(); for (String path : ignoreUrlsConfig.getUrls()) { if(pathMatcher.match(path,request.getServletPath())){ fi.getChain().doFilter(fi.getRequest(), fi.getResponse()); return; } } //此处会调用AccessDecisionManager中的decide方法进行鉴权操作 InterceptorStatusToken token = super.beforeInvocation(fi); try { fi.getChain().doFilter(fi.getRequest(), fi.getResponse()); } finally { super.afterInvocation(token, null); } } @Override public void destroy() { } @Override public Class getSecureObjectClass() { return FilterInvocation.class; } @Override public SecurityMetadataSource obtainSecurityMetadataSource() { return dynamicSecurityMetadataSource; } }