Bug description

When I run a load testing script that sends 150 requests/second for 10s targeting an endpoint that is protected by BASIC authentication with Spring Security, I see in JVisualVM that the CPU utilization remains mostly over 80% (even reaching peaks of 100%) and the response times increases significantly (average 302ms, p(90) 658ms, p(95) 1.1s), compared to when I run the same script targeting another endpoint in the same application that is not protected by BASIC authentication, when I see that the CPU utilization remains mostly under 10% and I get an average response time of 27ms, p(90) 46ms, p(95) 214ms.

Results of load testing the non-protected endpoint

JVisualVM Monitoring execution1-server-monitoring

Load Testing Tool Summary execution1-k6-summary

Results of load testing the protected endpoint

JVisualVM Monitoring execution2-server-monitoring

Load Testing Tool Summary execution2-k6-summary

To Reproduce

Basically, running a minimal application with an endpoint protected by BASIC authentication and running a load testing tool that fires 150 request/sec during 10 seconds is enough to reproduce and observe the behavior. Way more detailed information can be found on the sample provided below.

Expected behavior

When I load test the application targeting the protected endpoint, I expected CPU utilization and response times to be more similar to when I load test the application targeting the non-protected endpoint, i.e., CPU utilization around 10% and response times with average near 27ms, p(90) near 46ms, p(95) near 214ms.

Sample

I provided a minimal and reproducible sample that can be found at https://github.com/rafaelvanderlei/spring-security-loadtesting

Please let me know if more information is needed.

Comment From: rafaelvanderlei

I was wondering if there was an older version of Spring Boot that would be using an older version of Spring Security for the purpose of figuring out since which Spring Security version this behavior (100% CPU for BASIC authentication endpoint) started to happen, so I kept downgrading the Spring Boot version while keeping the rest of the application code untouched and I came up with this table:

spring-boot-version spring-security-web-version result *
2.5.2 5.5.12 BAD
2.4.8 5.4.7 BAD
2.3.12.RELEASE 5.3.9.RELEASE BAD
2.2.13.RELEASE 5.2.8.RELEASE BAD
2.1.18.RELEASE 5.1.13.RELEASE BAD
2.1.10.RELEASE 5.1.7.RELEASE BAD
2.1.5.RELEASE 5.1.5.RELEASE BAD
2.1.0.RELEASE 5.1.1.RELEASE BAD
2.0.9.RELEASE 5.0.12.RELEASE GOOD

* BAD just means high CPU utilization, while GOOD means low CPU utilization

This leads us to notice that the observed behavior was introduced somewhere between Spring Security versions 5.0.12.RELEASE and 5.1.1.RELEASE.

Comment From: jzheaux

Thanks for the detailed research, @rafaelvanderlei.

This is by design. BASIC authentication requires that the password be hashed on each request in order to mitigate brute force attacks. As a general rule, password hashing for BASIC authentication should be tuned on your server to take hundreds of milliseconds per hash.

If you feel like the performance lag is not due to hashing, then please re-open with more detail, and I'd be happy to take a closer look.