0

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.

springcorn
  • 611
  • 2
  • 15
  • 28
  • what have you tried, have you even read the spring security documentation before posting here? you are asking the absolute basic questions here before you even tried anything. i recommend you read the basics of spring security in the official documentation. – Toerktumlare Dec 01 '20 at 09:10
  • @Toerktumlare I have tried a million things, I am spinning wheels here. I just posted an edit showing how I tried setting security configuration for the test class that is wide open and how that allowed me to perform Get but I still have the same problems with PostMapping, PutMapping and DeleteMapping. I would think this is a common situation as most applications have security enabled. So people must have to test with TestRestTemplate and security. – springcorn Dec 01 '20 at 18:28
  • @Toerktumlare in terms of reading the documentation, please understand that I actually have the application functioning with authentication working. The problem is all my tests fail. I am literally spending more time trying to get the tests working than the application. – springcorn Dec 01 '20 at 18:31

1 Answers1

2

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()

springcorn
  • 611
  • 2
  • 15
  • 28
  • `@Order on WebSecurityConfigurers must be unique. Order of 100 was already used` raised this error when I tried to create a class for testing purpose. – Nguyễn Đức Tâm Jan 10 '22 at 07:36