Warm tip: This article is reproduced from serverfault.com, please click

TestRestTemplate and spring security

发布于 2020-11-30 19:45:26

I am learning spring rest. I am slowly building an application. I had full integration testing working well using TestRestTemplate.
However, I just started adding spring security to my application. Literally as soon as I add the spring security dependency, my testing fails.

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

I get these errors like so:

Error while extracting response for type [class [Lcom.myproject.model.viewobjects.AView;] and content type [application/json]; nested exception is org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Cannot deserialize instance of `[Lcom.myproject.model.viewobjects.AView;` out of START_OBJECT token; nested exception is com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize instance of `[Lcom.myproject.model.viewobjects.AView;` out of START_OBJECT token
 at [Source: (PushbackInputStream); line: 1, column: 1]

When I debug, the object it returns which it is trying deserialize is null. If I put a breakpoint on the rest controller it doesn't even get there.

It seems like just adding the dependency turns a lot of defaults on. How do I test with security on? 1)Can I disable the security for testing somehow?

2)Can I somehow allow no credentials or send acceptable fake credentials? (I did see examples of @WithMockUser but that doesn't work with TestRestTemplate)

Edit: I tried adding a security implementation to my test class to enable anonymous access and permitall:

@EnableWebSecurity
class TestSecurityConfig extends WebSecurityConfigurerAdapter
    {
    @Override
    protected void configure(HttpSecurity http) throws Exception
        {
        http.anonymous().and().authorizeRequests().antMatchers("/**").permitAll();
        }
    }

The result of this is that @GetMapping work. I can trace that the calls reach the controller. But @PostMapping still do not work. The calls never reach the controller. The post calls look like so:

updatedAView = restTemplate.postForObject(create_aview_url, aView, AView.class);

Why would get work but not post??? Also, to make sure there wasn't something else, I again went and removed the spring-boot-starter-security dependency and all the code that relates. Suddenly everything works. So it is definitely the security config that does this.

Questioner
springcorn
Viewed
0
springcorn 2020-12-02 06:12:16

If you include the spring-boot-starter-security dependency, spring security is enabled by default. TestRestTemplate requests will be processed through the security system.

If you want to test without authentication, you can configure a version of WebSecurityConfigurerAdapter with @EnableWebSecurity for testing only that is permissive. You may need to exclude other configurations so they don't override this.

Here is an example:

@EnableWebSecurity
class TestSecurityConfig extends WebSecurityConfigurerAdapter
    {
    @Override
    protected void configure(HttpSecurity http) throws Exception
        {
        http.anonymous().and().csrf().disable().authorizeRequests().antMatchers("/**").permitAll();
        }
    }

This allows you to make requests without user credentials

http.anonymous()

If you don't include the:

csrf().disable()

@GetMapping will work but no PostMapping or requests that change data as that is when csrf comes into play and it is enabled by default.

This permits you to access all the URLs in your application. You can of course limit this if you like:

authorizeRequests().antMatchers("/**").permitAll()