Hi, I wanted to create a security module in order to factorize classes that I write over and over again in all my Spring projects, my idea was to create a security module which works everywhere just by importing the module, even between Spring MVC and Spring Webflux projects, by using a profile at best.

The Spring MVC and Webflux classes are accessible in Spring Core so I can write the production code I want for both, but the implementation isn't so I can't test my module, let me explain with more details.

Security configuration

  • When you create a security config class for Spring MVC, you extends your class with WebSecurityConfigurerAdapter. This doesn't work with Spring Webflux.
  • When you create a security config class for Spring Webflux, you create a bean which is a build from ServerHttpSecurity, but ServerHttpSecurity isn't available in Spring MVC at Runtime.

Observation: My custom implementation doesn't change, only the Spring way of defining security change a little bit (this "little bit" stuff make things a "little bit" harder). Spring profiles do the job so I can write two security configuration classes and pick the one I want when the application starts. Why not? :)

Proposal: Make the ServerHttpSecurity way of defining security the same for both Spring MVC and Spring Webflux. Make ServerHttpSecurity available for Spring MVC, this API looks nicer than extending WebSecurityConfigurerAdapter anyway.

Tests

  • I want to test my security configuration, so I have to use MockMvc for Spring MVC and WebTestClient for Spring Webflux... two different Spring classes that share the same purpose. So I have to rewrite the same test classes but @IfProfileValue + @ActiveProfiles can't be mixed, can't do the job.
  • When I am in a Spring MVC environment, if my Controller has a Mono<String> return type, the HTTP response body is empty, I think that Spring MVC should implicitely apply a block().

Observation: I'm stucked at tests, because I have to include org.springframework.boot:spring-boot-starter-web for Spring MVC OR org.springframework.boot:spring-boot-starter-webflux for Spring Webflux, if I do both then Spring MVC has the priority but ServerHttpSecurity isn't available and tests fail. If I include org.springframework.boot:spring-boot-starter-webflux only then MockMvc isn't available and tests fail etcetera

Proposal: Make the WebTestClient way of testing routes available for both Spring MVC and Spring Webflux. Make WebTestClient available for Spring MVC, this API looks nicer than MockMvc anyway.

I know I can create to different modules, one for Spring MVC projects and the other for Webflux projects, but please consider this as an idea to make things easier between Spring MVC and Spring Webflux projects, make the learning curve easier for developpers who want to switch between Spring MVC and Webflux without doing more efforts than learning reactive classes like Mono and Flux. Thanks :)

Comment From: snicoll

While they feel "very close" from a configuration perspective because we were very careful to provide a consistent developer experience, the imperative and reactive frameworks are on different programming paradigms and are quite independent in practice.

This issue tracker isn't the right place to discuss why the security configuration is different between imperative and reactive. Looking at the Spring Security documentation, they make a clear distinction between Servlet applications and reactive applications. You may want to ask for more context on the #spring-security Gitter channel.

You can use WebTestClient for everything when running against an actual server. If you prefer to mock, MockMVC has to be used with Spring MVC.

if I do both then Spring MVC has the priority but ServerHttpSecurity isn't available and tests fail.

If you chose to add support for Spring MVC and Spring WebFlux in the same module, you will need to properly exercise those scenarios rather than starting an integration test. Sprig Boot provides such support and our testing scenarios use ApplicationContextRunner to simulate the environment that is under test. If you provide such infrastructure, I'd do so via auto-configuration rather than using profiles as you could automatically detect in which environment you run to apply only the customizations that make sense.

If you have more questions, please follow-up on StackOverflow or come chat with the community on Gitter, as mentioned in the guidelines for contributing, we prefer to use GitHub issues only for bugs and enhancements.