-
Notifications
You must be signed in to change notification settings - Fork 1.3k
SpringSecurity动态权限管理
Exrick edited this page Apr 29, 2019
·
3 revisions
- Spring Security核心配置入口
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled=true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
...
@Autowired
private MyFilterSecurityInterceptor myFilterSecurityInterceptor;
@Override
protected void configure(HttpSecurity http) throws Exception {
...
registry.and()
...
//添加自定义权限过滤器
.addFilterBefore(myFilterSecurityInterceptor, FilterSecurityInterceptor.class)
}
}
- 权限管理过滤器 监控用户行为
@Component
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);
}
public void invoke(FilterInvocation fi) throws IOException, ServletException {
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;
}
}
- 权限管理决断器 判断用户拥有的权限或角色是否有资源访问权限
@Component
public class MyAccessDecisionManager implements AccessDecisionManager {
@Override
public void decide(Authentication authentication, Object o, Collection<ConfigAttribute> configAttributes) throws AccessDeniedException, InsufficientAuthenticationException {
if(configAttributes==null){
return;
}
Iterator<ConfigAttribute> iterator = configAttributes.iterator();
while (iterator.hasNext()){
ConfigAttribute c = iterator.next();
String needPerm = c.getAttribute();
for(GrantedAuthority ga : authentication.getAuthorities()) {
// 匹配用户拥有的ga 和 系统中的needPerm
if(needPerm.trim().equals(ga.getAuthority())) {
return;
}
}
}
throw new AccessDeniedException("抱歉,您没有访问权限");
}
@Override
public boolean supports(ConfigAttribute configAttribute) {
return true;
}
@Override
public boolean supports(Class<?> aClass) {
return true;
}
}
- 权限资源管理器 为权限决断器提供支持
@Component
public class MySecurityMetadataSource implements FilterInvocationSecurityMetadataSource {
@Autowired
private PermissionService permissionService;
private Map<String, Collection<ConfigAttribute>> map = null;
/**
* 加载权限表中所有操作请求权限
*/
public void loadResourceDefine(){
map = new HashMap<>(16);
Collection<ConfigAttribute> configAttributes;
ConfigAttribute cfg;
// 获取启用的权限操作请求
List<Permission> permissions = permissionService.findByTypeAndStatusOrderBySortOrder(CommonConstant.PERMISSION_OPERATION, CommonConstant.STATUS_NORMAL);
for(Permission permission : permissions) {
if(StrUtil.isNotBlank(permission.getTitle())&&StrUtil.isNotBlank(permission.getPath())){
configAttributes = new ArrayList<>();
cfg = new SecurityConfig(permission.getTitle());
//作为MyAccessDecisionManager类的decide的第三个参数
configAttributes.add(cfg);
//用权限的path作为map的key,用ConfigAttribute的集合作为value
map.put(permission.getPath(), configAttributes);
}
}
}
/**
* 判定用户请求的url是否在权限表中
* 如果在权限表中,则返回给decide方法,用来判定用户是否有此权限
* 如果不在权限表中则放行
* @param o
* @return
* @throws IllegalArgumentException
*/
@Override
public Collection<ConfigAttribute> getAttributes(Object o) throws IllegalArgumentException {
if(map == null){
loadResourceDefine();
}
//Object中包含用户请求request
String url = ((FilterInvocation) o).getRequestUrl();
PathMatcher pathMatcher = new AntPathMatcher();
Iterator<String> iterator = map.keySet().iterator();
while (iterator.hasNext()) {
String resURL = iterator.next();
if (StrUtil.isNotBlank(resURL)&&pathMatcher.match(resURL,url)) {
return map.get(resURL);
}
}
return null;
}
@Override
public Collection<ConfigAttribute> getAllConfigAttributes() {
return null;
}
@Override
public boolean supports(Class<?> aClass) {
return true;
}
}
- 每次编辑权限信息后刷新内存中的系统权限信息
@Autowired
private MySecurityMetadataSource mySecurityMetadataSource;
//重新加载权限
mySecurityMetadataSource.loadResourceDefine();