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
, butServerHttpSecurity
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 andWebTestClient
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 ablock()
.
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.