2

Many answers to similar questions explains that permitAll() means "allow all authenticated users", and that if you want to skip authentication, you need to do

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

This does not work for me.

In particular, here is my controller test that I would like to pass.

@SpringBootTest
@AutoConfigureMockMvc
public class ChoreApplicationTest
{
    @Autowired
    private MockMvc mockMvc;

    @Test
    public void choresShouldBeEmptyAtStart() throws Exception
    {
        this.mockMvc.perform(get("/chores")).
                andExpect(status().isOk());
    }

Test results:

java.lang.AssertionError: Status expected:<200> but was:<401>
Expected :200
Actual   :401

Here's how I'm setting up the security:

@Configuration
@EnableWebSecurity
public class SecurityConfigurer extends WebSecurityConfigurerAdapter
{
    @Override
    public void configure(WebSecurity web) throws Exception
    {
        web.ignoring().antMatchers("/chores");
        super.configure(web);
    }
}

I reckon you can imagine what's in the Chores controller, but for completeness here's the relevant part:

@RestController
public class ChoreController
{
    private final ChoreRepository repository;

    ChoreController(ChoreRepository repository)
    {
        this.repository = repository;
    }

    @GetMapping("/chores")
    List<Chore> all()
    {
        return this.repository.findAll();
    }
}

Here is the request that the test prints in the output:

MockHttpServletRequest:
      HTTP Method = GET
      Request URI = /chores
       Parameters = {}
          Headers = []
             Body = null
    Session Attrs = {SPRING_SECURITY_SAVED_REQUEST=DefaultSavedRequest[http://localhost/chores]}

So why is my test getting a return code of 401, and how can I fix it?

jon
  • 215
  • 2
  • 12
  • 1
    Remove `super.configure(web);` from `configure(WebSecurity web)` and also make sure you have included the correct endpoint in this method. Can you please share the whole request – Romil Patel May 31 '20 at 16:54
  • @PatelRomil I'm getting the same thing without `super`. I've edited in the whole request. – jon May 31 '20 at 16:56
  • 1
    Hello @jon, Does your `SecurityConfigurer` class consist of `configure(HttpSecurity http)` method? Also add `@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)` in `SecurityConfigurer` and let me know – Romil Patel May 31 '20 at 16:59
  • If `SecurityConfigurer` consists of both methods `configure(WebSecurity web)` and `configure(HttpSecurity http)`. Make sure `configure(WebSecurity web)` is place above the `configure(HttpSecurity http)` – Romil Patel May 31 '20 at 17:01
  • @PatelRomil The `SecurityConfigurer` I pasted above is exactly what I'm using in my code. I've added the `@EnableGlobalMethodSecurity` annotation and got the same result. – jon May 31 '20 at 17:02
  • Please add `@Override public void configure(HttpSecurity http) throws Exception { http. csrf().disable() .cors().disable() .authorizeRequests() .antMatchers("/chores").permitAll() .anyRequest().authenticated(); }` and have a try again – Romil Patel May 31 '20 at 17:04
  • @PatelRomil I added this method, making sure t was below `configure(WebSecurity)`, and I am still seeing the same results in my test. – jon May 31 '20 at 17:07
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/215042/discussion-between-patel-romil-and-jon). – Romil Patel May 31 '20 at 17:09

2 Answers2

1

Security configurations are correct in configure(WebSecurity web), but the issue was SecurityConfigurer does not get invoked due to packages were different.

Spring Boot starts execution from the main application that is ChoreApplication, also note that all classes are in package chore other than SecurityConfigurer (in package security)

Our main application class consists of @SpringBootApplication where

@SpringBootApplication = @SpringBootConfiguration + @EnableAutoConfiguration + @ComponentScan

@ComponentScan

By default, spring will take care of all the classes which are in package chore, here the issue was spring does not know anything about classes resides in other packages. Here SecurityConfigurer in package security

To get invoked SecurityConfigurer, we have to add security package in as @ComponentScan(basePackages = {"chores", "security"})

Project


ChoreApplication.java

package chores;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;

@SpringBootApplication
@ComponentScan(basePackages = {"chores", "security"})
public class ChoreApplication
{
    public static void main(String args[])
    {
        SpringApplication.run(ChoreApplication.class, args);
    }
}

SecurityConfigurer.java

package security;

import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
public class SecurityConfigurer extends WebSecurityConfigurerAdapter {
    @Override
    public void configure(WebSecurity web) {
        web.ignoring().antMatchers("/chores");
    }
}

You may love to explore

Spring Security Configuration: HttpSecurity-vs-Webecurity

How to scan multiple paths using the @ComponentScan annotation

Romil Patel
  • 12,879
  • 7
  • 47
  • 76
0
@ActiveProfiles("integration-test")
@SpringBootTest
@AutoConfigureMockMvc
public class ChoreApplicationTest{}


@Configuration
@EnableWebSecurity
@Profile("!integration-test")
public class SecurityConfigurer extends WebSecurityConfigurerAdapter{}

You can ignore security by this way.

If you are writing integration test, then you can set profile to ignore some specific areas of spring. Example: security.

ActiveProfile can be on configuration file.

Gurkan İlleez
  • 1,503
  • 1
  • 10
  • 12