spring security 的權限控制有兩種方式,一種是比較當前請求url和當前用戶所擁有的權限中是否包含該url;java
另外一種是利用@PreAuthorize("hasAuthority('XXX')")註解的方式,其中xxx能夠爲角色role,也能夠爲任意的權限標識符,是個string類型web
1)註解的方式spring
須要在websecurityconfig文件上加上@EnableGlobalMethodSecurity(prePostEnabled = true)//開啓security註解apache
而後在loaduserdetail方法中加上該用戶所擁有的權限api
最後在方法上加註解@PreAuthorize("hasAuthority('XXX')")ide
2)是利用Spring security攔截的方式post
MyAccessDecisionManager.java文件this
import org.springframework.security.access.AccessDecisionManager; import org.springframework.security.access.AccessDeniedException; import org.springframework.security.access.ConfigAttribute; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.authentication.InsufficientAuthenticationException; import org.springframework.security.core.Authentication; import org.springframework.security.core.GrantedAuthority; import org.springframework.stereotype.Service; import java.util.Collection; import java.util.Iterator; @Service public class MyAccessDecisionManager implements AccessDecisionManager{ //決定是否擁有權限的決策方法 @Override public void decide(Authentication authentication, Object object, Collection<ConfigAttribute> configAttributes) throws AccessDeniedException, InsufficientAuthenticationException { if(null== configAttributes || configAttributes.size() <=0) { return; } ConfigAttribute c; String needRole; for(Iterator<ConfigAttribute> iter = configAttributes.iterator(); iter.hasNext(); ) { c = iter.next(); needRole = c.getAttribute(); for(GrantedAuthority ga : authentication.getAuthorities()) {//authentication 爲在註釋1 中循環添加到 GrantedAuthority 對象中的權限信息集合 if(needRole.trim().equals(ga.getAuthority())) { return; } } } throw new AccessDeniedException("no right"); } @Override public boolean supports(ConfigAttribute attribute) { return false; } @Override public boolean supports(Class<?> clazz) { return true; } }
MyFilterSecurityInterceptor.java文件url
import org.springframework.beans.factory.annotation.Autowired; 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.security.web.access.intercept.FilterInvocationSecurityMetadataSource; import org.springframework.stereotype.Service; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import java.io.IOException; //@Service public class MyFilterSecurityInterceptor extends AbstractSecurityInterceptor implements Filter { @Autowired private FilterInvocationSecurityMetadataSource securityMetadataSource; @Autowired public void setMyAccessDecisionManager(MyAccessDecisionManager myAccessDecisionManager) { super.setAccessDecisionManager(myAccessDecisionManager); } @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { FilterInvocation fi = new FilterInvocation(request, response, chain); invoke(fi); } private void invoke(FilterInvocation fi) throws IOException, ServletException { //fi裏面有一個被攔截的url //裏面調用MyInvocationSecurityMetadataSource的getAttributes(Object object)這個方法獲取fi對應的全部權限 //再調用MyAccessDecisionManager的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 this.securityMetadataSource; } }
MyInvocationSecurityMetadataSourceService.java文件code
import com.lenovo.scct.trackingapi.model.auth.AutResource; import com.lenovo.scct.trackingapi.repository.auth.MenuRepository; import com.lenovo.scct.trackingapi.service.auth.MenuService; import org.apache.commons.lang.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.access.ConfigAttribute; import org.springframework.security.access.SecurityConfig; import org.springframework.security.web.FilterInvocation; import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource; import org.springframework.security.web.util.matcher.AntPathRequestMatcher; import org.springframework.stereotype.Service; import javax.servlet.http.HttpServletRequest; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.Iterator; import java.util.List; @Service public class MyInvocationSecurityMetadataSourceService implements FilterInvocationSecurityMetadataSource { @Autowired MenuRepository menuRepository; private HashMap<String, Collection<ConfigAttribute>> map = null; /** * 加載權限表中全部的權限 */ public void loadResource() { map = new HashMap<>(); Collection<ConfigAttribute> array; ConfigAttribute configAttribute; List<AutResource> resourceList = menuRepository.getMenuResource("lujia3"); for (AutResource autResource : resourceList) { if (StringUtils.isBlank(autResource.getResourceUrl())) { autResource.setResourceUrl("/authorization/**/buttons"); autResource.setResourceName("xxx"); } array = new ArrayList<>(); configAttribute = new SecurityConfig(autResource.getResourceName()); array.add(configAttribute); map.put(autResource.getResourceUrl(), array); } } @Override public Collection<ConfigAttribute> getAttributes(Object object) throws IllegalArgumentException { if (map == null) loadResource(); //object 中包含用戶請求的request 信息 HttpServletRequest request = ((FilterInvocation) object).getHttpRequest(); AntPathRequestMatcher matcher; String resUrl; for (Iterator<String> iter = map.keySet().iterator(); iter.hasNext(); ) { resUrl = iter.next(); matcher = new AntPathRequestMatcher(resUrl); if (matcher.matches(request)) { return map.get(resUrl); } } return null; } @Override public Collection<ConfigAttribute> getAllConfigAttributes() { return null; } @Override public boolean supports(Class<?> clazz) { return true; } }