spring security 的权限控制有两种方式,一种是比较当前请求url和当前用户所拥有的权限中是否包含该url;
另一种是利用@PreAuthorize("hasAuthority('XXX')")注解的方式,其中xxx可以为角色role,也可以为任意的权限标识符,是个string类型
1)注解的方式
需要在websecurityconfig文件上加上@EnableGlobalMethodSecurity(prePostEnabled = true)//开启security注解
然后在loaduserdetail方法中加上该用户所拥有的权限
最后在方法上加注解@PreAuthorize("hasAuthority('XXX')")
2)是利用Spring security拦截的方式
MyAccessDecisionManager.java文件
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文件
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文件
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;
}
}