Compare commits
56 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 4f52b71be8 | |||
| 398430f672 | |||
| e54bb9f3f5 | |||
| aa21e62fb8 | |||
| b58187082a | |||
| fee6a9bb0e | |||
| e588a3528f | |||
| 334df75c39 | |||
| 11b601159d | |||
| 8521b7d5a6 | |||
| 00fbe052f4 | |||
| 5023cc7e4c | |||
| 3cd8dc5c44 | |||
| 97342f83fd | |||
| dfe062b390 | |||
| 703a81390e | |||
| 18c4c4c528 | |||
| 6d722edab1 | |||
| e712531555 | |||
| 100c07de98 | |||
| 279afe3e28 | |||
| b7b859cd9a | |||
| b83f682154 | |||
| aca1643284 | |||
| cf2114e36e | |||
| ecd17a9ee0 | |||
| ef5cdb50cc | |||
| b2e2d74cab | |||
| d3a55291bc | |||
| e584196c1d | |||
| 5baff27ffb | |||
| 39aaf25b60 | |||
| 8ecc4a9157 | |||
| af33ace82f | |||
| ddebff043d | |||
| 29c63bee69 | |||
| 944322932a | |||
| affa36b9bb | |||
| 9ff2d96088 | |||
| 644901fed5 | |||
| 09805317e6 | |||
| 4ab933803f | |||
| d2b1cb572f | |||
| d0166004aa | |||
| 9f96fbcda0 | |||
| ccffb48fd1 | |||
| d0fcdebe88 | |||
| f997e22d9d | |||
| ff908c4d7c | |||
| 521f533fc4 | |||
| 532d0bef14 | |||
| fed6df5167 | |||
| 4feeb0f843 | |||
| 8b0689cbb8 | |||
| 28e158d1cb | |||
| 82f87cf2b6 |
@@ -71,13 +71,6 @@ jobs:
|
||||
with:
|
||||
should-deploy-artifacts: ${{ needs.build.outputs.should-deploy-artifacts }}
|
||||
secrets: inherit
|
||||
deploy-docs:
|
||||
name: Deploy Docs
|
||||
needs: [ build, test, check-samples ]
|
||||
uses: spring-io/spring-security-release-tools/.github/workflows/deploy-docs.yml@v1
|
||||
with:
|
||||
should-deploy-docs: ${{ needs.build.outputs.should-deploy-artifacts }}
|
||||
secrets: inherit
|
||||
deploy-schema:
|
||||
name: Deploy Schema
|
||||
needs: [ build, test, check-samples ]
|
||||
@@ -87,7 +80,7 @@ jobs:
|
||||
secrets: inherit
|
||||
perform-release:
|
||||
name: Perform Release
|
||||
needs: [ deploy-artifacts, deploy-docs, deploy-schema ]
|
||||
needs: [ deploy-artifacts, deploy-schema ]
|
||||
uses: spring-io/spring-security-release-tools/.github/workflows/perform-release.yml@v1
|
||||
with:
|
||||
should-perform-release: ${{ needs.deploy-artifacts.outputs.artifacts-deployed }}
|
||||
|
||||
+1
-1
@@ -42,7 +42,7 @@ springRelease {
|
||||
weekOfMonth = 3
|
||||
dayOfWeek = 1
|
||||
referenceDocUrl = "https://docs.spring.io/spring-security/reference/{version}/index.html"
|
||||
apiDocUrl = "https://docs.spring.io/spring-security/site/docs/{version}/api/"
|
||||
apiDocUrl = "https://docs.spring.io/spring-security/reference/{version}/api/java/index.html"
|
||||
replaceSnapshotVersionInReferenceDocUrl = true
|
||||
}
|
||||
|
||||
|
||||
@@ -1,82 +0,0 @@
|
||||
/*
|
||||
* Copyright 2004-present the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License. You may obtain a copy of
|
||||
* the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package io.spring.gradle.convention
|
||||
|
||||
import org.gradle.api.plugins.JavaPlugin
|
||||
import org.gradle.api.tasks.bundling.Zip
|
||||
import org.gradle.api.Plugin
|
||||
import org.gradle.api.Project
|
||||
|
||||
public class DeployDocsPlugin implements Plugin<Project> {
|
||||
|
||||
@Override
|
||||
public void apply(Project project) {
|
||||
project.getPluginManager().apply('org.hidetake.ssh')
|
||||
|
||||
project.ssh.settings {
|
||||
knownHosts = allowAnyHosts
|
||||
}
|
||||
project.remotes {
|
||||
docs {
|
||||
role 'docs'
|
||||
if (project.hasProperty('deployDocsHost')) {
|
||||
host = project.findProperty('deployDocsHost')
|
||||
} else {
|
||||
host = 'docs.af.pivotal.io'
|
||||
}
|
||||
retryCount = 5 // retry 5 times (default is 0)
|
||||
retryWaitSec = 10 // wait 10 seconds between retries (default is 0)
|
||||
user = project.findProperty('deployDocsSshUsername')
|
||||
if (project.hasProperty('deployDocsSshKeyPath')) {
|
||||
identity = project.file(project.findProperty('deployDocsSshKeyPath'))
|
||||
} else if (project.hasProperty('deployDocsSshKey')) {
|
||||
identity = project.findProperty('deployDocsSshKey')
|
||||
}
|
||||
if(project.hasProperty('deployDocsSshPassphrase')) {
|
||||
passphrase = project.findProperty('deployDocsSshPassphrase')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
project.task('deployDocs') {
|
||||
dependsOn 'docsZip'
|
||||
doFirst {
|
||||
project.ssh.run {
|
||||
session(project.remotes.docs) {
|
||||
def now = System.currentTimeMillis()
|
||||
def name = project.rootProject.name
|
||||
def version = project.rootProject.version
|
||||
def tempPath = "/tmp/${name}-${now}-docs/".replaceAll(' ', '_')
|
||||
execute "mkdir -p $tempPath"
|
||||
|
||||
project.tasks.docsZip.outputs.each { o ->
|
||||
put from: o.files, into: tempPath
|
||||
}
|
||||
|
||||
execute "unzip $tempPath*.zip -d $tempPath"
|
||||
|
||||
def extractPath = "/var/www/domains/spring.io/docs/htdocs/autorepo/docs/${name}/${version}/"
|
||||
|
||||
execute "rm -rf $extractPath"
|
||||
execute "mkdir -p $extractPath"
|
||||
execute "mv $tempPath/docs/* $extractPath"
|
||||
execute "chmod -R g+w $extractPath"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -17,7 +17,6 @@ public class DocsPlugin implements Plugin<Project> {
|
||||
|
||||
PluginManager pluginManager = project.getPluginManager();
|
||||
pluginManager.apply(BasePlugin);
|
||||
pluginManager.apply(DeployDocsPlugin);
|
||||
pluginManager.apply(JavadocApiPlugin);
|
||||
|
||||
Task docsZip = project.tasks.create('docsZip', Zip) {
|
||||
|
||||
+1
-11
@@ -30,16 +30,6 @@ ossrh: {
|
||||
}
|
||||
}
|
||||
},
|
||||
docs: {
|
||||
stage('Deploy Docs') {
|
||||
node {
|
||||
checkout scm
|
||||
withCredentials([file(credentialsId: 'docs.spring.io-jenkins_private_ssh_key', variable: 'DEPLOY_SSH_KEY')]) {
|
||||
sh "./gradlew deployDocs -PdeployDocsSshKeyPath=$DEPLOY_SSH_KEY -PdeployDocsSshUsername=$SPRING_DOCS_USERNAME --refresh-dependencies --no-daemon --stacktrace"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
schema: {
|
||||
stage('Deploy Schema') {
|
||||
node {
|
||||
@@ -49,4 +39,4 @@ schema: {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
-1
@@ -3701,7 +3701,6 @@ public final class HttpSecurity extends AbstractConfiguredSecurityBuilder<Defaul
|
||||
* http
|
||||
* // ...
|
||||
* .webAuthn((webAuthn) -> webAuthn
|
||||
* .rpName("Spring Security Relying Party")
|
||||
* .rpId("example.com")
|
||||
* .allowedOrigins("https://example.com")
|
||||
* );
|
||||
|
||||
+3
-3
@@ -192,9 +192,9 @@ public class WebAuthnConfigurer<H extends HttpSecurityBuilder<H>>
|
||||
if (webauthnOperationsBean.isPresent()) {
|
||||
return webauthnOperationsBean.get();
|
||||
}
|
||||
Webauthn4JRelyingPartyOperations result = new Webauthn4JRelyingPartyOperations(userEntities, userCredentials,
|
||||
PublicKeyCredentialRpEntity.builder().id(this.rpId).name(this.rpName).build(), this.allowedOrigins);
|
||||
return result;
|
||||
String rpName = (this.rpName != null) ? this.rpName : this.rpId;
|
||||
return new Webauthn4JRelyingPartyOperations(userEntities, userCredentials,
|
||||
PublicKeyCredentialRpEntity.builder().id(this.rpId).name(rpName).build(), this.allowedOrigins);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+63
-1
@@ -18,12 +18,15 @@ package org.springframework.security.config.annotation.web.configurers;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.authentication.TestingAuthenticationToken;
|
||||
import org.springframework.security.config.Customizer;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||
@@ -38,7 +41,10 @@ import org.springframework.test.web.servlet.MockMvc;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.authentication;
|
||||
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.header;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
@@ -111,6 +117,42 @@ public class WebAuthnConfigurerTests {
|
||||
.hasSize(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
void webauthnWhenConfiguredDefaultsRpNameToRpId() throws Exception {
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
this.spring.register(DefaultWebauthnConfiguration.class).autowire();
|
||||
String response = this.mvc
|
||||
.perform(post("/webauthn/register/options").with(csrf())
|
||||
.with(authentication(new TestingAuthenticationToken("test", "ignored", "ROLE_user"))))
|
||||
.andExpect(status().is2xxSuccessful())
|
||||
.andReturn()
|
||||
.getResponse()
|
||||
.getContentAsString();
|
||||
|
||||
JsonNode parsedResponse = mapper.readTree(response);
|
||||
|
||||
assertThat(parsedResponse.get("rp").get("id").asText()).isEqualTo("example.com");
|
||||
assertThat(parsedResponse.get("rp").get("name").asText()).isEqualTo("example.com");
|
||||
}
|
||||
|
||||
@Test
|
||||
void webauthnWhenRpNameConfiguredUsesRpName() throws Exception {
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
this.spring.register(CustomRpNameWebauthnConfiguration.class).autowire();
|
||||
String response = this.mvc
|
||||
.perform(post("/webauthn/register/options").with(csrf())
|
||||
.with(authentication(new TestingAuthenticationToken("test", "ignored", "ROLE_user"))))
|
||||
.andExpect(status().is2xxSuccessful())
|
||||
.andReturn()
|
||||
.getResponse()
|
||||
.getContentAsString();
|
||||
|
||||
JsonNode parsedResponse = mapper.readTree(response);
|
||||
|
||||
assertThat(parsedResponse.get("rp").get("id").asText()).isEqualTo("example.com");
|
||||
assertThat(parsedResponse.get("rp").get("name").asText()).isEqualTo("Test RP Name");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void webauthnWhenConfiguredAndFormLoginThenDoesServesJavascript() throws Exception {
|
||||
this.spring.register(FormLoginAndNoDefaultRegistrationPageConfiguration.class).autowire();
|
||||
@@ -137,7 +179,27 @@ public class WebAuthnConfigurerTests {
|
||||
|
||||
@Bean
|
||||
SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
|
||||
return http.formLogin(Customizer.withDefaults()).webAuthn(Customizer.withDefaults()).build();
|
||||
return http.formLogin(Customizer.withDefaults())
|
||||
.webAuthn((webauthn) -> webauthn.rpId("example.com"))
|
||||
.build();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableWebSecurity
|
||||
static class CustomRpNameWebauthnConfiguration {
|
||||
|
||||
@Bean
|
||||
UserDetailsService userDetailsService() {
|
||||
return new InMemoryUserDetailsManager();
|
||||
}
|
||||
|
||||
@Bean
|
||||
SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
|
||||
return http.formLogin(Customizer.withDefaults())
|
||||
.webAuthn((webauthn) -> webauthn.rpId("example.com").rpName("Test RP Name"))
|
||||
.build();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+21
@@ -16,12 +16,14 @@
|
||||
|
||||
package org.springframework.security.crypto.bcrypt;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.SecureRandom;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
|
||||
import static org.assertj.core.api.Assertions.assertThatNoException;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
@@ -253,4 +255,23 @@ public class BCryptPasswordEncoderTests {
|
||||
assertThat(encoder.matches(password73chars, encodedPassword73chars)).isTrue();
|
||||
}
|
||||
|
||||
/**
|
||||
* Fixes gh-18133
|
||||
* @author StringManolo
|
||||
*/
|
||||
@Test
|
||||
void passwordLargerThan72BytesShouldThrowIllegalArgumentException() {
|
||||
BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
|
||||
String singleByteChars = "a".repeat(68);
|
||||
String password72Bytes = singleByteChars + "😀";
|
||||
assertThat(password72Bytes.length()).isEqualTo(70);
|
||||
assertThat(password72Bytes.getBytes(StandardCharsets.UTF_8).length).isEqualTo(72);
|
||||
assertThatNoException().isThrownBy(() -> encoder.encode(password72Bytes));
|
||||
String singleByteCharsTooLong = "a".repeat(69);
|
||||
String password73Bytes = singleByteCharsTooLong + "😀";
|
||||
assertThat(password73Bytes.getBytes(StandardCharsets.UTF_8).length).isEqualTo(73);
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> encoder.encode(password73Bytes))
|
||||
.withMessageContaining("password cannot be more than 72 bytes");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ urls:
|
||||
redirect_facility: httpd
|
||||
ui:
|
||||
bundle:
|
||||
url: https://github.com/spring-io/antora-ui-spring/releases/download/v0.4.18/ui-bundle.zip
|
||||
url: https://github.com/spring-io/antora-ui-spring/releases/download/v0.4.25/ui-bundle.zip
|
||||
snapshot: true
|
||||
runtime:
|
||||
log:
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
[[webflux-cors]]
|
||||
= CORS
|
||||
|
||||
@@ -75,3 +74,11 @@ fun springSecurityFilterChain(http: ServerHttpSecurity): SecurityWebFilterChain
|
||||
}
|
||||
----
|
||||
======
|
||||
|
||||
[WARNING]
|
||||
====
|
||||
CORS is a browser-based security feature.
|
||||
By disabling CORS in Spring Security, you are not removing CORS protection from your browser.
|
||||
Instead, you are removing CORS support from Spring Security, and users will not be able to interact with your Spring backend from a cross-origin browser application.
|
||||
To fix CORS errors in your application, you must enable CORS support, and provide an appropriate configuration source.
|
||||
====
|
||||
|
||||
@@ -137,7 +137,8 @@ fun method(authentication: Authentication?): String {
|
||||
will always return "not anonymous", even for anonymous requests.
|
||||
The reason is that Spring MVC resolves the parameter using `HttpServletRequest#getPrincipal`, which is `null` when the request is anonymous.
|
||||
|
||||
If you'd like to obtain the `Authentication` in anonymous requests, use `@CurrentSecurityContext` instead:
|
||||
If you'd like to obtain the `Authentication` in anonymous requests, use
|
||||
xref:servlet/integrations/mvc.adoc#mvc-current-security-context[`@CurrentSecurityContext`] instead:
|
||||
|
||||
.Use CurrentSecurityContext for Anonymous requests
|
||||
[tabs]
|
||||
|
||||
@@ -97,7 +97,11 @@ val authorities = authentication.authorities
|
||||
----
|
||||
======
|
||||
|
||||
// FIXME: Add links to and relevant description of HttpServletRequest.getRemoteUser() and @CurrentSecurityContext @AuthenticationPrincipal
|
||||
In Spring MVC, you can resolve the current principal with
|
||||
xref:servlet/integrations/mvc.adoc#mvc-authentication-principal[`@AuthenticationPrincipal`]
|
||||
and the full `SecurityContext` with
|
||||
xref:servlet/integrations/mvc.adoc#mvc-current-security-context[`@CurrentSecurityContext`].
|
||||
For Servlet API access, use `HttpServletRequest#getRemoteUser`.
|
||||
|
||||
By default, `SecurityContextHolder` uses a `ThreadLocal` to store these details, which means that the `SecurityContext` is always available to methods in the same thread, even if the `SecurityContext` is not explicitly passed around as an argument to those methods.
|
||||
Using a `ThreadLocal` in this way is quite safe if you take care to clear the thread after the present principal's request is processed.
|
||||
|
||||
@@ -39,7 +39,7 @@ Gradle::
|
||||
+
|
||||
[source,groovy,role="secondary",subs="verbatim,attributes"]
|
||||
----
|
||||
depenendencies {
|
||||
dependencies {
|
||||
implementation "org.springframework.security:spring-security-web"
|
||||
implementation "com.webauthn4j:webauthn4j-core:{webauthn4j-core-version}"
|
||||
}
|
||||
@@ -64,7 +64,6 @@ SecurityFilterChain filterChain(HttpSecurity http) {
|
||||
// ...
|
||||
.formLogin(withDefaults())
|
||||
.webAuthn((webAuthn) -> webAuthn
|
||||
.rpName("Spring Security Relying Party")
|
||||
.rpId("example.com")
|
||||
.allowedOrigins("https://example.com")
|
||||
);
|
||||
@@ -91,7 +90,6 @@ Kotlin::
|
||||
open fun filterChain(http: HttpSecurity): SecurityFilterChain {
|
||||
http {
|
||||
webAuthn {
|
||||
rpName = "Spring Security Relying Party"
|
||||
rpId = "example.com"
|
||||
allowedOrigins = setOf("https://example.com")
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ Gradle::
|
||||
+
|
||||
[source,groovy,role="secondary"]
|
||||
----
|
||||
depenendencies {
|
||||
dependencies {
|
||||
implementation "org.springframework.boot:spring-boot-starter-data-ldap"
|
||||
implementation "org.springframework.security:spring-security-ldap"
|
||||
}
|
||||
@@ -150,7 +150,7 @@ Gradle::
|
||||
+
|
||||
[source,groovy,role="secondary",subs="verbatim,attributes"]
|
||||
----
|
||||
depenendencies {
|
||||
dependencies {
|
||||
runtimeOnly "com.unboundid:unboundid-ldapsdk:{unboundid-ldapsdk-version}"
|
||||
}
|
||||
----
|
||||
|
||||
@@ -183,3 +183,11 @@ fun corsConfigurationSource(): UrlBasedCorsConfigurationSource {
|
||||
}
|
||||
----
|
||||
======
|
||||
|
||||
[WARNING]
|
||||
====
|
||||
CORS is a browser-based security feature.
|
||||
By disabling CORS in Spring Security with `.cors(CorsConfigurer::disable)`, you are not removing CORS protection from your browser.
|
||||
Instead, you are removing CORS support from Spring Security, and users will not be able to interact with your Spring backend from a cross-origin browser application.
|
||||
To fix CORS errors in your application, you must enable CORS support, and provide an appropriate configuration source.
|
||||
====
|
||||
|
||||
@@ -624,6 +624,72 @@ open fun findMessagesForUser(@CurrentUser("user_id") userId: String?): ModelAndV
|
||||
----
|
||||
======
|
||||
|
||||
[[mvc-current-security-context]]
|
||||
== @CurrentSecurityContext
|
||||
|
||||
Spring Security provides `CurrentSecurityContextArgumentResolver`, which can automatically resolve the current `SecurityContext` for Spring MVC arguments.
|
||||
By using `@EnableWebSecurity`, you automatically have this added to your Spring MVC configuration.
|
||||
If you use XML-based configuration, you must add this yourself:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
<mvc:annotation-driven>
|
||||
<mvc:argument-resolvers>
|
||||
<bean class="org.springframework.security.web.method.annotation.CurrentSecurityContextArgumentResolver" />
|
||||
</mvc:argument-resolvers>
|
||||
</mvc:annotation-driven>
|
||||
----
|
||||
|
||||
Once `CurrentSecurityContextArgumentResolver` is configured, you can access the `SecurityContext` directly:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,role="primary"]
|
||||
----
|
||||
@GetMapping("/me")
|
||||
public String me(@CurrentSecurityContext SecurityContext context) {
|
||||
return context.getAuthentication().getName();
|
||||
}
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,role="secondary"]
|
||||
----
|
||||
@GetMapping("/me")
|
||||
fun me(@CurrentSecurityContext context: SecurityContext): String {
|
||||
return context.authentication.name
|
||||
}
|
||||
----
|
||||
======
|
||||
|
||||
You can also use a SpEL expression that is rooted at the `SecurityContext`:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,role="primary"]
|
||||
----
|
||||
@GetMapping("/me")
|
||||
public String me(@CurrentSecurityContext(expression = "authentication") Authentication authentication) {
|
||||
return authentication.getName();
|
||||
}
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,role="secondary"]
|
||||
----
|
||||
@GetMapping("/me")
|
||||
fun me(@CurrentSecurityContext(expression = "authentication") authentication: Authentication): String {
|
||||
return authentication.name
|
||||
}
|
||||
----
|
||||
======
|
||||
|
||||
[[mvc-async]]
|
||||
== Spring MVC Async Integration
|
||||
|
||||
|
||||
+1
-1
@@ -14,7 +14,7 @@
|
||||
# limitations under the License.
|
||||
#
|
||||
springBootVersion=3.3.3
|
||||
version=6.4.12
|
||||
version=6.4.14-SNAPSHOT
|
||||
samplesBranch=6.4.x
|
||||
org.gradle.jvmargs=-Xmx3g -XX:+HeapDumpOnOutOfMemoryError
|
||||
org.gradle.parallel=true
|
||||
|
||||
+12
-12
@@ -5,8 +5,8 @@ io-spring-javaformat = "0.0.47"
|
||||
io-spring-nohttp = "0.0.11"
|
||||
jakarta-websocket = "2.2.0"
|
||||
org-apache-directory-server = "1.5.5"
|
||||
org-apache-maven-resolver = "1.9.24"
|
||||
org-aspectj = "1.9.24"
|
||||
org-apache-maven-resolver = "1.9.25"
|
||||
org-aspectj = "1.9.25.1"
|
||||
org-bouncycastle = "1.79"
|
||||
org-eclipse-jetty = "11.0.26"
|
||||
org-jetbrains-kotlin = "1.9.25"
|
||||
@@ -14,11 +14,11 @@ org-jetbrains-kotlinx = "1.9.0"
|
||||
org-mockito = "5.14.2"
|
||||
org-opensaml = "4.3.2"
|
||||
org-opensaml5 = "5.1.2"
|
||||
org-springframework = "6.2.12"
|
||||
org-springframework = "6.2.15"
|
||||
|
||||
[libraries]
|
||||
ch-qos-logback-logback-classic = "ch.qos.logback:logback-classic:1.5.20"
|
||||
com-fasterxml-jackson-jackson-bom = "com.fasterxml.jackson:jackson-bom:2.18.4.1"
|
||||
ch-qos-logback-logback-classic = "ch.qos.logback:logback-classic:1.5.25"
|
||||
com-fasterxml-jackson-jackson-bom = "com.fasterxml.jackson:jackson-bom:2.18.5"
|
||||
com-google-inject-guice = "com.google.inject:guice:3.0"
|
||||
com-netflix-nebula-nebula-project-plugin = "com.netflix.nebula:nebula-project-plugin:8.2.0"
|
||||
com-nimbusds-nimbus-jose-jwt = "com.nimbusds:nimbus-jose-jwt:9.37.4"
|
||||
@@ -28,15 +28,15 @@ com-squareup-okhttp3-okhttp = { module = "com.squareup.okhttp3:okhttp", version.
|
||||
com-unboundid-unboundid-ldapsdk = "com.unboundid:unboundid-ldapsdk:6.0.11"
|
||||
com-unboundid-unboundid-ldapsdk7 = "com.unboundid:unboundid-ldapsdk:7.0.1"
|
||||
commons-collections = "commons-collections:commons-collections:3.2.2"
|
||||
io-micrometer-micrometer-observation = "io.micrometer:micrometer-observation:1.14.12"
|
||||
io-micrometer-micrometer-observation = "io.micrometer:micrometer-observation:1.14.14"
|
||||
io-mockk = "io.mockk:mockk:1.13.17"
|
||||
io-projectreactor-reactor-bom = "io.projectreactor:reactor-bom:2023.0.19"
|
||||
io-projectreactor-reactor-bom = "io.projectreactor:reactor-bom:2024.0.13"
|
||||
io-rsocket-rsocket-bom = { module = "io.rsocket:rsocket-bom", version.ref = "io-rsocket" }
|
||||
io-spring-javaformat-spring-javaformat-checkstyle = { module = "io.spring.javaformat:spring-javaformat-checkstyle", version.ref = "io-spring-javaformat" }
|
||||
io-spring-javaformat-spring-javaformat-gradle-plugin = { module = "io.spring.javaformat:spring-javaformat-gradle-plugin", version.ref = "io-spring-javaformat" }
|
||||
io-spring-nohttp-nohttp-checkstyle = { module = "io.spring.nohttp:nohttp-checkstyle", version.ref = "io-spring-nohttp" }
|
||||
io-spring-nohttp-nohttp-gradle = { module = "io.spring.nohttp:nohttp-gradle", version.ref = "io-spring-nohttp" }
|
||||
io-spring-security-release-plugin = "io.spring.gradle:spring-security-release-plugin:1.0.11"
|
||||
io-spring-security-release-plugin = "io.spring.gradle:spring-security-release-plugin:1.0.13"
|
||||
jakarta-annotation-jakarta-annotation-api = "jakarta.annotation:jakarta.annotation-api:2.1.1"
|
||||
jakarta-inject-jakarta-inject-api = "jakarta.inject:jakarta.inject-api:2.0.1"
|
||||
jakarta-persistence-jakarta-persistence-api = "jakarta.persistence:jakarta.persistence-api:3.1.0"
|
||||
@@ -56,7 +56,7 @@ org-apache-directory-server-apacheds-protocol-shared = { module = "org.apache.di
|
||||
org-apache-directory-server-apacheds-server-jndi = { module = "org.apache.directory.server:apacheds-server-jndi", version.ref = "org-apache-directory-server" }
|
||||
org-apache-directory-shared-shared-ldap = "org.apache.directory.shared:shared-ldap:0.9.15"
|
||||
org-apache-httpcomponents-httpclient = "org.apache.httpcomponents:httpclient:4.5.14"
|
||||
org-apache-maven-maven-resolver-provider = "org.apache.maven:maven-resolver-provider:3.9.11"
|
||||
org-apache-maven-maven-resolver-provider = "org.apache.maven:maven-resolver-provider:3.9.12"
|
||||
org-apache-maven-resolver-maven-resolver-connector-basic = { module = "org.apache.maven.resolver:maven-resolver-connector-basic", version.ref = "org-apache-maven-resolver" }
|
||||
org-apache-maven-resolver-maven-resolver-impl = { module = "org.apache.maven.resolver:maven-resolver-impl", version.ref = "org-apache-maven-resolver" }
|
||||
org-apache-maven-resolver-maven-resolver-transport-http = { module = "org.apache.maven.resolver:maven-resolver-transport-http", version.ref = "org-apache-maven-resolver" }
|
||||
@@ -70,7 +70,7 @@ org-bouncycastle-bcprov-jdk15on = { module = "org.bouncycastle:bcprov-jdk18on",
|
||||
org-eclipse-jetty-jetty-server = { module = "org.eclipse.jetty:jetty-server", version.ref = "org-eclipse-jetty" }
|
||||
org-eclipse-jetty-jetty-servlet = { module = "org.eclipse.jetty:jetty-servlet", version.ref = "org-eclipse-jetty" }
|
||||
org-hamcrest = "org.hamcrest:hamcrest:2.2"
|
||||
org-hibernate-orm-hibernate-core = "org.hibernate.orm:hibernate-core:6.6.33.Final"
|
||||
org-hibernate-orm-hibernate-core = "org.hibernate.orm:hibernate-core:6.6.41.Final"
|
||||
org-hsqldb = "org.hsqldb:hsqldb:2.7.4"
|
||||
org-jetbrains-kotlin-kotlin-bom = { module = "org.jetbrains.kotlin:kotlin-bom", version.ref = "org-jetbrains-kotlin" }
|
||||
org-jetbrains-kotlin-kotlin-gradle-plugin = "org.jetbrains.kotlin:kotlin-gradle-plugin:1.9.25"
|
||||
@@ -88,8 +88,8 @@ org-seleniumhq-selenium-selenium-support = "org.seleniumhq.selenium:selenium-sup
|
||||
org-skyscreamer-jsonassert = "org.skyscreamer:jsonassert:1.5.3"
|
||||
org-slf4j-log4j-over-slf4j = "org.slf4j:log4j-over-slf4j:1.7.36"
|
||||
org-slf4j-slf4j-api = "org.slf4j:slf4j-api:2.0.17"
|
||||
org-springframework-data-spring-data-bom = "org.springframework.data:spring-data-bom:2024.1.11"
|
||||
org-springframework-ldap-spring-ldap-core = "org.springframework.ldap:spring-ldap-core:3.2.15"
|
||||
org-springframework-data-spring-data-bom = "org.springframework.data:spring-data-bom:2024.1.13"
|
||||
org-springframework-ldap-spring-ldap-core = "org.springframework.ldap:spring-ldap-core:3.2.16"
|
||||
org-springframework-spring-framework-bom = { module = "org.springframework:spring-framework-bom", version.ref = "org-springframework" }
|
||||
org-synchronoss-cloud-nio-multipart-parser = "org.synchronoss.cloud:nio-multipart-parser:1.1.0"
|
||||
|
||||
|
||||
+1
-1
@@ -5,7 +5,7 @@ pluginManagement {
|
||||
}
|
||||
|
||||
plugins {
|
||||
id "io.spring.develocity.conventions" version "0.0.24"
|
||||
id "io.spring.develocity.conventions" version "0.0.25"
|
||||
}
|
||||
|
||||
dependencyResolutionManagement {
|
||||
|
||||
Reference in New Issue
Block a user