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<Object> {
|
|
@Override
|
public boolean supports(ConfigAttribute attribute) {
|
return true;
|
}
|
|
@Override
|
public int vote(Authentication authentication, Object object, Collection<ConfigAttribute> attributes) {
|
FilterInvocation fi = (FilterInvocation) object;
|
HttpServletRequest fiRequest = fi.getRequest();
|
String requestURI = fiRequest.getRequestURI();
|
Map<RequestMappingInfo, HandlerMethod> handlerMethods = ((RequestMappingHandlerMapping)SpringContextUtils.getBean("requestMappingHandlerMapping")).getHandlerMethods();
|
Set<String> anonymousUrls = new HashSet<>();
|
for (Map.Entry<RequestMappingInfo, HandlerMethod> 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<? extends GrantedAuthority> 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<? extends GrantedAuthority> extractAuthorities(
|
Authentication authentication) {
|
return authentication.getAuthorities();
|
}
|
|
@Override
|
public boolean supports(Class clazz) {
|
return true;
|
}
|
}
|