Ilya Y
Ilya Y

Reputation: 844

how to disable @PreAuthorize for tests?

I use Spring Boot with Spring Security. I want to disable security so that @PreAuthorize. I partially managed to do it, but there is still an error.

security is partially disabled. but some part is included. finally, I would like to disable security for certain tests

org.springframework.security.access.AccessDeniedException: Access denied
    at org.springframework.security.access.vote.AffirmativeBased.decide(AffirmativeBased.java:73) ~[spring-security-core-5.5.3.jar:5.5.3]
    at org.springframework.security.access.intercept.AbstractSecurityInterceptor.attemptAuthorization(AbstractSecurityInterceptor.java:238) ~[spring-security-core-5.5.3.jar:5.5.3]

This is my controller

@PreAuthorize("hasAnyAuthority('ADMIN')")
@GetMapping("/hello")
fun hello(): String {
    return "Hello"
}

This my Spring Configutarion for tests.

@TestConfiguration
@Order(1)
class TestSecurityConfig : WebSecurityConfigurerAdapter()  {

    @Override
    override fun configure(httpSecurity: HttpSecurity) {
        http.authorizeRequests()
            .anyRequest().permitAll();

        http.csrf().disable()
            .httpBasic().disable()
            .formLogin().disable()
            .logout().disable();
    }

}

And finally my test class:

@TestInstance(TestInstance.Lifecycle.PER_CLASS)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
    classes = [TestSecurityConfig::class])
@ActiveProfiles("test")
@ExtendWith(SpringExtension::class)
class HelloControllerTest {

    @LocalServerPort
    private var port: Int = 8281

    @Value("#{servletContext.contextPath}")
    private lateinit var contextPath: String

    private lateinit var url: String

    @Autowired
    private lateinit var testRestTemplate: TestRestTemplate


    @BeforeAll
    fun setUp() {
        url = UriComponentsBuilder
            .fromUriString("http://localhost")
            .port(port)
            .path(contextPath)
            .pathSegment("hello")
            .toUriString()
    }

    @Test
    fun hello() {

        val responseEntity = testRestTemplate.getForEntity(url, String::class.java)
        assertNotNull(responseEntity)
        assertEquals(HttpStatus.OK, responseEntity.statusCode)
        val response = responseEntity.body
    }

Upvotes: 0

Views: 2298

Answers (1)

Gannebal Barka
Gannebal Barka

Reputation: 83

Usually you can use mock system for authorization with spring-test

<dependency>
   <groupId>org.springframework.security</groupId>
   <artifactId>spring-security-test</artifactId>
   <scope>test</scope>
</dependency>
<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-test</artifactId>
   <scope>test</scope>
</dependency>

For web FLUX

import org.springframework.security.test.context.support.WithMockUser;
import org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient;
import org.springframework.beans.factory.annotation.Autowired;

@WithMockUser
@SpringBootTest
@AutoConfigureWebTestClient
class MyTest {
    @Autowired
    WebTestClient rest;

    @Test
    void fooTest() {
      StatusAssertions.isOk(rest.get().uri(path).exchange().expectStatus())
    }
}

For web MVC

import org.springframework.security.test.context.support.WithMockUser;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.beans.factory.annotation.Autowired;

import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

@WithMockUser
@AutoConfigureMockMvc
@SpringBootTest
class MyTest {
    @Autowired
    private MockMvc mvc;

    @Test
    void fooTest() {
      mvc.perform(get("path")).andExpect(status().isOk())
    }
}

Upvotes: 0

Related Questions