在SpringSecurity的日常开发中,可能使用SpringSecurity的PermitAll()请求还是会被拦截,这是为什么呢?
public WebSecurityCustomizer webSecurityCustomizer(){
return web->{
web.ignoring().antMatchers("/login","/logout","/captcha");
};
}
httpSecurity.authorizeRequests()
.antMatchers("/login","/logout","/captcha").permitAll()
.anyRequest().authenticated()
当使用WebSecurityCustomizer的时候,过滤器会忽略后面请求的路径,默认就不会走springSecurity的过滤器和重写的springSecurity的过滤器。但是还是会被自定义的过滤器所拦截。因此常用于静态页面等的存放。
当使用PermitAll的时候,SpringSecurity会拿到你放行的请求进行判断,因此不会被SpringSecurity默认的过滤器所拦截,但是可能会被我们重写的过滤器所拦截,但是当在授权的时候如果实现了FilterInvocationSecurityMetadataSource(授权时的元数据,如果基于RBAC框架,就是当前请求所需要的角色进行判断),也需要判断是否是放行的资源,然后在重写的
AccessDecisionManager决定是否放行,根据不同的角色判断出不同的情况。
判断当前的请求需要哪些角色,如果与UrlConstant中需要放行的请求相对应,就返回null,然后在
AccessDecisionManager中进行相应的判断
@Component
public class CustomerFilter implements FilterInvocationSecurityMetadataSource {
@Autowired
private IMenuService menuService;
AntPathMatcher antPathMatcher = new AntPathMatcher();
@Override
public Collection<ConfigAttribute> getAttributes(Object object) throws IllegalArgumentException {
//获取到登录请求的url
String url = ((FilterInvocation) object).getRequestUrl();
for (String s : UrlConstant.urls) {
if(antPathMatcher.match(s,url)){
return null;
}
}
List<Menu> menuList = menuService.getMenuWithRole();
for (Menu menu : menuList) {
if (antPathMatcher.match(menu.getUrl(), url)) {
String[] strings = menu.getRoles().stream().map(it -> {
return it.getName();
}).toArray(String[]::new);
//转换为
return SecurityConfig.createList(strings);
}
}
return SecurityConfig.createList("ROLE_LOGIN");
}
@Override
public Collection<ConfigAttribute> getAllConfigAttributes() {
return null;
}
@Override
public boolean supports(Class<?> clazz) {
return true;
}
}
决定此次请求是否被允许访问的
@Component
public class CustomerDecisionFilter implements AccessDecisionManager {
@Override
public void decide(Authentication authentication, Object object, Collection<ConfigAttribute> configAttributes) throws AccessDeniedException, InsufficientAuthenticationException {
if(configAttributes.isEmpty()||configAttributes.size()==0){
return;
}
for (ConfigAttribute configAttribute : configAttributes) {
//这就是当前url需要的角色,满足其中一个角色就可以了
String attribute = configAttribute.getAttribute();
if("ROLE_LOGIN".equals(attribute)){
//判断当前是否登录,如果没有登录
return;
}
//取出当前的角色
//TODO
Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities();
for (GrantedAuthority authority : authorities) {
String authorityAuth = authority.getAuthority();
if(authorityAuth.equals(attribute)){
return;
}
}
}
throw new AccessDeniedException("权限不足");
}
@Override
public boolean supports(ConfigAttribute attribute) {
return false;
}
@Override
public boolean supports(Class<?> clazz) {
return false;
}
}