Access denied exception while trying to access the login page in spring security

Viewed 4175

I am using java based spring security. I have created the custom access decision voter impl.

But when I run the application, I can not open the login page as it says, access is denied.

This happened after I added the custom access decision voter impl. I guess the issue is because of the following code in custom AccessDecisionVoter.

if(authentication instanceof AnonymousAuthenticationToken)
            return ACCESS_DENIED;

But i need this so that permissions are not checked for not logged in users.

And it goes in infinite loop, login page, access decision voter, access denied, login page and so on.

Below is the spring security configuration code.

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private UserDetailsService userDetailsService;

    @Autowired
    private AffirmativeBased accessDecisionManager;

    @Bean
    @Autowired
    public AffirmativeBased accessDecisionManager(AccessDecisionVoterImpl accessDecisionVoter) {
        List<AccessDecisionVoter<?>> accessDecisionVoters = new ArrayList<AccessDecisionVoter<?>>();
        accessDecisionVoters.add(accessDecisionVoter);
        AffirmativeBased accessDecisionManager = new AffirmativeBased(accessDecisionVoters);
        return accessDecisionManager;
    }

    @Override
    @Autowired
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
    }

    @Bean
    public PasswordEncoder passwordEncoder(){
        PasswordEncoder passwordEncoder = new PasswordEncoder();
        passwordEncoder.setStringDigester(stringDigester());
        return passwordEncoder;
    }

    @Bean
    public PooledStringDigester stringDigester() {
        PooledStringDigester psd = new PooledStringDigester();

        psd.setPoolSize(2);
        psd.setAlgorithm("SHA-256");
        psd.setIterations(1000);
        psd.setSaltSizeBytes(16);
        psd.setSaltGenerator(randomSaltGenerator());

        return psd;
    }

    @Bean
    public RandomSaltGenerator randomSaltGenerator() {
        RandomSaltGenerator randomSaltGenerator = new RandomSaltGenerator();
        return randomSaltGenerator;
    }

    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring()
                .antMatchers("/static/**")
                .antMatchers("/i18n/**");
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .csrf()
        .and()
            .formLogin()
            .loginPage("/login")
            .loginProcessingUrl("/checkLogin")
            .defaultSuccessUrl("/home")
            .failureUrl("/login?login_error=1")
            .usernameParameter("username")
            .passwordParameter("password")
            .permitAll()
        .and()
            .logout()
            .logoutUrl("/logout")
            .logoutSuccessUrl("/login?isLoggedOut=1")
            .deleteCookies("JSESSIONID")
            .invalidateHttpSession(true)
            .permitAll()
        .and()
            .authorizeRequests()
            .antMatchers("/login**").permitAll()
            .antMatchers("/error**").permitAll()
            .antMatchers("/checkLogin**").permitAll()
            .anyRequest()
            .authenticated()
            .accessDecisionManager(accessDecisionManager)
        .and()
            .exceptionHandling()
            .accessDeniedPage("/accessDenied")
        .and()
            .headers()
            .frameOptions()
            .disable()
        .and()
            .sessionManagement()
            .invalidSessionUrl("/login")
            .maximumSessions(1);
    }

}

and my custom voter impl

@Component
public class AccessDecisionVoterImpl implements AccessDecisionVoter {

    @Autowired
    private ModuleService moduleService;

    @Override
    public boolean supports(ConfigAttribute attribute) {
        return true;
    }

    @Override
    public boolean supports(Class clazz) {
        return true;
    }

    @Override
    public int vote(Authentication authentication, Object object, Collection collection) {
// i have given this so that if user is not logged in then should not check permission at all 
        if(authentication instanceof AnonymousAuthenticationToken)
            return ACCESS_DENIED;

             HttpServletRequest request = ((FilterInvocation) object).getHttpRequest();
    String requestedOperation = request.getParameter("operation");

    if (requestedOperation != null && !requestedOperation.isEmpty()){
        String [] requestURISplit = request.getRequestURI().split("/");
        String requestedModuleName = requestURISplit[2];

        if(SecurityUtils.hasPermission(requestedModuleName, requestedOperation)){
           return ACCESS_GRANTED;
        }
    } else {
        return ACCESS_GRANTED;
    }

    return ACCESS_DENIED; 

Also, when I remove following lines from my voter, if the user is not logged in and tries to access the secured pages, it goes ahead. It should have redirected to the login page instead.

if(authentication instanceof AnonymousAuthenticationToken)
                return ACCESS_DENIED;

This is the first time I am trying to use the spring boot. Hence, i am not sure of all the configuration issues.

Is there anything wrong with the order of the antMatchers?

Please help.

3 Answers
Related