I have a question: Why is it that when getAttributes() returns null, every subsequent request doesn't go through the MyFilterSecurityInterceptor class and it doesn't intercept for the next request or every request after that?
MyFilterSecurityInterceptor
@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);
}
public void invoke(FilterInvocation fi) throws IOException, ServletException {
//There is a blocked url in fi
//Call the getAttributes(Object object) method of MyInvocationSecurityMetadataSource to get all the permissions corresponding to fi
//Call the decide method of MyAccessDecisionManager to verify whether the user's permissions are sufficient
InterceptorStatusToken token = super.beforeInvocation(fi);
try {
//Execute the next interceptor
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;
}
}
MyFilterSecurityMetadataSource
public class MyFilterSecurityMetadataSource implements FilterInvocationSecurityMetadataSource {
@Override
public List<ConfigAttribute> getAttributes(Object object) {
FilterInvocation fi = (FilterInvocation) object;
HttpServletRequest request = fi.getRequest();
HttpMethod httpMethod = HttpMethod.valueOf(fi.getRequest().getMethod());
// Bypassing Security check for /js, /css and /images url
if (new AntPathRequestMatcher("/js/**").matches(request)
|| new AntPathRequestMatcher("/css/**").matches(request)
|| new AntPathRequestMatcher("/images/**").matches(request)
|| new AntPathRequestMatcher("/login").matches(request)
|| new AntPathRequestMatcher("/").matches(request)
|| new AntPathRequestMatcher("/h2/**").matches(request)) {
return SecurityConfig.createList(new String[] { "Allow" });
}
try {
Collection<? extends GrantedAuthority> authorities = SecurityContextHolder.getContext().getAuthentication()
.getAuthorities();
for (GrantedAuthority grantedAuthority : authorities) {
if(new AntPathRequestMatcher(grantedAuthority.toString()).matches(request)) {
return SecurityConfig.createList(new String[] { "Allow" });
}
}
} catch (Exception e) {
return SecurityConfig.createList(new String[] { "Deny" });
}
return null;
}
public Collection<ConfigAttribute> getAllConfigAttributes() {
return null;
}
public boolean supports(Class<?> clazz) {
return FilterInvocation.class.isAssignableFrom(clazz);
}
}
MyAccessDecisionManager
public class MyAccessDecisionManager implements AccessDecisionManager {
@Override
public void decide(Authentication authentication, Object object, Collection<ConfigAttribute> configAttributes)
throws AccessDeniedException, InsufficientAuthenticationException {
if (configAttributes == null || configAttributes.size() == 0) {
return;
}
Iterator<ConfigAttribute> ite = configAttributes.iterator();
if(ite.next().toString().equalsIgnoreCase("Allow")) {
return;
}
else {
System.out.println("Access is denied");
throw new AccessDeniedException("Access is denied");
}
}
@Override
public boolean supports(ConfigAttribute attribute) {
return true;
}
@Override
public boolean supports(Class<?> clazz) {
return true;
}
}
config security
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private MyFilterSecurityInterceptor myFilterSecurityInterceptor;
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/h2/**").permitAll()
.anyRequest().authenticated()
.and().httpBasic()
.and().formLogin()
.addFilterBefore(myFilterSecurityInterceptor, FilterSecurityInterceptor.class);
}
}
and I have set a breakpoint in debug to check, it really only stops on the first request, and after return null is returned incoming requests are not stopped
