package com.common.security.configure; import com.common.annotation.NoAuthorize; import com.common.annotation.NoToken; import com.common.core.utils.SpringContextUtils; import org.aopalliance.intercept.MethodInvocation; import org.springframework.security.access.AccessDecisionVoter; import org.springframework.security.access.ConfigAttribute; import org.springframework.security.core.Authentication; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.web.FilterInvocation; import org.springframework.web.method.HandlerMethod; import org.springframework.web.servlet.mvc.condition.PatternsRequestCondition; import org.springframework.web.servlet.mvc.method.RequestMappingInfo; import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping; import javax.servlet.http.HttpServletRequest; import java.util.*; import java.util.stream.Collectors; public class RoleBasedVoter implements AccessDecisionVoter { @Override public boolean supports(ConfigAttribute attribute) { return true; } @Override public int vote(Authentication authentication, Object object, Collection attributes) { FilterInvocation fi = (FilterInvocation) object; HttpServletRequest fiRequest = fi.getRequest(); String requestURI = fiRequest.getRequestURI(); Map handlerMethods = ((RequestMappingHandlerMapping)SpringContextUtils.getBean("requestMappingHandlerMapping")).getHandlerMethods(); Set anonymousUrls = new HashSet<>(); for (Map.Entry infoEntry : handlerMethods.entrySet()) { // 获取所有接口的方法 HandlerMethod handlerMethod = infoEntry.getValue(); if ( handlerMethod.hasMethodAnnotation(NoAuthorize.class)) { PatternsRequestCondition requestCondition = infoEntry.getKey().getPatternsCondition(); Optional.ofNullable(requestCondition).orElseThrow(RuntimeException::new); anonymousUrls.addAll(requestCondition.getPatterns().stream().map(m -> SpringContextUtils.getEnvParam("server.servlet.context-path")+m).collect(Collectors.toList())); } if ( handlerMethod.hasMethodAnnotation(NoToken.class)) { PatternsRequestCondition requestCondition = infoEntry.getKey().getPatternsCondition(); Optional.ofNullable(requestCondition).orElseThrow(RuntimeException::new); anonymousUrls.addAll(requestCondition.getPatterns().stream().map(m -> SpringContextUtils.getEnvParam("server.servlet.context-path")+m).collect(Collectors.toList())); } } for(String item : Arrays.asList(new String[]{ ".html", ".css", ".js", ".png", ".ttf", ".ico", ".woff", "/swagger-resources", "/v2/api-docs", "/druid" })){ if(requestURI.contains(item)){ return ACCESS_GRANTED; } } if(anonymousUrls.contains(requestURI)){ return ACCESS_GRANTED; } if(authentication == null) { return ACCESS_DENIED; } int result = ACCESS_ABSTAIN; Collection authorities = extractAuthorities(authentication); for (ConfigAttribute attribute : attributes) { if (this.supports(attribute)) { //TODO 目前是所有请求都要判断权限,如后续有不需要判断的,可以启动时从数据库加载到缓存 result = ACCESS_DENIED; // Attempt to find a matching granted authority for (GrantedAuthority authority : authorities) { if (requestURI.equals(authority.getAuthority())) { return ACCESS_GRANTED; } } } } return result; } Collection extractAuthorities( Authentication authentication) { return authentication.getAuthorities(); } @Override public boolean supports(Class clazz) { return true; } }