Skip to content

Document using Spring Security without a servlet request - #19944

Open
Yusuf-Hussien wants to merge 2 commits into
spring-projects:mainfrom
Yusuf-Hussien:docs/11910-outside-servlet
Open

Yusuf-Hussien wants to merge 2 commits into
spring-projects:mainfrom
Yusuf-Hussien:docs/11910-outside-servlet

Conversation

@Yusuf-Hussien

Copy link
Copy Markdown

Closes gh-11910

Adds a single entry point for using Spring Security in code that runs without an HTTP request: scheduled jobs, CLI runners, message listeners, background threads, and plain unit tests.

The reference documentation is organized around Servlet and Reactive applications, and the only page that touches non-request code today is features/integrations/concurrency.adoc, which assumes you already know you need DelegatingSecurityContextRunnable. This new page starts from the "I have no HttpServletRequest" case and links out to the existing material instead of repeating it:

  • the SecurityContextHolder / ThreadLocal model and setting/clearing the context manually;
  • propagating the context to other threads, linking to features/integrations/concurrency.adoc;
  • method security (@PreAuthorize) in a non-web context, linking to the method security docs;
  • testing with @WithMockUser / @WithSecurityContext without MockMvc, linking to servlet/test/method.adoc;
  • a short pointer to the Reactive stack for anyone not using SecurityContextHolder.

Changes:

  • add docs/modules/ROOT/pages/features/integrations/outside-servlet.adoc
  • add Outside of a Servlet Request to docs/modules/ROOT/nav.adoc under Features > Integrations

Verified locally with ./gradlew :spring-security-docs:antora; the new page renders and all cross-references resolve.

Add a dedicated entry point under Features > Integrations that
explains how to apply Spring Security in non-web contexts such as
scheduled jobs, CLI runners, message listeners, and plain unit tests:
populating and clearing the SecurityContextHolder, propagating the
context to other threads, securing methods with @PreAuthorize, and
testing without MockMvc. Cross-reference the existing concurrency,
method security, and testing sections instead of duplicating them.

Closes spring-projectsgh-11910

Signed-off-by: Yusuf Hussien <yhussien01@gmail.com>

@utafrali utafrali left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Useful documentation addition that fills a real gap, but the method-security snippet is missing @Configuration (will not work as shown), the page title does not match the Reactive content it also covers, and the code samples are inlined rather than included from compiled example sources as elsewhere in the reference. Worth another pass before merge.

See xref:features/integrations/concurrency.adoc[Concurrency Support] for the full set of wrappers.

[[outside-servlet-method-security]]
== Method Security

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The MethodSecurityConfig sample is missing @Configuration:

@EnableMethodSecurity
public class MethodSecurityConfig {
}

@EnableMethodSecurity is a stereotype that imports configuration but the enclosing class still needs to be a Spring-managed bean to be picked up (either @Configuration, or picked up via component scan on another stereotype). As written, dropped into a plain class, the annotation has no effect and readers will quietly end up with no method security enabled. Please add @Configuration to both the Java and Kotlin snippets to match the rest of the Spring Security reference docs.

@@ -0,0 +1,190 @@
[[outside-servlet]]
= Spring Security Outside of a Servlet Request

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The page title says "Outside of a Servlet Request" but the content explicitly covers Reactive scenarios too (section [[outside-servlet-reactive]] at the end, plus the opening paragraph mentions Reactive). Consider renaming to "Outside of a Request" (and updating the nav entry and the outside-servlet anchor/filename accordingly), or scoping the page strictly to Servlet and moving the Reactive pointer to its own small page. As it stands, readers on a reactive stack will skip this page based on the title and miss the pointer that is intended for them.

[tabs]
======
Java::
+

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The rest of the Spring Security reference pulls code samples from compiled example sources (e.g. include::partial$...) rather than embedding inline Java/Kotlin blocks. Inlined snippets like the try/finally block here, the DelegatingSecurityContextRunnable block, and the @SpringBootTest test do not get compiled, so a future rename of SecurityContextHolder.createEmptyContext() or DelegatingSecurityContextRunnable will silently rot this page. Consider moving the samples into the docs module's example sources and using include:: with tag regions, as features/integrations/concurrency.adoc does.


[[outside-servlet-testing]]
== Testing Without a Web Request

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The testing example bootstraps the full application context with @SpringBootTest, but the surrounding prose promises "plain unit tests that exercise secured services directly" (bullet in the intro). For a reader who truly has no web layer, a slice test or a plain @ExtendWith(SpringExtension.class) + narrow @ContextConfiguration is a much better fit and much faster. Consider either switching the snippet to a lighter setup or adding a sentence noting that @WithMockUser works with any Spring Test context, not only @SpringBootTest.

Comment thread docs/modules/ROOT/nav.adoc Outdated
*** xref:features/exploits/headers.adoc[HTTP Headers]
*** xref:features/exploits/http.adoc[HTTP Requests]
** xref:features/integrations/index.adoc[Integrations]
*** xref:features/integrations/outside-servlet.adoc[Outside of a Servlet Request]

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new entry is inserted as the first child of Integrations, ahead of REST Client and Cryptography. The existing order under Integrations is not strictly alphabetical, but putting a brand-new, cross-cutting "Outside of a Servlet Request" entry at the very top gives it more prominence than, say, Cryptography or CORS. Consider placing it after the existing integration entries (or alphabetically between Observability and REST Client) so the ordering reflects discovery priority rather than recency of addition.

[[outside-servlet-reactive]]
== Reactive Environments

If you are on a reactive stack, `SecurityContextHolder` is not the idiomatic mechanism; Spring Security instead carries the context through Reactor's `Context`.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The reactive pointer links only to reactive/index.adoc. For readers who arrived here specifically because they are propagating context across threads without a request, a direct link to the reactive equivalent of SecurityContextHolder (ReactiveSecurityContextHolder, documented under reactive/authentication/) would save a hop. Suggestion: add a second xref to the reactive authentication architecture page alongside the existing one.

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged label Oct 20, 2026
- Rename the page to "Outside of a Request" and the anchors to
  outside-request-*, since it also covers reactive environments
- Add @configuration to the method security samples so
  @EnableMethodSecurity actually takes effect
- Use a lightweight Spring Test slice instead of @SpringBootTest
- Link directly to ReactiveSecurityContextHolder
- Move the nav entry below the existing integration entries

Closes spring-projectsgh-11910

Signed-off-by: Yusuf Hussien <yhussien01@gmail.com>
@Yusuf-Hussien

Copy link
Copy Markdown
Author

Thanks for the detailed review, @utafrali. I've pushed a revision that addresses the points:

  • Added @Configuration to the MethodSecurityConfig samples (Java and Kotlin) so @EnableMethodSecurity actually takes effect. Good catch.
  • Renamed the page and anchors to "Outside of a Request" (outside-request), since it covers the reactive pointer too. Updated the nav entry and filename accordingly.
  • Switched the testing sample from @SpringBootTest to a lightweight @ExtendWith(SpringExtension.class) + @ContextConfiguration slice, and noted that @WithMockUser works with any Spring Test context.
  • Added a direct xref to ReactiveSecurityContextHolder (reactive/authorization/method.adoc) alongside the reactive index link.
  • Moved the nav entry below the existing integration entries instead of the top of the list.

On the compiled-samples point: I kept the snippets inline for now. The nearest siblings (concurrency.adoc, data.adoc) also use inline ====== tabs, so this matches them rather than the include-code:: style used under servlet/.... If you'd prefer, I'm happy to move them into docs-src examples with tag regions - just let me know whether that should follow the include-code::./File[tag=...] convention here.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

status: waiting-for-triage An issue we've not yet triaged

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Document non Servlet code separately

3 participants