Maintainers
Pricing
Enterprise
More
More
Documentation
Try Live
Rankings
Install
Blog
Docs7
Ask
New
Add Docs
Spring Security
https://github.com/spring-projects/spring-security
Admin
Spring Security
Tokens:
1,760,497
Snippets:
9,040
Trust Score:
9.7
License:
Apache-2.0
Update:
4 days ago
Context
Chat
Benchmark
67.1
Latest
Show doc for...
Code
Info
Show Results
Tokens:
Raw
Copy
Link
Tokens:
Raw
Copy
Link
### Using DelegatingSecurityContextRunnable with a new Thread Source: https://github.com/spring-projects/spring-security/blob/main/docs/modules/ROOT/pages/servlet/integrations/concurrency.adoc Example of creating a Runnable, wrapping it with DelegatingSecurityContextRunnable using the current SecurityContext, and starting a new thread. ```java Runnable originalRunnable = new Runnable() { public void run() { // invoke secured service } }; SecurityContext context = SecurityContextHolder.getContext(); DelegatingSecurityContextRunnable wrappedRunnable = new DelegatingSecurityContextRunnable(originalRunnable, context); new Thread(wrappedRunnable).start(); ``` -------------------------------- ### WebTestClient Security Setup with springSecurity() and basicAuthentication Source: https://github.com/spring-projects/spring-security/blob/main/docs/modules/ROOT/pages/reactive/test/web/setup.adoc Basic WebTestClient security setup for Spring Security tests. The Java and Kotlin versions are equivalent and shown as tabs. The setup binds the WebTestClient to the application context, applies the springSecurity() configurer, and adds a basicAuthentication filter for user "user" with password "password". ```java import static org.springframework.security.test.web.reactive.server.SecurityMockServerConfigurers.springSecurity; import static org.springframework.web.reactive.function.client.ExchangeFilterFunctions.basicAuthentication; @ExtendWith(SpringExtension.class) @ContextConfiguration(classes = HelloWebfluxMethodApplication.class) public class HelloWebfluxMethodApplicationTests { @Autowired ApplicationContext context; WebTestClient rest; @BeforeEach public void setup() { this.rest = WebTestClient .bindToApplicationContext(this.context) // add Spring Security test Support .apply(springSecurity()) .configureClient() .filter(basicAuthentication("user", "password")) .build(); } // ... } ``` ```kotlin import org.springframework.security.test.web.reactive.server.SecurityMockServerConfigurers.springSecurity import org.springframework.web.reactive.function.client.ExchangeFilterFunctions.basicAuthentication @ExtendWith(SpringExtension::class) @ContextConfiguration(classes = [HelloWebfluxMethodApplication::class]) class HelloWebfluxMethodApplicationTests { @Autowired lateinit var context: ApplicationContext lateinit var rest: WebTestClient @BeforeEach fun setup() { this.rest = WebTestClient .bindToApplicationContext(this.context) // add Spring Security test Support .apply(springSecurity()) .configureClient() .filter(basicAuthentication("user", "password")) .build() } // ... } ``` -------------------------------- ### Example Registration Request Source: https://github.com/spring-projects/spring-security/blob/main/docs/modules/ROOT/pages/servlet/authentication/passkeys.adoc Example registration request. The publicKey is the result of calling navigator.credentials.create with binary values base64url encoded; the label is user-selected to distinguish the credential. ```http POST /webauthn/register X-CSRF-TOKEN: 4bfd1575-3ad1-4d21-96c7-4ef2d9f86721 { "publicKey": { // <1> "credential": { "id": "dYF7EGnRFFIXkpXi9XU2wg", "rawId": "dYF7EGnRFFIXkpXi9XU2wg", "response": { "attestationObject": "o2NmbXRkbm9uZWdhdHRTdG10oGhhdXRoRGF0YViUy9GqwTRaMpzVDbXq1dyEAXVOxrou08k22ggRC45MKNhdAAAAALraVWanqkAfvZZFYZpVEg0AEHWBexBp0RRSF5KV4vV1NsKlAQIDJiABIVggQjmrekPGzyqtoKK9HPUH-8Z2FLpoqkklFpFPQVICQ3IiWCD6I9Jvmor685fOZOyGXqUd87tXfvJk8rxj9OhuZvUALA", "clientDataJSON": "eyJ0eXBlIjoid2ViYXV0aG4uY3JlYXRlIiwiY2hhbGxlbmdlIjoiSl9RTi10SFJYRWVKYjlNcUNrWmFPLUdOVmlibXpGVGVWMk43Z0ptQUdrQSIsIm9yaWdpbiI6Imh0dHBzOi8vZXhhbXBsZS5sb2NhbGhvc3Q6ODQ0MyIsImNyb3NzT3JpZ2luIjpmYWxzZX0", "transports": [ "internal", "hybrid" ] }, "type": "public-key", "clientExtensionResults": {}, "authenticatorAttachment": "platform" }, "label": "1password" // <2> } } ``` -------------------------------- ### Install Spring Security artifacts to local Maven repository Source: https://github.com/spring-projects/spring-security/blob/main/README.adoc Installs all spring-*.jar files into the local Maven repository. Run this before building the project to resolve dependencies. ```bash ./gradlew publishToMavenLocal ``` -------------------------------- ### Configure RSocket Authorization Rules Source: https://github.com/spring-projects/spring-security/blob/main/docs/modules/ROOT/pages/reactive/integrations/rsocket.adoc Configures RSocket authorization rules using the DSL. Rules are evaluated in order, and only the first matching rule is invoked. The example sets up rules for setup, specific routes, custom matchers, and fallback rules for any request or exchange. ```java rsocket .authorizePayload(authz -> authz .setup().hasRole("SETUP") // <1> .route("fetch.profile.me").authenticated() // <2> .matcher((payloadExchange) -> payloadExchange(payloadExchange)) // <3> .hasRole("CUSTOM") .route("fetch.profile.{username}") // <4> .access((authentication, context) -> checkFriends(authentication, context)) .anyRequest().authenticated() // <5> .anyExchange().permitAll() // <6> ); ``` ```kotlin rsocket .authorizePayload { authz -> authz .setup().hasRole("SETUP") // <1> .route("fetch.profile.me").authenticated() // <2> .matcher { payloadExchange -> isMatch(payloadExchange) } // <3> .hasRole("CUSTOM") .route("fetch.profile.{username}") // <4> .access { authentication, context -> checkFriends(authentication, context) } .anyRequest().authenticated() // <5> .anyExchange().permitAll() } // <6> ``` -------------------------------- ### Configure Resource Server with JWTs (Java and Kotlin) Source: https://github.com/spring-projects/spring-security/blob/main/docs/modules/ROOT/pages/servlet/oauth2/index.adoc Configures a resource server with JWT support. The Java example shows the default arrangement equivalent to the Spring Boot configuration properties. The Kotlin example is incomplete in the source. ```java @Configuration @EnableWebSecurity public class SecurityConfig { @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http .authorizeHttpRequests((authorize) -> authorize .anyRequest().authenticated() ) .oauth2ResourceServer((oauth2) -> oauth2 .jwt(Customizer.withDefaults()) ); return http.build(); } @Bean public JwtDecoder jwtDecoder() { return JwtDecoders.fromIssuerLocation("https://my-auth-server.com"); } } ``` ```kotlin import org.springframework.security.config.annotation.web.invoke @Configuration @EnableWebSecurity class SecurityConfig { ``` -------------------------------- ### Feature-Policy Example Source: https://github.com/spring-projects/spring-security/blob/main/docs/modules/ROOT/pages/reactive/exploits/headers.adoc Example of a Feature-Policy header that allows geolocation only for the same origin. This header is not added by default; you must configure it explicitly. ```http Feature-Policy: geolocation 'self' ``` -------------------------------- ### Refreshable RelyingPartyRegistrationRepository using OpenSaml5AssertingPartyMetadataRepository (Kotlin) Source: https://github.com/spring-projects/spring-security/blob/main/docs/modules/ROOT/pages/servlet/saml2/metadata.adoc Kotlin version of the refreshable repository example, using OpenSaml5AssertingPartyMetadataRepository and implementing IterableRelyingPartyRegistrationRepository. ```kotlin @Component class RefreshableRelyingPartyRegistrationRepository : IterableRelyingPartyRegistrationRepository { private val metadata: AssertingPartyMetadataRepository = OpenSaml5AssertingPartyMetadataRepository.fromTrustedMetadataLocation( "https://idp.example.org/metadata").build() fun findByRegistrationId(registrationId:String?): RelyingPartyRegistration { val metadata = this.metadata.findByEntityId(registrationId) if (metadata == null) { return null } return applyRelyingParty(metadata) } fun iterator(): Iterator<RelyingPartyRegistration> { return StreamSupport.stream(this.metadata.spliterator(), false) .map(this::applyRelyingParty).iterator() } private fun applyRelyingParty(metadata: AssertingPartyMetadata): RelyingPartyRegistration { val details: AssertingPartyMetadata = metadata as AssertingPartyMetadata return RelyingPartyRegistration.withAssertingPartyMetadata(details) // apply any relying party configuration .build() } } ``` -------------------------------- ### OAuth2 Client Configuration Options (Java/Kotlin) Source: https://github.com/spring-projects/spring-security/blob/main/docs/modules/ROOT/pages/reactive/oauth2/client/index.adoc Complete configuration options for the ServerHttpSecurity.oauth2Client() DSL in both Java and Kotlin. The Java example uses a SecurityWebFilterChain bean, while the Kotlin example uses the equivalent DSL syntax. ```java @Configuration @EnableWebFluxSecurity public class OAuth2ClientSecurityConfig { @Bean public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http) { http .oauth2Client((oauth2) -> oauth2 .clientRegistrationRepository(this.clientRegistrationRepository()) .authorizedClientRepository(this.authorizedClientRepository()) .authorizationRequestRepository(this.authorizationRequestRepository()) .authorizationRequestResolver(this.authorizationRequestResolver()) .authenticationConverter(this.authenticationConverter()) .authenticationManager(this.authenticationManager()) ); return http.build(); } } ``` ```kotlin @Configuration @EnableWebFluxSecurity class OAuth2ClientSecurityConfig { @Bean fun securityFilterChain(http: ServerHttpSecurity): SecurityWebFilterChain { http { oauth2Client { clientRegistrationRepository = clientRegistrationRepository() authorizedClientRepository = authorizedClientRepository() authorizationRequestRepository = authorizedRequestRepository() authorizationRequestResolver = authorizationRequestResolver() authenticationConverter = authenticationConverter() authenticationManager = authenticationManager() } } return http.build() } } ``` -------------------------------- ### Example Successful Registration Response Source: https://github.com/spring-projects/spring-security/blob/main/docs/modules/ROOT/pages/servlet/authentication/passkeys.adoc Successful registration response indicating the credential was registered. ```http HTTP/1.1 200 OK { "success": true } ``` -------------------------------- ### Old @Secured-only configuration Source: https://github.com/spring-projects/spring-security/blob/main/docs/modules/ROOT/pages/servlet/authorization/method-security.adoc Old configuration that enables only @Secured; used as the 'before' migration example. ```java @EnableGlobalMethodSecurity(securedEnabled = true) ``` ```kotlin @EnableGlobalMethodSecurity(securedEnabled = true) ``` ```xml <global-method-security secured-enabled="true"/> ``` -------------------------------- ### Create Kerberos database with kdb5_util Source: https://github.com/spring-projects/spring-security/blob/main/docs/modules/ROOT/pages/servlet/authentication/kerberos/appendix.adoc Initializes the Kerberos database for the EXAMPLE.ORG realm. Prompts for the master password, which must not be forgotten. ```text # kdb5_util create -s -r EXAMPLE.ORG Loading random data Initializing database '/var/lib/krb5kdc/principal' for realm 'EXAMPLE.ORG', master key name 'K/M@EXAMPLE.ORG' You will be prompted for the database Master Password. It is important that you NOT FORGET this password. Enter KDC database master key: Re-enter KDC database master key to verify: ``` -------------------------------- ### Configure JWT Bearer authorized client manager Source: https://github.com/spring-projects/spring-security/blob/main/docs/modules/ROOT/pages/reactive/oauth2/client/authorization-grants.adoc Configures a DefaultReactiveOAuth2AuthorizedClientManager with a JwtBearerReactiveOAuth2AuthorizedClientProvider. The Java example is partial, showing only the manager setup; the Kotlin example is a complete @Bean method. ```java DefaultReactiveOAuth2AuthorizedClientManager authorizedClientManager = new DefaultReactiveOAuth2AuthorizedClientManager( clientRegistrationRepository, authorizedClientRepository); authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider); return authorizedClientManager; } ``` ```kotlin @Bean fun authorizedClientManager( clientRegistrationRepository: ReactiveClientRegistrationRepository, authorizedClientRepository: ServerOAuth2AuthorizedClientRepository): ReactiveOAuth2AuthorizedClientManager { val jwtBearerAuthorizedClientProvider = JwtBearerReactiveOAuth2AuthorizedClientProvider() val authorizedClientProvider = ReactiveOAuth2AuthorizedClientProviderBuilder.builder() .provider(jwtBearerAuthorizedClientProvider) .build() val authorizedClientManager = DefaultReactiveOAuth2AuthorizedClientManager( clientRegistrationRepository, authorizedClientRepository) authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider) return authorizedClientManager } ``` -------------------------------- ### Run sec-server-client-auth Sample Source: https://github.com/spring-projects/spring-security/blob/main/docs/modules/ROOT/pages/servlet/authentication/kerberos/samples.adoc Command to run the server-side auth sample. ```text $ java -jar sec-server-client-auth-{spring-security-version}.jar ``` -------------------------------- ### Configure opaque token authorities Source: https://github.com/spring-projects/spring-security/blob/main/docs/modules/ROOT/pages/reactive/test/web/oauth2.adoc Java and Kotlin examples for configuring custom authorities on the opaque token using the authorities() method. ```java client .mutateWith(mockOpaqueToken() .authorities(new SimpleGrantedAuthority("SCOPE_message:read")) ) .get().uri("/endpoint").exchange(); ``` ```kotlin client .mutateWith(mockOpaqueToken() .authorities(SimpleGrantedAuthority("SCOPE_message:read")) ) .get().uri("/endpoint").exchange() ``` -------------------------------- ### InMemoryUserDetailsManager with User.withDefaultPasswordEncoder Source: https://github.com/spring-projects/spring-security/blob/main/docs/modules/ROOT/pages/servlet/authentication/passwords/in-memory.adoc Use User.withDefaultPasswordEncoder to encode passwords before storing in memory. This is only for getting started and not for production because the password can be obtained by decompiling the source code. ```java @Bean public UserDetailsService users() { // The builder will ensure the passwords are encoded before saving in memory UserBuilder users = User.withDefaultPasswordEncoder(); UserDetails user = users .username("user") .password("password") .roles("USER") .build(); UserDetails admin = users .username("admin") .password("password") .roles("USER", "ADMIN") .build(); return new InMemoryUserDetailsManager(user, admin); } ``` ```kotlin @Bean fun users(): UserDetailsService { // The builder will ensure the passwords are encoded before saving in memory val users = User.withDefaultPasswordEncoder() val user = users .username("user") .password("password") .roles("USER") .build() val admin = users .username("admin") .password("password") .roles("USER", "ADMIN") .build() return InMemoryUserDetailsManager(user, admin) } ``` -------------------------------- ### Run sec-server-win-auth Sample Source: https://github.com/spring-projects/spring-security/blob/main/docs/modules/ROOT/pages/servlet/authentication/kerberos/samples.adoc Command to run the Windows Auth sample server. May require custom Kerberos config on Linux via -Djava.security.krb5.conf or GlobalSunJaasKerberosConfig bean. ```text $ java -jar sec-server-win-auth-{spring-security-version}.jar ``` -------------------------------- ### Run client with keytab (user2) Source: https://github.com/spring-projects/spring-security/blob/main/docs/modules/ROOT/pages/servlet/authentication/kerberos/samples.adoc Runs the client with the default configuration, using the keytab file for user2. ```text $ java -jar sec-client-rest-template-{spring-security-version}.jar ``` -------------------------------- ### Async thread example with response commit Source: https://github.com/spring-projects/spring-security/blob/main/docs/modules/ROOT/pages/servlet/integrations/servlet-api.adoc Illustrates a potential issue in an asynchronous environment: prior to Spring Security 3.2, the SecurityContext was saved when the response was committed, which can cause problems. This example starts an async request and spawns a thread that sleeps then flushes the response. ```java httpServletRequest.startAsync(); new Thread("AsyncThread") { @Override public void run() { try { // Do work TimeUnit.SECONDS.sleep(1); // Write to and commit the httpServletResponse httpServletResponse.getOutputStream().flush(); } catch (Exception ex) { ex.printStackTrace(); } } }.start(); ``` -------------------------------- ### Run sec-server-spnego-form-auth Sample Source: https://github.com/spring-projects/spring-security/blob/main/docs/modules/ROOT/pages/servlet/authentication/kerberos/samples.adoc Command to run the SPNEGO and form auth sample server. ```text $ java -jar sec-server-spnego-form-auth-{spring-security-version}.jar ``` -------------------------------- ### Send credentials in RSocket request metadata Source: https://github.com/spring-projects/spring-security/blob/main/docs/modules/ROOT/pages/reactive/integrations/rsocket.adoc Sends username and password in a request metadata instead of (or in addition to) the setup. The example shows a method that attaches credentials to a route and retrieves an AirportLocation. ```java Mono<RSocketRequester> requester; UsernamePasswordMetadata credentials = new UsernamePasswordMetadata("user", "password"); public Mono<AirportLocation> findRadar(String code) { return this.requester.flatMap(req -> req.route("find.radar.{code}", code) .metadata(credentials, authenticationMimeType) .retrieveMono(AirportLocation.class) ); } ``` ```kotlin import org.springframework.messaging.rsocket.retrieveMono // ... var requester: Mono<RSocketRequester>? = null var credentials = UsernamePasswordMetadata("user", "password") open fun findRadar(code: String): Mono<AirportLocation> { return requester!!.flatMap { req -> req.route("find.radar.{code}", code) .metadata(credentials, authenticationMimeType) .retrieveMono<AirportLocation>() } } ``` -------------------------------- ### <user-service> {noop} XML Configuration Source: https://github.com/spring-projects/spring-security/blob/main/docs/modules/ROOT/pages/servlet/authentication/passwords/in-memory.adoc XML configuration for demos or getting started that prefixes passwords with {noop} to indicate no encoding should be used. There is no simple way to use User.withDefaultPasswordEncoder with XML-based configuration. ```xml <user-service> <user name="user" password="{noop}password" authorities="ROLE_USER" /> <user name="admin" password="{noop}password" authorities="ROLE_USER,ROLE_ADMIN" /> </user-service> ``` -------------------------------- ### Boot application with ObservationRegistryCustomizer Source: https://github.com/spring-projects/spring-security/blob/main/docs/modules/ROOT/pages/reactive/integrations/observability.adoc Boot application that configures a reactive user details service and an ObservationRegistryCustomizer to add an ObservationTextPublisher handler. The Java and Kotlin versions are equivalent and are shown as tabs in the source. ```java @SpringBootApplication public class MyApplication { @Bean public ReactiveUserDetailsService userDetailsService() { return new MapReactiveUserDetailsManager( User.withDefaultPasswordEncoder() .username("user") .password("password") .authorities("app") .build() ); } @Bean ObservationRegistryCustomizer<ObservationRegistry> addTextHandler() { return (registry) -> registry.observationConfig().observationHandler(new ObservationTextPublisher()); } public static void main(String[] args) { SpringApplication.run(ListenerSamplesApplication.class, args); } } ``` ```kotlin @SpringBootApplication class MyApplication { @Bean fun userDetailsService(): ReactiveUserDetailsService { MapReactiveUserDetailsManager( User.withDefaultPasswordEncoder() .username("user") .password("password") .authorities("app") .build() ); } @Bean fun addTextHandler(): ObservationRegistryCustomizer<ObservationRegistry> { return registry: ObservationRegistry -> registry.observationConfig() .observationHandler(ObservationTextPublisher()); } fun main(args: Array<String>) { runApplication<MyApplication>(*args) } } ``` -------------------------------- ### Access SecurityContext in Kotlin Source: https://github.com/spring-projects/spring-security/blob/main/docs/modules/ROOT/pages/servlet/authentication/architecture.adoc Kotlin example showing how to access the current SecurityContext and its Authentication details, including the username, principal, and authorities. ```kotlin val context = SecurityContextHolder.getContext() val authentication = context.authentication val username = authentication.name val principal = authentication.principal val authorities = authentication.authorities ``` -------------------------------- ### Add OAuth2 Resource Server Starter with Maven Source: https://github.com/spring-projects/spring-security/blob/main/docs/modules/ROOT/pages/reactive/oauth2/index.adoc Adds the Spring Boot starter for OAuth2 Resource Server using Maven. Required to get started with OAuth2 Resource Server in a Spring Boot project. ```maven <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-oauth2-resource-server</artifactId> </dependency> ``` -------------------------------- ### Windows Auth Sample Configuration (application.yml) Source: https://github.com/spring-projects/spring-security/blob/main/docs/modules/ROOT/pages/servlet/authentication/kerberos/samples.adoc Default YAML configuration for the sec-server-win-auth sample. Override these settings using Spring Boot command-line options or a custom application.yml file. ```yaml server: port: 8080 app: ad-domain: EXAMPLE.ORG ad-server: ldap://WIN-EKBO0EQ7TS7.example.org/ service-principal: HTTP/neo.example.org@EXAMPLE.ORG keytab-location: /tmp/tomcat.keytab ldap-search-base: dc=example,dc=org ldap-search-filter: "(| (userPrincipalName={0}) (sAMAccountName={0}))" ``` -------------------------------- ### Build Spring Security project Source: https://github.com/spring-projects/spring-security/blob/main/README.adoc Compiles and tests the project, building all JARs, distribution zips, and docs. The reference docs are not included in the distribution zip. ```bash ./gradlew build ``` -------------------------------- ### Add OAuth2 Resource Server Starter with Gradle Source: https://github.com/spring-projects/spring-security/blob/main/docs/modules/ROOT/pages/reactive/oauth2/index.adoc Adds the Spring Boot starter for OAuth2 Resource Server using Gradle. Required to get started with OAuth2 Resource Server in a Spring Boot project. ```gradle implementation 'org.springframework.boot:spring-boot-starter-oauth2-resource-server' ``` -------------------------------- ### Boot application with ObservationTextPublisher Source: https://github.com/spring-projects/spring-security/blob/main/docs/modules/ROOT/pages/servlet/integrations/observability.adoc Boot application that configures an in-memory user and adds an ObservationTextPublisher handler to print observation events. The Java and Kotlin versions are equivalent and shown as tabs. ```java @SpringBootApplication public class MyApplication { @Bean public UserDetailsService userDetailsService() { return new InMemoryUserDetailsManager( User.withDefaultPasswordEncoder() .username("user") .password("password") .authorities("app") .build() ); } @Bean ObservationRegistryCustomizer<ObservationRegistry> addTextHandler() { return (registry) -> registry.observationConfig().observationHandler(new ObservationTextPublisher()); } public static void main(String[] args) { SpringApplication.run(ListenerSamplesApplication.class, args); } } ``` ```kotlin @SpringBootApplication class MyApplication { @Bean fun userDetailsService(): UserDetailsService { InMemoryUserDetailsManager( User.withDefaultPasswordEncoder() .username("user") .password("password") .authorities("app") .build() ); } @Bean fun addTextHandler(): ObservationRegistryCustomizer<ObservationRegistry> { return registry: ObservationRegistry -> registry.observationConfig() .observationHandler(ObservationTextPublisher()); } fun main(args: Array<String>) { runApplication<MyApplication>(*args) } } ``` -------------------------------- ### Provide CorsConfigurationSource bean Source: https://github.com/spring-projects/spring-security/blob/main/docs/modules/ROOT/pages/servlet/integrations/cors.adoc Provides a CorsConfigurationSource bean to integrate CORS with Spring Security. Spring Security automatically configures CORS only if a UrlBasedCorsConfigurationSource instance is present. The example allows origins from https://example.com and methods GET and POST. ```java @Bean UrlBasedCorsConfigurationSource corsConfigurationSource() { CorsConfiguration configuration = new CorsConfiguration(); configuration.setAllowedOrigins(Arrays.asList("https://example.com")); configuration.setAllowedMethods(Arrays.asList("GET","POST")); UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); source.registerCorsConfiguration("/**", configuration); return source; } ``` ```kotlin @Bean fun corsConfigurationSource(): UrlBasedCorsConfigurationSource { val configuration = CorsConfiguration() configuration.allowedOrigins = listOf("https://example.com") configuration.allowedMethods = listOf("GET", "POST") val source = UrlBasedCorsConfigurationSource() source.registerCorsConfiguration("/**", configuration) return source } ``` -------------------------------- ### Simple Username/Password Example (Kotlin) Source: https://github.com/spring-projects/spring-security/blob/main/docs/modules/ROOT/pages/servlet/authentication/passwords/index.adoc Kotlin configuration for username/password authentication using formLogin and httpBasic, with an in-memory user created via User.withDefaultPasswordEncoder(). The user has username 'user', password 'password', and role 'USER'. ```kotlin import org.springframework.security.config.annotation.web.invoke @Configuration @EnableWebSecurity class SecurityConfig { @Bean fun securityFilterChain(http: HttpSecurity): SecurityFilterChain { http { authorizeHttpRequests { authorize(anyRequest, authenticated) } formLogin { } httpBasic { } } return http.build() } @Bean fun userDetailsService(): UserDetailsService { val user = User.withDefaultPasswordEncoder() .username("user") .password("password") .roles("USER") .build() return InMemoryUserDetailsManager(user) } } ``` -------------------------------- ### Using WebClient to Invoke Downstream Service with Bearer Token Source: https://github.com/spring-projects/spring-security/blob/main/docs/modules/ROOT/pages/reactive/oauth2/resource-server/bearer-tokens.adoc Example of using the configured WebClient to make a GET request to a downstream service. The bearer token is automatically added to the Authorization header. Java and Kotlin variants are provided. ```java this.rest.get() .uri("https://other-service.example.com/endpoint") .retrieve() .bodyToMono(String.class) ``` ```kotlin this.rest.get() .uri("https://other-service.example.com/endpoint") .retrieve() .bodyToMono<String>() ``` -------------------------------- ### Create admin principal with kadmin.local Source: https://github.com/spring-projects/spring-security/blob/main/docs/modules/ROOT/pages/servlet/authentication/kerberos/appendix.adoc Uses kadmin.local to list existing principals and add the root/admin principal. This is required before kadmin can be used. ```text root@neo:/etc/krb5kdc# kadmin.local Authenticating as principal root/admin@EXAMPLE.ORG with password. kadmin.local: listprincs K/M@EXAMPLE.ORG kadmin/admin@EXAMPLE.ORG kadmin/changepw@EXAMPLE.ORG kadmin/cypher@EXAMPLE.ORG krbtgt/EXAMPLE.ORG@EXAMPLE.ORG kadmin.local: addprinc root/admin@EXAMPLE.ORG WARNING: no policy specified for root/admin@EXAMPLE.ORG; defaulting to no policy Enter password for principal "root/admin@EXAMPLE.ORG": Re-enter password for principal "root/admin@EXAMPLE.ORG": Principal "root/admin@EXAMPLE.ORG" created. ``` -------------------------------- ### Multiple SecurityWebFilterChain Configuration (Java) Source: https://github.com/spring-projects/spring-security/blob/main/docs/modules/ROOT/pages/reactive/configuration/webflux.adoc Shows how to configure multiple SecurityWebFilterChain instances to separate configuration by RequestMatcher. This example isolates configuration for URLs starting with `/api` using a PathPatternParserServerWebExchangeMatcher and OAuth2 resource server with JWT. The `@Order(Ordered.HIGHEST_PRECEDENCE)` annotation sets the precedence. ```java @Configuration @EnableWebFluxSecurity static class MultiSecurityHttpConfig { @Order(Ordered.HIGHEST_PRECEDENCE) <1> @Bean SecurityWebFilterChain apiHttpSecurity(ServerHttpSecurity http) { http .securityMatcher(new PathPatternParserServerWebExchangeMatcher("/api/**")) <2> .authorizeExchange((authorize) -> authorize .anyExchange().authenticated() ) .oauth2ResourceServer(OAuth2ResourceServerSpec::jwt); <3> return http.build(); } } ``` -------------------------------- ### kinit with keytab and klist verification Source: https://github.com/spring-projects/spring-security/blob/main/docs/modules/ROOT/pages/servlet/authentication/kerberos/appendix.adoc Uses the custom krb5.ini and the exported keytab to obtain initial credentials with kinit, then verifies with klist. The output shows a valid ticket for the HTTP principal. ```text $ env KRB5_CONFIG=/path/to/krb5.ini kinit -kt tomcat.keytab HTTP/neo.example.org@EXAMPLE.ORG $ klist Ticket cache: FILE:/tmp/krb5cc_1000 Default principal: HTTP/neo.example.org@EXAMPLE.ORG Valid starting Expires Service principal 26/03/15 09:04:37 26/03/15 19:04:37 krbtgt/EXAMPLE.ORG@EXAMPLE.ORG renew until 27/03/15 09:04:37 ``` -------------------------------- ### Initialize OpenSamlInitializationService in Kotlin Source: https://github.com/spring-projects/spring-security/blob/main/docs/modules/ROOT/pages/servlet/saml2/login/overview.adoc Kotlin equivalent of statically initializing OpenSamlInitializationService using a companion object's init block. ```kotlin companion object { init { OpenSamlInitializationService.initialize() } } ``` -------------------------------- ### HTTP Basic Authentication with httpBasic RequestPostProcessor Source: https://github.com/spring-projects/spring-security/blob/main/docs/modules/ROOT/pages/servlet/test/mockmvc/http-basic.adoc Use Spring Security's httpBasic RequestPostProcessor to add the Authorization header for HTTP Basic authentication in MockMvc tests. The Java example uses perform(get("/").with(httpBasic("user","password"))), while the Kotlin example uses mvc.get("/") { with(httpBasic("user","password")) }. Both authenticate with username "user" and password "password". ```java mvc .perform(get("/").with(httpBasic("user","password"))) ``` ```kotlin mvc.get("/") { with(httpBasic("user","password")) } ``` -------------------------------- ### Test Reactive Method Security with @WithMockUser Source: https://github.com/spring-projects/spring-security/blob/main/docs/modules/ROOT/pages/reactive/test/method.adoc Test method security in a reactive WebFlux application using the same setup and annotations as the servlet testing example. The test class uses @ExtendWith(SpringExtension.class) and @ContextConfiguration to load HelloWebfluxMethodApplication, then verifies that unauthenticated and user-authenticated calls are denied with AccessDeniedException, while an ADMIN role receives the expected message. ```java @ExtendWith(SpringExtension.class) @ContextConfiguration(classes = HelloWebfluxMethodApplication.class) public class HelloWorldMessageServiceTests { @Autowired HelloWorldMessageService messages; @Test public void messagesWhenNotAuthenticatedThenDenied() { StepVerifier.create(this.messages.findMessage()) .expectError(AccessDeniedException.class) .verify(); } @Test @WithMockUser public void messagesWhenUserThenDenied() { StepVerifier.create(this.messages.findMessage()) .expectError(AccessDeniedException.class) .verify(); } @Test @WithMockUser(roles = "ADMIN") public void messagesWhenAdminThenOk() { StepVerifier.create(this.messages.findMessage()) .expectNext("Hello World!") .verifyComplete(); } } ``` ```kotlin @ExtendWith(SpringExtension.class) @ContextConfiguration(classes = [HelloWebfluxMethodApplication::class]) class HelloWorldMessageServiceTests { @Autowired lateinit var messages: HelloWorldMessageService @Test fun messagesWhenNotAuthenticatedThenDenied() { StepVerifier.create(messages.findMessage()) .expectError(AccessDeniedException::class.java) .verify() } @Test @WithMockUser fun messagesWhenUserThenDenied() { StepVerifier.create(messages.findMessage()) .expectError(AccessDeniedException::class.java) .verify() } @Test @WithMockUser(roles = ["ADMIN"]) fun messagesWhenAdminThenOk() { StepVerifier.create(messages.findMessage()) .expectNext("Hello World!") .verifyComplete() } } ``` -------------------------------- ### Active Directory Authentication Provider Configuration (Java) Source: https://github.com/spring-projects/spring-security/blob/main/docs/modules/ROOT/pages/servlet/authentication/passwords/ldap.adoc Java configuration for ActiveDirectoryLdapAuthenticationProvider with domain 'example.com' and LDAP URL 'ldap://company.example.com/'. ```java @Bean ActiveDirectoryLdapAuthenticationProvider authenticationProvider() { return new ActiveDirectoryLdapAuthenticationProvider("example.com", "ldap://company.example.com/"); } ``` -------------------------------- ### Custom security header example Source: https://github.com/spring-projects/spring-security/blob/main/docs/modules/ROOT/pages/servlet/exploits/headers.adoc Example custom security header to be added to responses. ```http X-Custom-Security-Header: header-value ``` -------------------------------- ### ktpass export keytab for HTTP/neo.example.org Source: https://github.com/spring-projects/spring-security/blob/main/docs/modules/ROOT/pages/servlet/authentication/kerberos/appendix.adoc Exports a keytab file for the HTTP/neo.example.org principal and maps it to the tomcat user. The output confirms successful mapping to the domain controller. ```text PS C:\> ktpass /out c:\tomcat.keytab /mapuser tomcat@EXAMPLE.ORG /princ HTTP/neo.example.org@EXAMPLE.ORG /pass Password# /ptype KRB5_NT_PRINCIPAL /crypto All Targeting domain controller: WIN-EKBO0EQ7TS7.example.org Using legacy password setting method Successfully mapped HTTP/neo.example.org to tomcat. ``` -------------------------------- ### Disable GET request conversion in Saml2AuthenticationTokenConverter bean Source: https://github.com/spring-projects/spring-security/blob/main/docs/modules/ROOT/pages/migration/servlet/saml2.adoc Defines a bean for a Saml2AuthenticationTokenConverter that disables GET request conversion. The bean is created with a RelyingPartyRegistrationRepository and calls setShouldConvertGetRequests(false). To continue processing GET requests, set this property to true. ```kotlin @Bean fun authenticationConverter(val registrations: RelyingPartyRegistrationRepository): Saml2AuthenticationTokenConverter { val authenticationConverter = Saml2AuthenticationTokenConverter(registrations) authenticationConverter.setShouldConvertGetRequests(false) return authenticationConverter } ``` -------------------------------- ### Allow Only GET & POST with StrictHttpFirewall Source: https://github.com/spring-projects/spring-security/blob/main/docs/modules/ROOT/pages/servlet/exploits/firewall.adoc Restricts allowed HTTP methods to GET and POST by setting allowedHttpMethods on a StrictHttpFirewall bean. The default valid methods are DELETE, GET, HEAD, OPTIONS, PATCH, POST, and PUT. Shown in Java, XML, and Kotlin. ```java @Bean public StrictHttpFirewall httpFirewall() { StrictHttpFirewall firewall = new StrictHttpFirewall(); firewall.setAllowedHttpMethods(Arrays.asList("GET", "POST")); return firewall; } ``` ```xml <b:bean id="httpFirewall" class="org.springframework.security.web.firewall.StrictHttpFirewall" p:allowedHttpMethods="GET,POST"/> <http-firewall ref="httpFirewall"/> ``` ```kotlin @Bean fun httpFirewall(): StrictHttpFirewall { val firewall = StrictHttpFirewall() firewall.setAllowedHttpMethods(listOf("GET", "POST")) return firewall } ``` -------------------------------- ### Build Spring Security reference docs Source: https://github.com/spring-projects/spring-security/blob/main/README.adoc Builds the reference docs for the current branch. Publishes the docs site to the _docs/build/site_ directory. ```bash ./gradlew :spring-security-docs:antora ``` -------------------------------- ### Permissions-Policy Example Source: https://github.com/spring-projects/spring-security/blob/main/docs/modules/ROOT/pages/reactive/exploits/headers.adoc Example of a Permissions-Policy header that allows geolocation only for the same origin. This header is not added by default; you must configure it explicitly. ```http Permissions-Policy: geolocation=(self) ``` -------------------------------- ### Navigate to hooks folder Source: https://github.com/spring-projects/spring-security/wiki/Working-with-Git-branches Navigates to the hooks folder found in step 2, where the pre-push hook will be set up. ```bash cd spring-security/.git-hooks ``` -------------------------------- ### Simple Username/Password Example (XML) Source: https://github.com/spring-projects/spring-security/blob/main/docs/modules/ROOT/pages/servlet/authentication/passwords/index.adoc XML configuration for username/password authentication using form-login, http-basic, and an in-memory user with a {noop} password encoder. The user is defined with name 'user', password 'password', and authority 'ROLE_USER'. ```xml <http> <intercept-url pattern="/**" access="authenticated"/> <form-login /> <http-basic /> <user-service> <user name="user" password="{noop}password" authorities="ROLE_USER" /> </user-service> </http> ``` -------------------------------- ### Disable All HTTP Security Headers Source: https://github.com/spring-projects/spring-security/blob/main/docs/modules/ROOT/pages/servlet/exploits/headers.adoc Configure Spring Security to disable all HTTP security response headers. The Java example uses headers.disable(). The XML example uses <headers disabled="true" />. The Kotlin example uses headers { disable() }. ```java @Configuration @EnableWebSecurity public class WebSecurityConfig { @Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { http // ... .headers((headers) -> headers.disable()); return http.build(); } } ``` ```xml <http> <!-- ... --> <headers disabled="true" /> </http> ``` ```kotlin @Configuration @EnableWebSecurity class SecurityConfig { @Bean open fun filterChain(http: HttpSecurity): SecurityFilterChain { http { // ... headers { disable() } } return http.build() } } ``` -------------------------------- ### Add OAuth2 Client Starter with Spring Boot (Gradle) Source: https://github.com/spring-projects/spring-security/blob/main/docs/modules/ROOT/pages/reactive/oauth2/index.adoc Adds the spring-boot-starter-oauth2-client dependency using Gradle. This is the primary build tool example. ```gradle implementation 'org.springframework.boot:spring-boot-starter-oauth2-client' ``` -------------------------------- ### Clear-Site-Data Example Source: https://github.com/spring-projects/spring-security/blob/main/docs/modules/ROOT/pages/reactive/exploits/headers.adoc Example of a Clear-Site-Data header that instructs the browser to clear cache and cookies. This header is not added by default; you must configure it explicitly. ```http Clear-Site-Data: "cache", "cookies" ``` -------------------------------- ### Allow Only GET & POST with StrictServerWebExchangeFirewall Source: https://github.com/spring-projects/spring-security/blob/main/docs/modules/ROOT/pages/reactive/exploits/firewall.adoc Restricts allowed HTTP methods to GET and POST by configuring a StrictServerWebExchangeFirewall bean. The default allowed methods are DELETE, GET, HEAD, OPTIONS, PATCH, POST, and PUT. This helps protect against Cross Site Tracing (XST) and HTTP Verb Tampering. ```java @Bean public StrictServerWebExchangeFirewall httpFirewall() { StrictServerWebExchangeFirewall firewall = new StrictServerWebExchangeFirewall(); firewall.setAllowedHttpMethods(Arrays.asList("GET", "POST")); return firewall; } ``` ```kotlin @Bean fun httpFirewall(): StrictServerWebExchangeFirewall { val firewall = StrictServerWebExchangeFirewall() firewall.setAllowedHttpMethods(listOf("GET", "POST")) return firewall } ``` -------------------------------- ### Default application configuration (YAML) Source: https://github.com/spring-projects/spring-security/blob/main/docs/modules/ROOT/pages/servlet/authentication/kerberos/samples.adoc Default configuration for the Kerberos client example. Sets the user principal, keytab location, and access URL. ```yaml app: user-principal: user2@EXAMPLE.ORG keytab-location: /tmp/user2.keytab access-url: https://neo.example.org:8080/hello ``` -------------------------------- ### Send credentials in RSocket setup metadata Source: https://github.com/spring-projects/spring-security/blob/main/docs/modules/ROOT/pages/reactive/integrations/rsocket.adoc Sends username and password to the receiver in the setup metadata using the authentication MIME type and the configured RSocketStrategies. ```java MimeType authenticationMimeType = MimeTypeUtils.parseMimeType(WellKnownMimeType.MESSAGE_RSOCKET_AUTHENTICATION.getString()); UsernamePasswordMetadata credentials = new UsernamePasswordMetadata("user", "password"); Mono<RSocketRequester> requester = RSocketRequester.builder() .setupMetadata(credentials, authenticationMimeType) .rsocketStrategies(strategies.build()) .connectTcp(host, port); ``` ```kotlin val authenticationMimeType: MimeType = MimeTypeUtils.parseMimeType(WellKnownMimeType.MESSAGE_RSOCKET_AUTHENTICATION.string) val credentials = UsernamePasswordMetadata("user", "password") val requester: Mono<RSocketRequester> = RSocketRequester.builder() .setupMetadata(credentials, authenticationMimeType) .rsocketStrategies(strategies.build()) .connectTcp(host, port) ``` -------------------------------- ### Configure OpenSaml5AuthenticationTokenConverter to not process GET requests (Java) Source: https://github.com/spring-projects/spring-security/blob/main/docs/modules/ROOT/pages/migration/servlet/saml2.adoc Publish an OpenSaml5AuthenticationTokenConverter bean with setShouldConvertGetRequests(false) to prepare for Spring Security 8, which will not process GET requests by default. ```java @Bean OpenSaml5AuthenticationTokenConverter authenticationConverter(RelyingPartyRegistrationRepository registrations) { OpenSaml5AuthenticationTokenConverter authenticationConverter = new OpenSaml5AuthenticationTokenConverter(registrations); authenticationConverter.setShouldConvertGetRequests(false); return authenticationConverter; } ``` -------------------------------- ### Client Auth Sample Configuration (application.yml) Source: https://github.com/spring-projects/spring-security/blob/main/docs/modules/ROOT/pages/servlet/authentication/kerberos/samples.adoc YAML configuration for the sec-server-client-auth sample, setting the server port to 8080. ```yaml server: port: 8080 ``` -------------------------------- ### Add OAuth2 Client Starter with Spring Boot (Maven) Source: https://github.com/spring-projects/spring-security/blob/main/docs/modules/ROOT/pages/reactive/oauth2/index.adoc Adds the spring-boot-starter-oauth2-client dependency using Maven. This is the secondary build tool example. ```maven <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-oauth2-client</artifactId> </dependency> ``` -------------------------------- ### Create service principal for Tomcat and export keytab Source: https://github.com/spring-projects/spring-security/blob/main/docs/modules/ROOT/pages/servlet/authentication/kerberos/appendix.adoc Creates a service principal HTTP/neo.example.org@EXAMPLE.ORG with a random key and exports its keytab to /tmp/tomcat.keytab. The output shows the encryption types added. ```text kadmin: addprinc -randkey HTTP/neo.example.org@EXAMPLE.ORG WARNING: no policy specified for HTTP/neo.example.org@EXAMPLE.ORG; defaulting to no policy Principal "HTTP/neo.example.org@EXAMPLE.ORG" created. kadmin: ktadd -k /tmp/tomcat.keytab HTTP/neo.example.org@EXAMPLE.ORG Entry for principal HTTP/neo.example.org@EXAMPLE.ORG with kvno 2, encryption type aes256-cts-hmac-sha1-96 added to keytab WRFILE:/tmp/tomcat2.keytab. Entry for principal HTTP/neo.example.org@EXAMPLE.ORG with kvno 2, encryption type arcfour-hmac added to keytab WRFILE:/tmp/tomcat2.keytab. Entry for principal HTTP/neo.example.org@EXAMPLE.ORG with kvno 2, encryption type des3-cbc-sha1 added to keytab WRFILE:/tmp/tomcat2.keytab. Entry for principal HTTP/neo.example.org@EXAMPLE.ORG with kvno 2, encryption type des-cbc-crc added to keytab WRFILE:/tmp/tomcat2.keytab. ``` -------------------------------- ### DelegatingPasswordEncoder Encoded Passwords Example Source: https://github.com/spring-projects/spring-security/blob/main/docs/modules/ROOT/pages/features/authentication/password-storage.adoc Example of passwords encoded with different ids, all with original password 'password'. Each id delegates to a specific PasswordEncoder: bcrypt, noop, pbkdf2, scrypt, sha256. ```text {bcrypt}$2a$10$dXJ3SW6G7P50lGmMkkmwe.20cQQubK3.HZWzG3YB1tlRy.fqvM/BG // <1> {noop}password // <2> {pbkdf2}5d923b44a6d129f3ddf3e3c8d29412723dcbde72445e8ef6bf3b508fbf17fa4ed4d6b99ca763d8dc // <3> {scrypt}$e0801$8bWJaSu2IKSn9Z9kM+TPXfOc/9bdYSrN1oD9qfVThWEwdRTnO7re7Ei+fUZRJ68k9lTyuTeUp4of4g24hHnazw==$OAOec05+bXxvuu/1qZ6NUR+xQYvYv7BeL1QxwRpY5Pc= // <4> {sha256}97cde38028ad898ebc02e690819fa220e88c62e0699403e94fff291cfffaf8410849f27605abcbc0 // <5> ``` -------------------------------- ### SPNEGO and Form Auth Sample Configuration (application.yml) Source: https://github.com/spring-projects/spring-security/blob/main/docs/modules/ROOT/pages/servlet/authentication/kerberos/samples.adoc YAML configuration for the sec-server-spnego-form-auth sample, setting the server port and Kerberos service principal and keytab location. ```yaml server: port: 8080 app: service-principal: HTTP/neo.example.org@EXAMPLE.ORG keytab-location: /tmp/tomcat.keytab ``` -------------------------------- ### Build documentation with Gradle asciidoctor Source: https://github.com/spring-projects/spring-security/blob/main/buildSrc/src/test/resources/samples/showcase/sgbcs-docs/src/docs/asciidoc/index.adoc Command to build the documentation using Gradle's asciidoctor task. ```shell $ ./gradlew asciidoctor ``` -------------------------------- ### Customize Cache Control Headers: Disable Defaults and Add Only Cache Control Source: https://github.com/spring-projects/spring-security/blob/main/docs/modules/ROOT/pages/servlet/exploits/headers.adoc Configure Spring Security to disable all default headers and explicitly add only the Cache Control header. The Java example uses defaultsDisabled() and cacheControl(withDefaults()). The XML example uses defaults-disabled="true" and <cache-control/>. The Kotlin example uses defaultsDisabled = true and cacheControl { }. ```java @Configuration @EnableWebSecurity public class WebSecurityConfig { @Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { http // ... .headers((headers) -> headers // do not use any default headers unless explicitly listed .defaultsDisabled() .cacheControl(withDefaults()) ); return http.build(); } } ``` ```xml <http> <!-- ... --> <headers defaults-disabled="true"> <cache-control/> </headers> </http> ``` ```kotlin @Configuration @EnableWebSecurity class SecurityConfig { @Bean open fun filterChain(http: HttpSecurity): SecurityFilterChain { http { // ... headers { // do not use any default headers unless explicitly listed defaultsDisabled = true cacheControl { } } } return http.build() } } ``` -------------------------------- ### AsyncContext.start(Runnable) to propagate SecurityContext Source: https://github.com/spring-projects/spring-security/blob/main/docs/modules/ROOT/pages/servlet/integrations/servlet-api.adoc Shows how to use AsyncContext.start(Runnable) to propagate the current SecurityContext to a new thread. The example outputs the current user's Authentication. Java and Kotlin variants are provided. ```java final AsyncContext async = httpServletRequest.startAsync(); async.start(new Runnable() { public void run() { Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); try { final HttpServletResponse asyncResponse = (HttpServletResponse) async.getResponse(); asyncResponse.setStatus(HttpServletResponse.SC_OK); asyncResponse.getWriter().write(String.valueOf(authentication)); async.complete(); } catch(Exception ex) { throw new RuntimeException(ex); } } }); ``` ```kotlin val async: AsyncContext = httpServletRequest.startAsync() async.start { val authentication: Authentication = SecurityContextHolder.getContext().authentication try { val asyncResponse = async.response as HttpServletResponse asyncResponse.status = HttpServletResponse.SC_OK asyncResponse.writer.write(String.valueOf(authentication)) async.complete() } catch (ex: Exception) { throw RuntimeException(ex) } } ``` -------------------------------- ### Propagate Bearer Token on Request Example Source: https://github.com/spring-projects/spring-security/blob/main/docs/modules/ROOT/pages/servlet/oauth2/resource-server/bearer-tokens.adoc Use the WebClient configured with ServletBearerExchangeFilterFunction to invoke the endpoint, automatically adding the bearer token Authorization header. The example shows the default propagation behavior. ```java this.rest.get() .uri("https://other-service.example.com/endpoint") .retrieve() .bodyToMono(String.class) .block() ``` ```kotlin this.rest.get() .uri("https://other-service.example.com/endpoint") .retrieve() .bodyToMono<String>() .block() ``` -------------------------------- ### Example Content Security Policy header Source: https://github.com/spring-projects/spring-security/blob/main/docs/modules/ROOT/pages/reactive/exploits/headers.adoc Example Content Security Policy (CSP) header value. It restricts script sources to self and trustedscripts.example.com, object sources to trustedplugins.example.com, and specifies a report-uri for violations. ```http Content-Security-Policy: script-src 'self' https://trustedscripts.example.com; object-src https://trustedplugins.example.com; report-uri /csp-report-endpoint/ ```