1
0
mirror of synced 2026-07-08 12:20:02 +00:00

Compare commits

..

77 Commits

Author SHA1 Message Date
github-actions[bot] 6d3f1699c0 Release 5.7.9 2023-06-19 16:09:53 +00:00
Rob Winch 0cf95dbf61 Merge branch '5.6.x' into 5.7.x
Closes gh-13404
2023-06-18 21:31:35 -05:00
Rob Winch 39c43159f4 Convert to Asciidoctor Tabs
Closes gh-13403
2023-06-18 21:30:41 -05:00
Marcus Da Coregio 0a022a348c Merge branch '5.6.x' into 5.7.x
Closes gh-dry-run
2023-06-18 11:16:54 -03:00
Marcus Da Coregio afec90c8e8 Remove /plugins-release and /plugins-snapshot from build
Those repositories now need authentication, and we do not actually need them, the dependencies can be resolved from Maven Central

Closes gh-13245

(cherry picked from commit 663f5cf76b)
2023-06-17 19:32:48 -03:00
Marcus Da Coregio c7ccba66c7 Merge branch '5.6.x' into 5.7.x
Closes gh-dry-run
2023-06-17 18:23:15 -03:00
Marcus Da Coregio a6599f9874 Update org.springframework to 5.3.28
Closes gh-13401
2023-06-17 17:58:50 -03:00
Marcus Da Coregio 9f581850a1 Update hibernate-entitymanager to 5.6.15.Final
Closes gh-13400
2023-06-17 17:58:50 -03:00
Marcus Da Coregio 6e13927b48 Update org.eclipse.jetty to 9.4.51.v20230217
Closes gh-13399
2023-06-17 17:58:49 -03:00
Marcus Da Coregio cead207c5b Update org.aspectj to 1.9.19
Closes gh-13398
2023-06-17 17:58:49 -03:00
Marcus Da Coregio 9e22d40264 Update io.spring.nohttp to 0.0.11
Closes gh-13394
2023-06-17 17:58:49 -03:00
Marcus Da Coregio c54a191042 Update io.rsocket to 1.1.4
Closes gh-13392
2023-06-17 17:58:49 -03:00
Marcus Da Coregio 0da2e5a33e Update blockhound to 1.0.8.RELEASE
Closes gh-13390
2023-06-17 17:58:45 -03:00
Marcus Da Coregio 08b84502e3 Update io.projectreactor to 2020.0.33
Closes gh-13387
2023-06-17 17:58:22 -03:00
Marcus Da Coregio dbcff3f1af Update org.springframework.data to 2021.2.13
Closes gh-13385
2023-06-17 17:16:33 -03:00
Marcus Da Coregio e87fae40df Update org.springframework to 5.3.28
Closes gh-13382
2023-06-17 17:16:29 -03:00
Marcus Da Coregio 32d25e8f23 Update io.rsocket to 1.1.4
Closes gh-13379
2023-06-17 17:16:25 -03:00
Marcus Da Coregio 9656f79afe Update jackson-bom to 2.13.5
Closes gh-13375
2023-06-17 17:16:21 -03:00
Marcus Da Coregio 81723fca9a Update io.projectreactor to 2020.0.33
Closes gh-13373
2023-06-17 17:16:19 -03:00
Marcus Da Coregio ac32095bc8 Update logback-classic to 1.2.12
Closes gh-13372
2023-06-17 17:16:17 -03:00
Rob Winch 30206b6d0c Merge branch '5.6.x' into 5.7.x
Closes gh-13328
2023-06-16 20:23:19 -05:00
Rob Winch 3e22c1e8de Use antora name of security
Closes gh-13327
2023-06-16 17:14:56 -05:00
Marcus Da Coregio d67c11cfbd Add Proxy Server Configuration to nav
Closes gh-13313
2023-06-15 08:45:49 -03:00
Rob Winch a387f401b7 Merge branch '5.6.x' into 5.7.x
Closes gh-13315
2023-06-14 16:20:02 -05:00
Rob Winch 9bd04ed0e0 Fix Documentation Title
Closes gh-13314
2023-06-14 16:18:46 -05:00
Rob Winch 68cec50bad Merge branch '5.6.x' into 5.7.x
Closes gh-13291
2023-06-08 17:08:54 -05:00
Rob Winch 04692d9ee8 Fix Antora Warnings
Closes gh-13210
2023-06-08 17:02:19 -05:00
Anubhav Ahlawat 2279f9fd39 Typos in persistence section 2023-06-05 14:27:43 -06:00
Josh Cummings e834543eed Change possessives to use two ticks 2023-06-05 13:17:15 -06:00
1993heqiang 783f674704 Fix typo authentication.adoc 2023-06-05 13:17:15 -06:00
1993heqiang 933debebeb Fix typo overview.adoc 2023-06-05 13:17:15 -06:00
Marcus Da Coregio 7250abc185 Does not apply a Configurer when disabled from another DSL
Closes gh-13203
2023-06-05 16:01:20 -03:00
Christoph Zuleger 06e58e4c34 Update JavaDoc of BasicAuthenticationFilter
Remove deprecated hint to use Digest Auth in favor of Basic Auth.
2023-06-05 12:46:30 -06:00
Josh Cummings bcc1cfc28a Restore OAuth2AuthorizedClientRepository Test Instrumentation
Closes gh-13113
2023-05-31 15:30:03 -06:00
Marcus Da Coregio 663f5cf76b Remove /plugins-release and /plugins-snapshot from build
Those repositories now need authentication, and we do not actually need them, the dependencies can be resolved from Maven Central

Closes gh-13245
2023-05-30 15:25:54 -03:00
Marcus Da Coregio a53cbb838b Polish
Issue gh-13155
2023-05-24 14:59:16 -03:00
joerg-richter-5234 8287289bcb Fix XContentTypeOptionsServerHttpHeadersWriter
set constant value to X-Content-Type-Options

Closes gh-13155
2023-05-24 14:59:14 -03:00
Josh Cummings 1eefd433b6 Add spring-security.xsd symlink
Closes gh-13131
2023-05-22 15:42:02 -06:00
moli b6f3cb71e6 Add Missing AuthorizationRequestRepository in Snippet
Closes PR-13099
2023-05-18 10:54:19 -06:00
Josh Cummings 3469bcb822 Address Antora Warnings 2023-05-10 15:51:49 -06:00
Josh Cummings b4083f1b9e Revert "gh-13136 fixed log level related bug"
This reverts commit 1e093db1b6.
2023-05-08 15:23:17 -06:00
stnor 1e093db1b6 gh-13136 fixed log level related bug 2023-05-08 15:18:14 -06:00
Marcus Da Coregio e61adcb0cd Clarify that Kotlin DSL needs an import
Closes gh-13092
2023-04-26 15:56:47 -03:00
Ruslan Stelmachenko caa4093619 Fix javadoc for migration from WebSecurityConfigurerAdapter 2023-04-24 16:32:16 -06:00
Amal Krishna 8bec14009e Fix typo in SecurityMockMvcResultMatchers.java
Change the first parameter's name of the AuthenticatedMatcher.withAuthentication() method from assesrtAuthentication to assertAuthentication
2023-04-19 11:25:55 -03:00
SeasonPan 556ae316ba fix typo of modules.adoc 2023-04-19 11:25:55 -03:00
github-actions[bot] 53d007f062 Next development version 2023-04-17 16:04:08 +00:00
github-actions[bot] d6eeafb10c Release 5.7.8 2023-04-17 15:21:42 +00:00
Marcus Da Coregio 2d52fb8e4b Clear Repository on Logout 2023-04-17 06:47:57 -03:00
Marcus Da Coregio 37d8846652 Update org.springframework.data to 2021.2.11
Closes gh-13019
2023-04-14 13:57:28 -03:00
Marcus Da Coregio 74b8c6715b Update org.springframework to 5.3.27
Closes gh-13018
2023-04-14 10:41:45 -03:00
Marcus Da Coregio 8c9275067e Update org.eclipse.jetty to 9.4.51.v20230217
Closes gh-13017
2023-04-14 10:41:41 -03:00
Marcus Da Coregio 4b8bfee7c5 Update blockhound to 1.0.8.RELEASE
Closes gh-13016
2023-04-14 10:41:37 -03:00
Marcus Da Coregio b727f24c95 Update io.projectreactor to 2020.0.31
Closes gh-13014
2023-04-14 10:41:31 -03:00
Marcus Da Coregio d55c8aac4f Update logback-classic to 1.2.12
Closes gh-13013
2023-04-14 10:41:27 -03:00
Nick Meverden c4e9fb885d Delay JWSVerificationKeySelector Construction
Updating the NimbusReactiveJwtDecoder.JwkSetUriReactiveJwtDecoderBuilder processor to execute the ConfigurableJWTProcessor customizations before holding a reference to the JWSKeySelector.

Closes gh-12960
2023-04-12 12:45:00 -06:00
Christian Marck 442faccb5f Avoid NPE in FilterInvocation
Handle unknown headers in dummy request wrapper.

Closes gh-12998
2023-04-11 17:01:59 -06:00
Marcus Da Coregio e25117856e Add static imports to code snippets
Closes gh-6597
2023-04-11 09:56:19 -03:00
Yuanhang Guo c69df9fba0 Fix javadoc typo in ReactiveAuthorizationManager
Closes gh-12978
2023-04-10 11:24:49 -05:00
Josh Cummings 39cee36065 Use SingletonSupplier
Issue gh-9991
2023-04-04 13:25:31 -06:00
Tatiana Slednikova a106188add Add nameIdFormat processing to OpenSamlAuthenticationRequestResolver
Closes gh-12825
2023-03-27 16:33:11 -06:00
Martin Tarjányi 5eefe9dcff Fix typo in SessionManagementConfigurer javadoc 2023-03-22 10:07:44 -03:00
Siva Kumar Edupuganti 98321b769a Fixed Broken Support Link
Closes gh-12759
2023-03-20 16:59:04 -06:00
twosom 3d7e22a4e9 Add test to SimpleUrlAuthenticationSuccessHandlerTests 2023-03-20 16:20:30 -06:00
Marcus Da Coregio 84cca81edf Use HttpSessionSecurityContextRepository by default in SwitchUserFilter
Closes gh-12834
2023-03-07 13:27:18 -03:00
bist 094bf1b527 Validate hasRole Input
There are no check for role prefix in AuthorizeHttpRequestsConfigurer#XXXrole
methods. This PR adds check for the same. Now the configuration
will fail if role/s start with prefix for hasRole and hasAnyRole methods.

Closes #12581
2023-03-03 15:00:34 -07:00
Josh Cummings 66665344c5 Formatting
Issue gh-12664
2023-03-01 11:23:45 -07:00
stnor 6c7703789a Ignore SPSSODescriptor elements
Closes gh-12664
2023-03-01 11:23:45 -07:00
Steve Riesenberg fabf7f649c Fix path of copied schema files
Issue gh-12804
2023-03-01 11:49:36 -06:00
Steve Riesenberg 7b88ab289d Add nohttp exclusion
Issue gh-12804
2023-02-28 16:52:19 -06:00
Steve Riesenberg 26566af431 Copy spring-security-oauth schemas on deploy
Closes gh-12804
2023-02-28 16:16:08 -06:00
Steve Riesenberg 5257e36ffc Update SaganApi to work with Contentful backend
Also fixed an issue with incorrect referenceDocUrl for Antora
with SNAPSHOT versions.

Closes gh-12575
2023-02-28 14:09:51 -06:00
Josh Cummings 0421e25cba Document Common SAML URI Endpoints
Issue gh-12764
2023-02-28 12:45:48 -07:00
Josh Cummings 1c885cf3a3 Document Federation Usecase
Closes gh-12764
2023-02-28 12:35:04 -07:00
Marcus Da Coregio 1c3ce1e401 Fix entity-id ignored in RelyingPartyRegistration XML config
Closes gh-11898
2023-02-23 15:16:40 -03:00
github-actions[bot] b851a8bf6d Next development version 2023-02-21 15:20:58 +00:00
github-actions[bot] faadadf71a Release 5.7.7 2023-02-21 14:41:42 +00:00
851 changed files with 9359 additions and 42968 deletions
+1 -1
View File
@@ -57,7 +57,7 @@ See also the https://github.com/spring-projects/spring-framework/wiki/Gradle-bui
== Getting Support
Check out the https://stackoverflow.com/questions/tagged/spring-security[Spring Security tags on Stack Overflow].
https://spring.io/services[Commercial support] is available too.
https://spring.io/support[Commercial support] is available too.
== Contributing
https://help.github.com/articles/creating-a-pull-request[Pull requests] are welcome; see the https://github.com/spring-projects/spring-security/blob/main/CONTRIBUTING.adoc[contributor guidelines] for details.
@@ -27,9 +27,7 @@ import org.springframework.security.acls.model.SidRetrievalStrategy;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.context.SecurityContextHolderStrategy;
import org.springframework.util.Assert;
/**
@@ -48,9 +46,6 @@ import org.springframework.util.Assert;
*/
public class AclAuthorizationStrategyImpl implements AclAuthorizationStrategy {
private SecurityContextHolderStrategy securityContextHolderStrategy = SecurityContextHolder
.getContextHolderStrategy();
private final GrantedAuthority gaGeneralChanges;
private final GrantedAuthority gaModifyAuditing;
@@ -86,12 +81,12 @@ public class AclAuthorizationStrategyImpl implements AclAuthorizationStrategy {
@Override
public void securityCheck(Acl acl, int changeType) {
SecurityContext context = this.securityContextHolderStrategy.getContext();
if ((context == null) || (context.getAuthentication() == null)
|| !context.getAuthentication().isAuthenticated()) {
if ((SecurityContextHolder.getContext() == null)
|| (SecurityContextHolder.getContext().getAuthentication() == null)
|| !SecurityContextHolder.getContext().getAuthentication().isAuthenticated()) {
throw new AccessDeniedException("Authenticated principal required to operate with ACLs");
}
Authentication authentication = context.getAuthentication();
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
// Check if authorized by virtue of ACL ownership
Sid currentUser = createCurrentUser(authentication);
if (currentUser.equals(acl.getOwner())
@@ -151,15 +146,4 @@ public class AclAuthorizationStrategyImpl implements AclAuthorizationStrategy {
this.sidRetrievalStrategy = sidRetrievalStrategy;
}
/**
* Sets the {@link SecurityContextHolderStrategy} to use. The default action is to use
* the {@link SecurityContextHolderStrategy} stored in {@link SecurityContextHolder}.
*
* @since 5.8
*/
public void setSecurityContextHolderStrategy(SecurityContextHolderStrategy securityContextHolderStrategy) {
Assert.notNull(securityContextHolderStrategy, "securityContextHolderStrategy cannot be null");
this.securityContextHolderStrategy = securityContextHolderStrategy;
}
}
@@ -40,7 +40,6 @@ import org.springframework.security.acls.model.ObjectIdentity;
import org.springframework.security.acls.model.Sid;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.context.SecurityContextHolderStrategy;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import org.springframework.util.Assert;
@@ -65,9 +64,6 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS
private static final String DEFAULT_INSERT_INTO_ACL_CLASS_WITH_ID = "insert into acl_class (class, class_id_type) values (?, ?)";
private SecurityContextHolderStrategy securityContextHolderStrategy = SecurityContextHolder
.getContextHolderStrategy();
private boolean foreignKeysInDatabase = true;
private final AclCache aclCache;
@@ -119,7 +115,7 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS
// Need to retrieve the current principal, in order to know who "owns" this ACL
// (can be changed later on)
Authentication auth = this.securityContextHolderStrategy.getContext().getAuthentication();
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
PrincipalSid sid = new PrincipalSid(auth);
// Create the acl_object_identity row
@@ -477,15 +473,4 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS
}
}
/**
* Sets the {@link SecurityContextHolderStrategy} to use. The default action is to use
* the {@link SecurityContextHolderStrategy} stored in {@link SecurityContextHolder}.
*
* @since 5.8
*/
public void setSecurityContextHolderStrategy(SecurityContextHolderStrategy securityContextHolderStrategy) {
Assert.notNull(securityContextHolderStrategy, "securityContextHolderStrategy cannot be null");
this.securityContextHolderStrategy = securityContextHolderStrategy;
}
}
@@ -34,7 +34,7 @@ import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.verifyZeroInteractions;
/**
* @author Luke Taylor
@@ -68,7 +68,7 @@ public class AclPermissionCacheOptimizerTests {
pco.setObjectIdentityRetrievalStrategy(oids);
pco.setSidRetrievalStrategy(sids);
pco.cachePermissionsFor(mock(Authentication.class), Collections.emptyList());
verifyNoMoreInteractions(service, sids, oids);
verifyZeroInteractions(service, sids, oids);
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 the original author or authors.
* Copyright 2002-2016 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.
@@ -29,13 +29,9 @@ import org.springframework.security.acls.model.Acl;
import org.springframework.security.authentication.TestingAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.context.SecurityContextHolderStrategy;
import org.springframework.security.core.context.SecurityContextImpl;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.verify;
/**
* @author Rob Winch
@@ -44,14 +40,9 @@ import static org.mockito.Mockito.verify;
@ExtendWith(MockitoExtension.class)
public class AclAuthorizationStrategyImplTests {
SecurityContext context;
@Mock
Acl acl;
@Mock
SecurityContextHolderStrategy securityContextHolderStrategy;
GrantedAuthority authority;
AclAuthorizationStrategyImpl strategy;
@@ -62,8 +53,7 @@ public class AclAuthorizationStrategyImplTests {
TestingAuthenticationToken authentication = new TestingAuthenticationToken("foo", "bar",
Arrays.asList(this.authority));
authentication.setAuthenticated(true);
this.context = new SecurityContextImpl(authentication);
SecurityContextHolder.setContext(this.context);
SecurityContextHolder.getContext().setAuthentication(authentication);
}
@AfterEach
@@ -86,16 +76,6 @@ public class AclAuthorizationStrategyImplTests {
this.strategy.securityCheck(this.acl, AclAuthorizationStrategy.CHANGE_GENERAL);
}
@Test
public void securityCheckWhenCustomSecurityContextHolderStrategyThenUses() {
given(this.securityContextHolderStrategy.getContext()).willReturn(this.context);
given(this.acl.getOwner()).willReturn(new GrantedAuthoritySid("ROLE_AUTH"));
this.strategy = new AclAuthorizationStrategyImpl(new SimpleGrantedAuthority("ROLE_SYSTEM_ADMIN"));
this.strategy.setSecurityContextHolderStrategy(this.securityContextHolderStrategy);
this.strategy.securityCheck(this.acl, AclAuthorizationStrategy.CHANGE_GENERAL);
verify(this.securityContextHolderStrategy).getContext();
}
@SuppressWarnings("serial")
class CustomAuthority implements GrantedAuthority {
@@ -48,10 +48,7 @@ import org.springframework.security.acls.model.Sid;
import org.springframework.security.acls.sid.CustomSid;
import org.springframework.security.authentication.TestingAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.context.SecurityContextHolderStrategy;
import org.springframework.security.core.context.SecurityContextImpl;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.context.transaction.AfterTransaction;
@@ -62,9 +59,7 @@ import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
/**
* Integration tests the ACL system using an in-memory database.
@@ -355,19 +350,6 @@ public class JdbcMutableAclServiceTests {
assertThat(this.jdbcMutableAclService.readAclById(new ObjectIdentityImpl(TARGET_CLASS, 101L))).isNotNull();
}
@Test
@Transactional
public void createAclWhenCustomSecurityContextHolderStrategyThenUses() {
SecurityContextHolderStrategy securityContextHolderStrategy = mock(SecurityContextHolderStrategy.class);
SecurityContext context = new SecurityContextImpl(this.auth);
given(securityContextHolderStrategy.getContext()).willReturn(context);
JdbcMutableAclService service = new JdbcMutableAclService(this.dataSource, this.lookupStrategy, this.aclCache);
service.setSecurityContextHolderStrategy(securityContextHolderStrategy);
ObjectIdentity oid = new ObjectIdentityImpl(TARGET_CLASS, 101);
service.createAcl(oid);
verify(securityContextHolderStrategy).getContext();
}
/**
* SEC-655
*/
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 the original author or authors.
* Copyright 2002-2016 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.
@@ -37,9 +37,7 @@ import org.springframework.security.access.prepost.PreFilter;
* @author Mike Wiesner
* @author Luke Taylor
* @since 3.1
* @deprecated Use aspects in {@link org.springframework.security.authorization.method.aspectj} instead
*/
@Deprecated
public aspect AnnotationSecurityAspect implements InitializingBean {
/**
@@ -1,61 +0,0 @@
/*
* Copyright 2002-2022 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 org.springframework.security.authorization.method.aspectj;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.security.access.prepost.PostAuthorize;
/**
* Abstract AspectJ aspect for adapting a {@link MethodInvocation}
*
* @author Josh Cummings
* @since 5.8
*/
abstract aspect AbstractMethodInterceptorAspect {
protected abstract pointcut executionOfAnnotatedMethod();
private MethodInterceptor securityInterceptor;
Object around(): executionOfAnnotatedMethod() {
if (this.securityInterceptor == null) {
return proceed();
}
MethodInvocation invocation = new JoinPointMethodInvocation(thisJoinPoint, () -> proceed());
try {
return this.securityInterceptor.invoke(invocation);
} catch (Throwable t) {
throwUnchecked(t);
throw new IllegalStateException("Code unexpectedly reached", t);
}
}
public void setSecurityInterceptor(MethodInterceptor securityInterceptor) {
this.securityInterceptor = securityInterceptor;
}
private static void throwUnchecked(Throwable ex) {
AbstractMethodInterceptorAspect.<RuntimeException>throwAny(ex);
}
@SuppressWarnings("unchecked")
private static <E extends Throwable> void throwAny(Throwable ex) throws E {
throw (E) ex;
}
}
@@ -1,98 +0,0 @@
/*
* Copyright 2002-2022 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 org.springframework.security.authorization.method.aspectj;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Method;
import java.util.function.Supplier;
import org.aopalliance.intercept.MethodInvocation;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.reflect.CodeSignature;
import org.springframework.util.Assert;
class JoinPointMethodInvocation implements MethodInvocation {
private final JoinPoint jp;
private final Method method;
private final Object target;
private final Supplier<Object> proceed;
JoinPointMethodInvocation(JoinPoint jp, Supplier<Object> proceed) {
this.jp = jp;
if (jp.getTarget() != null) {
this.target = jp.getTarget();
}
else {
// SEC-1295: target may be null if an ITD is in use
this.target = jp.getSignature().getDeclaringType();
}
String targetMethodName = jp.getStaticPart().getSignature().getName();
Class<?>[] types = ((CodeSignature) jp.getStaticPart().getSignature()).getParameterTypes();
Class<?> declaringType = jp.getStaticPart().getSignature().getDeclaringType();
this.method = findMethod(targetMethodName, declaringType, types);
Assert.notNull(this.method, () -> "Could not obtain target method from JoinPoint: '" + jp + "'");
this.proceed = proceed;
}
private Method findMethod(String name, Class<?> declaringType, Class<?>[] params) {
Method method = null;
try {
method = declaringType.getMethod(name, params);
}
catch (NoSuchMethodException ignored) {
}
if (method == null) {
try {
method = declaringType.getDeclaredMethod(name, params);
}
catch (NoSuchMethodException ignored) {
}
}
return method;
}
@Override
public Method getMethod() {
return this.method;
}
@Override
public Object[] getArguments() {
return this.jp.getArgs();
}
@Override
public AccessibleObject getStaticPart() {
return this.method;
}
@Override
public Object getThis() {
return this.target;
}
@Override
public Object proceed() throws Throwable {
return this.proceed.get();
}
}
@@ -1,44 +0,0 @@
/*
* Copyright 2002-2022 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 org.springframework.security.authorization.method.aspectj;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.security.access.prepost.PostAuthorize;
/**
* Concrete AspectJ aspect using Spring Security @PostAuthorize annotation.
*
* <p>
* When using this aspect, you <i>must</i> annotate the implementation class
* (and/or methods within that class), <i>not</i> the interface (if any) that
* the class implements. AspectJ follows Java's rule that annotations on
* interfaces are <i>not</i> inherited. This will vary from Spring AOP.
*
* @author Mike Wiesner
* @author Luke Taylor
* @author Josh Cummings
* @since 5.8
*/
public aspect PostAuthorizeAspect extends AbstractMethodInterceptorAspect {
/**
* Matches the execution of any method with a PostAuthorize annotation.
*/
protected pointcut executionOfAnnotatedMethod() : execution(* *(..)) && @annotation(PostAuthorize);
}
@@ -1,45 +0,0 @@
/*
* Copyright 2002-2022 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 org.springframework.security.authorization.method.aspectj;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.security.access.prepost.PostFilter;
/**
* Concrete AspectJ aspect using Spring Security @PostFilter annotation.
*
* <p>
* When using this aspect, you <i>must</i> annotate the implementation class
* (and/or methods within that class), <i>not</i> the interface (if any) that
* the class implements. AspectJ follows Java's rule that annotations on
* interfaces are <i>not</i> inherited. This will vary from Spring AOP.
*
* @author Mike Wiesner
* @author Luke Taylor
* @author Josh Cummings
* @since 5.8
*/
public aspect PostFilterAspect extends AbstractMethodInterceptorAspect {
/**
* Matches the execution of any method with a PostFilter annotation.
*/
protected pointcut executionOfAnnotatedMethod() : execution(* *(..)) && @annotation(PostFilter);
}
@@ -1,44 +0,0 @@
/*
* Copyright 2002-2022 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 org.springframework.security.authorization.method.aspectj;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.security.access.prepost.PreAuthorize;
/**
* Concrete AspectJ aspect using Spring Security @PreAuthorize annotation.
*
* <p>
* When using this aspect, you <i>must</i> annotate the implementation class
* (and/or methods within that class), <i>not</i> the interface (if any) that
* the class implements. AspectJ follows Java's rule that annotations on
* interfaces are <i>not</i> inherited. This will vary from Spring AOP.
*
* @author Mike Wiesner
* @author Luke Taylor
* @author Josh Cummings
* @since 5.8
*/
public aspect PreAuthorizeAspect extends AbstractMethodInterceptorAspect {
/**
* Matches the execution of any method with a PreAuthorize annotation.
*/
protected pointcut executionOfAnnotatedMethod() : execution(* *(..)) && @annotation(PreAuthorize);
}
@@ -1,45 +0,0 @@
/*
* Copyright 2002-2022 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 org.springframework.security.authorization.method.aspectj;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.security.access.prepost.PreFilter;
/**
* Concrete AspectJ aspect using Spring Security @PreFilter annotation.
*
* <p>
* When using this aspect, you <i>must</i> annotate the implementation class
* (and/or methods within that class), <i>not</i> the interface (if any) that
* the class implements. AspectJ follows Java's rule that annotations on
* interfaces are <i>not</i> inherited. This will vary from Spring AOP.
*
* @author Mike Wiesner
* @author Luke Taylor
* @author Josh Cummings
* @since 5.8
*/
public aspect PreFilterAspect extends AbstractMethodInterceptorAspect {
/**
* Matches the execution of any method with a PreFilter annotation.
*/
protected pointcut executionOfAnnotatedMethod() : execution(* *(..)) && @annotation(PreFilter);
}
@@ -1,56 +0,0 @@
/*
* Copyright 2002-2022 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 org.springframework.security.authorization.method.aspectj;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.security.access.annotation.Secured;
/**
* Concrete AspectJ aspect using Spring Security @Secured annotation.
*
* <p>
* When using this aspect, you <i>must</i> annotate the implementation class
* (and/or methods within that class), <i>not</i> the interface (if any) that
* the class implements. AspectJ follows Java's rule that annotations on
* interfaces are <i>not</i> inherited. This will vary from Spring AOP.
*
* @author Mike Wiesner
* @author Luke Taylor
* @author Josh Cummings
* @since 5.8
*/
public aspect SecuredAspect extends AbstractMethodInterceptorAspect {
/**
* Matches the execution of any public method in a type with the Secured
* annotation, or any subtype of a type with the Secured annotation.
*/
private pointcut executionOfAnyPublicMethodInAtSecuredType() :
execution(public * ((@Secured *)+).*(..)) && @this(Secured);
/**
* Matches the execution of any method with the Secured annotation.
*/
private pointcut executionOfSecuredMethod() :
execution(* *(..)) && @annotation(Secured);
protected pointcut executionOfAnnotatedMethod() :
executionOfAnyPublicMethodInAtSecuredType() ||
executionOfSecuredMethod();
}
@@ -1,160 +0,0 @@
/*
* Copyright 2002-2022 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 org.springframework.security.authorization.method.aspectj;
import org.aopalliance.intercept.MethodInterceptor;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.MockitoAnnotations;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.access.prepost.PostAuthorize;
import org.springframework.security.authentication.AuthenticationCredentialsNotFoundException;
import org.springframework.security.authentication.TestingAuthenticationToken;
import org.springframework.security.authorization.method.AuthorizationManagerAfterMethodInterceptor;
import org.springframework.security.core.context.SecurityContextHolder;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
/**
* @author Luke Taylor
* @since 3.0.3
*/
public class PostAuthorizeAspectTests {
private TestingAuthenticationToken anne = new TestingAuthenticationToken("anne", "", "ROLE_A");
private MethodInterceptor interceptor;
private SecuredImpl secured = new SecuredImpl();
private SecuredImplSubclass securedSub = new SecuredImplSubclass();
private PrePostSecured prePostSecured = new PrePostSecured();
@BeforeEach
public final void setUp() {
MockitoAnnotations.initMocks(this);
this.interceptor = AuthorizationManagerAfterMethodInterceptor.postAuthorize();
PostAuthorizeAspect secAspect = PostAuthorizeAspect.aspectOf();
secAspect.setSecurityInterceptor(this.interceptor);
}
@AfterEach
public void clearContext() {
SecurityContextHolder.clearContext();
}
@Test
public void securedInterfaceMethodAllowsAllAccess() {
this.secured.securedMethod();
}
@Test
public void securedClassMethodDeniesUnauthenticatedAccess() {
assertThatExceptionOfType(AuthenticationCredentialsNotFoundException.class)
.isThrownBy(() -> this.secured.securedClassMethod());
}
@Test
public void securedClassMethodAllowsAccessToRoleA() {
SecurityContextHolder.getContext().setAuthentication(this.anne);
this.secured.securedClassMethod();
}
@Test
public void internalPrivateCallIsIntercepted() {
SecurityContextHolder.getContext().setAuthentication(this.anne);
assertThatExceptionOfType(AccessDeniedException.class).isThrownBy(() -> this.secured.publicCallsPrivate());
assertThatExceptionOfType(AccessDeniedException.class).isThrownBy(() -> this.securedSub.publicCallsPrivate());
}
@Test
public void protectedMethodIsIntercepted() {
SecurityContextHolder.getContext().setAuthentication(this.anne);
assertThatExceptionOfType(AccessDeniedException.class).isThrownBy(() -> this.secured.protectedMethod());
}
@Test
public void overriddenProtectedMethodIsNotIntercepted() {
// AspectJ doesn't inherit annotations
this.securedSub.protectedMethod();
}
// SEC-1262
@Test
public void denyAllPreAuthorizeDeniesAccess() {
SecurityContextHolder.getContext().setAuthentication(this.anne);
assertThatExceptionOfType(AccessDeniedException.class).isThrownBy(this.prePostSecured::denyAllMethod);
}
interface SecuredInterface {
@PostAuthorize("hasRole('X')")
void securedMethod();
}
static class SecuredImpl implements SecuredInterface {
// Not really secured because AspectJ doesn't inherit annotations from interfaces
@Override
public void securedMethod() {
}
@PostAuthorize("hasRole('A')")
void securedClassMethod() {
}
@PostAuthorize("hasRole('X')")
private void privateMethod() {
}
@PostAuthorize("hasRole('X')")
protected void protectedMethod() {
}
@PostAuthorize("hasRole('X')")
void publicCallsPrivate() {
privateMethod();
}
}
static class SecuredImplSubclass extends SecuredImpl {
@Override
protected void protectedMethod() {
}
@Override
public void publicCallsPrivate() {
super.publicCallsPrivate();
}
}
static class PrePostSecured {
@PostAuthorize("denyAll")
void denyAllMethod() {
}
}
}
@@ -1,66 +0,0 @@
/*
* Copyright 2002-2022 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 org.springframework.security.authorization.method.aspectj;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.aopalliance.intercept.MethodInterceptor;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.MockitoAnnotations;
import org.springframework.security.access.prepost.PostFilter;
import org.springframework.security.authorization.method.PostFilterAuthorizationMethodInterceptor;
import static org.assertj.core.api.Assertions.assertThat;
/**
* @author Luke Taylor
* @since 3.0.3
*/
public class PostFilterAspectTests {
private MethodInterceptor interceptor;
private PrePostSecured prePostSecured = new PrePostSecured();
@BeforeEach
public final void setUp() {
MockitoAnnotations.initMocks(this);
this.interceptor = new PostFilterAuthorizationMethodInterceptor();
PostFilterAspect secAspect = PostFilterAspect.aspectOf();
secAspect.setSecurityInterceptor(this.interceptor);
}
@Test
public void preFilterMethodWhenListThenFilters() {
List<String> objects = new ArrayList<>(Arrays.asList("apple", "banana", "aubergine", "orange"));
assertThat(this.prePostSecured.postFilterMethod(objects)).containsExactly("apple", "aubergine");
}
static class PrePostSecured {
@PostFilter("filterObject.startsWith('a')")
List<String> postFilterMethod(List<String> objects) {
return objects;
}
}
}
@@ -1,160 +0,0 @@
/*
* Copyright 2002-2022 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 org.springframework.security.authorization.method.aspectj;
import org.aopalliance.intercept.MethodInterceptor;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.MockitoAnnotations;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.authentication.AuthenticationCredentialsNotFoundException;
import org.springframework.security.authentication.TestingAuthenticationToken;
import org.springframework.security.authorization.method.AuthorizationManagerBeforeMethodInterceptor;
import org.springframework.security.core.context.SecurityContextHolder;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
/**
* @author Luke Taylor
* @since 3.0.3
*/
public class PreAuthorizeAspectTests {
private TestingAuthenticationToken anne = new TestingAuthenticationToken("anne", "", "ROLE_A");
private MethodInterceptor interceptor;
private SecuredImpl secured = new SecuredImpl();
private SecuredImplSubclass securedSub = new SecuredImplSubclass();
private PrePostSecured prePostSecured = new PrePostSecured();
@BeforeEach
public final void setUp() {
MockitoAnnotations.initMocks(this);
this.interceptor = AuthorizationManagerBeforeMethodInterceptor.preAuthorize();
PreAuthorizeAspect secAspect = PreAuthorizeAspect.aspectOf();
secAspect.setSecurityInterceptor(this.interceptor);
}
@AfterEach
public void clearContext() {
SecurityContextHolder.clearContext();
}
@Test
public void securedInterfaceMethodAllowsAllAccess() {
this.secured.securedMethod();
}
@Test
public void securedClassMethodDeniesUnauthenticatedAccess() {
assertThatExceptionOfType(AuthenticationCredentialsNotFoundException.class)
.isThrownBy(() -> this.secured.securedClassMethod());
}
@Test
public void securedClassMethodAllowsAccessToRoleA() {
SecurityContextHolder.getContext().setAuthentication(this.anne);
this.secured.securedClassMethod();
}
@Test
public void internalPrivateCallIsIntercepted() {
SecurityContextHolder.getContext().setAuthentication(this.anne);
assertThatExceptionOfType(AccessDeniedException.class).isThrownBy(() -> this.secured.publicCallsPrivate());
assertThatExceptionOfType(AccessDeniedException.class).isThrownBy(() -> this.securedSub.publicCallsPrivate());
}
@Test
public void protectedMethodIsIntercepted() {
SecurityContextHolder.getContext().setAuthentication(this.anne);
assertThatExceptionOfType(AccessDeniedException.class).isThrownBy(() -> this.secured.protectedMethod());
}
@Test
public void overriddenProtectedMethodIsNotIntercepted() {
// AspectJ doesn't inherit annotations
this.securedSub.protectedMethod();
}
// SEC-1262
@Test
public void denyAllPreAuthorizeDeniesAccess() {
SecurityContextHolder.getContext().setAuthentication(this.anne);
assertThatExceptionOfType(AccessDeniedException.class).isThrownBy(this.prePostSecured::denyAllMethod);
}
interface SecuredInterface {
@PreAuthorize("hasRole('X')")
void securedMethod();
}
static class SecuredImpl implements SecuredInterface {
// Not really secured because AspectJ doesn't inherit annotations from interfaces
@Override
public void securedMethod() {
}
@PreAuthorize("hasRole('A')")
void securedClassMethod() {
}
@PreAuthorize("hasRole('X')")
private void privateMethod() {
}
@PreAuthorize("hasRole('X')")
protected void protectedMethod() {
}
@PreAuthorize("hasRole('X')")
void publicCallsPrivate() {
privateMethod();
}
}
static class SecuredImplSubclass extends SecuredImpl {
@Override
protected void protectedMethod() {
}
@Override
public void publicCallsPrivate() {
super.publicCallsPrivate();
}
}
static class PrePostSecured {
@PreAuthorize("denyAll")
void denyAllMethod() {
}
}
}
@@ -1,66 +0,0 @@
/*
* Copyright 2002-2022 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 org.springframework.security.authorization.method.aspectj;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.aopalliance.intercept.MethodInterceptor;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.MockitoAnnotations;
import org.springframework.security.access.prepost.PreFilter;
import org.springframework.security.authorization.method.PreFilterAuthorizationMethodInterceptor;
import static org.assertj.core.api.Assertions.assertThat;
/**
* @author Luke Taylor
* @since 3.0.3
*/
public class PreFilterAspectTests {
private MethodInterceptor interceptor;
private PrePostSecured prePostSecured = new PrePostSecured();
@BeforeEach
public final void setUp() {
MockitoAnnotations.initMocks(this);
this.interceptor = new PreFilterAuthorizationMethodInterceptor();
PreFilterAspect secAspect = PreFilterAspect.aspectOf();
secAspect.setSecurityInterceptor(this.interceptor);
}
@Test
public void preFilterMethodWhenListThenFilters() {
List<String> objects = new ArrayList<>(Arrays.asList("apple", "banana", "aubergine", "orange"));
assertThat(this.prePostSecured.preFilterMethod(objects)).containsExactly("apple", "aubergine");
}
static class PrePostSecured {
@PreFilter("filterObject.startsWith('a')")
List<String> preFilterMethod(List<String> objects) {
return objects;
}
}
}
@@ -1,143 +0,0 @@
/*
* Copyright 2002-2022 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 org.springframework.security.authorization.method.aspectj;
import org.aopalliance.intercept.MethodInterceptor;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.MockitoAnnotations;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.access.annotation.Secured;
import org.springframework.security.authentication.AuthenticationCredentialsNotFoundException;
import org.springframework.security.authentication.TestingAuthenticationToken;
import org.springframework.security.authorization.method.AuthorizationManagerBeforeMethodInterceptor;
import org.springframework.security.core.context.SecurityContextHolder;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
/**
* @author Luke Taylor
* @since 3.0.3
*/
public class SecuredAspectTests {
private TestingAuthenticationToken anne = new TestingAuthenticationToken("anne", "", "ROLE_A");
private MethodInterceptor interceptor;
private SecuredImpl secured = new SecuredImpl();
private SecuredImplSubclass securedSub = new SecuredImplSubclass();
@BeforeEach
public final void setUp() {
MockitoAnnotations.initMocks(this);
this.interceptor = AuthorizationManagerBeforeMethodInterceptor.secured();
SecuredAspect secAspect = SecuredAspect.aspectOf();
secAspect.setSecurityInterceptor(this.interceptor);
}
@AfterEach
public void clearContext() {
SecurityContextHolder.clearContext();
}
@Test
public void securedInterfaceMethodAllowsAllAccess() {
this.secured.securedMethod();
}
@Test
public void securedClassMethodDeniesUnauthenticatedAccess() {
assertThatExceptionOfType(AuthenticationCredentialsNotFoundException.class)
.isThrownBy(() -> this.secured.securedClassMethod());
}
@Test
public void securedClassMethodAllowsAccessToRoleA() {
SecurityContextHolder.getContext().setAuthentication(this.anne);
this.secured.securedClassMethod();
}
@Test
public void internalPrivateCallIsIntercepted() {
SecurityContextHolder.getContext().setAuthentication(this.anne);
assertThatExceptionOfType(AccessDeniedException.class).isThrownBy(() -> this.secured.publicCallsPrivate());
assertThatExceptionOfType(AccessDeniedException.class).isThrownBy(() -> this.securedSub.publicCallsPrivate());
}
@Test
public void protectedMethodIsIntercepted() {
SecurityContextHolder.getContext().setAuthentication(this.anne);
assertThatExceptionOfType(AccessDeniedException.class).isThrownBy(() -> this.secured.protectedMethod());
}
@Test
public void overriddenProtectedMethodIsNotIntercepted() {
// AspectJ doesn't inherit annotations
this.securedSub.protectedMethod();
}
interface SecuredInterface {
@Secured("ROLE_X")
void securedMethod();
}
static class SecuredImpl implements SecuredInterface {
// Not really secured because AspectJ doesn't inherit annotations from interfaces
@Override
public void securedMethod() {
}
@Secured("ROLE_A")
void securedClassMethod() {
}
@Secured("ROLE_X")
private void privateMethod() {
}
@Secured("ROLE_X")
protected void protectedMethod() {
}
@Secured("ROLE_X")
void publicCallsPrivate() {
privateMethod();
}
}
static class SecuredImplSubclass extends SecuredImpl {
@Override
protected void protectedMethod() {
}
@Override
public void publicCallsPrivate() {
super.publicCallsPrivate();
}
}
}
+21 -13
View File
@@ -4,7 +4,7 @@ buildscript {
dependencies {
classpath "io.spring.javaformat:spring-javaformat-gradle-plugin:$springJavaformatVersion"
classpath 'io.spring.nohttp:nohttp-gradle:0.0.11'
classpath "io.freefair.gradle:aspectj-plugin:6.5.1"
classpath "io.freefair.gradle:aspectj-plugin:6.4.3.1"
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion"
classpath "com.netflix.nebula:nebula-project-plugin:8.2.0"
}
@@ -104,9 +104,16 @@ updateDependenciesSettings {
majorVersionBump()
minorVersionBump()
releaseCandidatesVersions()
milestoneVersions()
alphaBetaVersions()
snapshotVersions()
addRule { components ->
components.withModule("commons-codec:commons-codec") { selection ->
ModuleComponentIdentifier candidate = selection.getCandidate();
if (!candidate.getVersion().equals(selection.getCurrentVersion())) {
selection.reject("commons-codec updates break saml tests");
}
}
components.withModule("org.python:jython") { selection ->
ModuleComponentIdentifier candidate = selection.getCandidate();
if (!candidate.getVersion().equals(selection.getCurrentVersion())) {
@@ -119,12 +126,6 @@ updateDependenciesSettings {
selection.reject("nimbus-jose-jwt gets updated when oauth2-oidc-sdk is updated to ensure consistency");
}
}
components.withModule("io.mockk:mockk") { selection ->
ModuleComponentIdentifier candidate = selection.getCandidate();
if (!candidate.getVersion().equals(selection.getCurrentVersion())) {
selection.reject("mockk updates break tests");
}
}
components.all { selection ->
ModuleComponentIdentifier candidate = selection.getCandidate();
// Do not compare version due to multiple versions existing
@@ -133,6 +134,18 @@ updateDependenciesSettings {
selection.reject("org.opensaml maintains two different versions, so it must be updated manually");
}
}
components.withModule("io.spring.javaformat:spring-javaformat-gradle-plugin") { selection ->
ModuleComponentIdentifier candidate = selection.getCandidate();
if (!candidate.getVersion().equals(selection.getCurrentVersion())) {
selection.reject("spring-javaformat-gradle-plugin updates break checkstyle");
}
}
components.withModule("io.spring.javaformat:spring-javaformat-checkstyle") { selection ->
ModuleComponentIdentifier candidate = selection.getCandidate();
if (!candidate.getVersion().equals(selection.getCurrentVersion())) {
selection.reject("spring-javaformat-checkstyle updates break checkstyle");
}
}
}
}
}
@@ -144,6 +157,7 @@ subprojects {
tasks.withType(JavaCompile) {
options.encoding = "UTF-8"
options.compilerArgs.add("-parameters")
options.release = 8
}
}
@@ -172,12 +186,6 @@ allprojects {
}
}
}
tasks.withType(JavaCompile).configureEach {
javaCompiler = javaToolchains.compilerFor {
languageVersion = JavaLanguageVersion.of(8)
}
}
}
if (hasProperty('buildScan')) {
+2 -3
View File
@@ -10,7 +10,6 @@ sourceCompatibility = 1.8
repositories {
gradlePluginPortal()
mavenCentral()
maven { url 'https://repo.spring.io/plugins-release/' }
}
sourceSets {
@@ -87,7 +86,7 @@ dependencies {
implementation localGroovy()
implementation 'io.github.gradle-nexus:publish-plugin:1.1.0'
implementation 'io.projectreactor:reactor-core:3.5.0-M1'
implementation 'io.projectreactor:reactor-core:3.5.0'
implementation 'org.gretty:gretty:3.0.9'
implementation 'com.apollographql.apollo:apollo-runtime:2.4.5'
implementation 'com.github.ben-manes:gradle-versions-plugin:0.38.0'
@@ -99,7 +98,7 @@ dependencies {
implementation 'org.jfrog.buildinfo:build-info-extractor-gradle:4.29.0'
implementation 'org.sonarsource.scanner.gradle:sonarqube-gradle-plugin:2.7.1'
testImplementation platform('org.junit:junit-bom:5.9.2')
testImplementation platform('org.junit:junit-bom:5.8.2')
testImplementation "org.junit.jupiter:junit-jupiter-api"
testImplementation "org.junit.jupiter:junit-jupiter-params"
testImplementation "org.junit.jupiter:junit-jupiter-engine"
@@ -62,6 +62,33 @@ public class SchemaDeployPlugin implements Plugin<Project> {
execute "rm -f $tempPath*.zip"
execute "rm -rf $extractPath*"
execute "mv $tempPath/* $extractPath"
/*
* Copy spring-security-oauth schemas so that legacy projects using the "http" scheme can
* resolve the following schema locations:
*
* - http://www.springframework.org/schema/security/spring-security-oauth-1.0.xsd
* - http://www.springframework.org/schema/security/spring-security-oauth2-1.0.xsd
* - http://www.springframework.org/schema/security/spring-security-oauth2-2.0.xsd
*
* Note: The directory:
* https://www.springframework.org/schema/security/
*
* is a symbolic link pointing to:
* https://docs.spring.io/autorepo/schema/spring-security/current/security/
*
* which in turn points to the latest:
* https://docs.spring.io/autorepo/schema/spring-security/$version/security/
*
* with the help of the autoln command which is run regularly via a cron job.
*
* See https://github.com/spring-io/autoln for more info.
*/
if (name == "spring-security") {
def springSecurityOauthPath = "/var/www/domains/spring.io/docs/htdocs/autorepo/schema/spring-security-oauth/current/security"
execute "cp $springSecurityOauthPath/* ${extractPath}security"
}
execute "chmod -R g+w $extractPath"
}
}
@@ -1,9 +1,9 @@
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
import org.gradle.api.plugins.JavaPlugin
import org.gradle.api.tasks.bundling.Zip
public class SchemaZipPlugin implements Plugin<Project> {
@@ -37,6 +37,15 @@ public class SchemaZipPlugin implements Plugin<Project> {
from xsdFile.path
}
}
File symlink = module.sourceSets.main.resources.find {
it.path.endsWith('org/springframework/security/config/spring-security.xsd')
}
if (symlink != null) {
schemaZip.into('security') {
duplicatesStrategy 'exclude'
from symlink.path
}
}
}
}
}
@@ -0,0 +1,82 @@
/*
* Copyright 2020-2023 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 org.springframework.gradle.github.user;
import java.io.IOException;
import com.google.gson.Gson;
import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
/**
* @author Steve Riesenberg
*/
public class GitHubUserApi {
private String baseUrl = "https://api.github.com";
private final OkHttpClient httpClient;
private Gson gson = new Gson();
public GitHubUserApi(String gitHubAccessToken) {
this.httpClient = new OkHttpClient.Builder()
.addInterceptor(new AuthorizationInterceptor(gitHubAccessToken))
.build();
}
public void setBaseUrl(String baseUrl) {
this.baseUrl = baseUrl;
}
/**
* Retrieve a GitHub user by the personal access token.
*
* @return The GitHub user
*/
public User getUser() {
String url = this.baseUrl + "/user";
Request request = new Request.Builder().url(url).get().build();
try (Response response = this.httpClient.newCall(request).execute()) {
if (!response.isSuccessful()) {
throw new RuntimeException(
String.format("Unable to retrieve GitHub user." +
" Please check the personal access token and try again." +
" Got response %s", response));
}
return this.gson.fromJson(response.body().charStream(), User.class);
} catch (IOException ex) {
throw new RuntimeException("Unable to retrieve GitHub user.", ex);
}
}
private static class AuthorizationInterceptor implements Interceptor {
private final String token;
public AuthorizationInterceptor(String token) {
this.token = token;
}
@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request().newBuilder()
.addHeader("Authorization", "Bearer " + this.token)
.build();
return chain.proceed(request);
}
}
}
@@ -0,0 +1,53 @@
package org.springframework.gradle.github.user;
/**
* @author Steve Riesenberg
*/
public class User {
private Long id;
private String login;
private String name;
private String url;
public Long getId() {
return this.id;
}
public void setId(Long id) {
this.id = id;
}
public String getLogin() {
return this.login;
}
public void setLogin(String login) {
this.login = login;
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public String getUrl() {
return this.url;
}
public void setUrl(String url) {
this.url = url;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", login='" + login + '\'' +
", name='" + name + '\'' +
", url='" + url + '\'' +
'}';
}
}
@@ -26,14 +26,14 @@ import java.util.Base64;
* Implements necessary calls to the Sagan API See https://spring.io/restdocs/index.html
*/
public class SaganApi {
private String baseUrl = "https://spring.io/api";
private String baseUrl = "https://api.spring.io";
private OkHttpClient client;
private Gson gson = new Gson();
public SaganApi(String gitHubToken) {
public SaganApi(String username, String gitHubToken) {
this.client = new OkHttpClient.Builder()
.addInterceptor(new BasicInterceptor("not-used", gitHubToken))
.addInterceptor(new BasicInterceptor(username, gitHubToken))
.build();
}
@@ -20,6 +20,9 @@ import org.gradle.api.DefaultTask;
import org.gradle.api.tasks.Input;
import org.gradle.api.tasks.TaskAction;
import org.springframework.gradle.github.user.GitHubUserApi;
import org.springframework.gradle.github.user.User;
public class SaganCreateReleaseTask extends DefaultTask {
@Input
@@ -35,11 +38,22 @@ public class SaganCreateReleaseTask extends DefaultTask {
@TaskAction
public void saganCreateRelease() {
SaganApi sagan = new SaganApi(this.gitHubAccessToken);
GitHubUserApi github = new GitHubUserApi(this.gitHubAccessToken);
User user = github.getUser();
// Antora reference docs URLs for snapshots do not contain -SNAPSHOT
String referenceDocUrl = this.referenceDocUrl;
if (this.version.endsWith("-SNAPSHOT")) {
referenceDocUrl = this.referenceDocUrl
.replace("{version}", this.version)
.replace("-SNAPSHOT", "");
}
SaganApi sagan = new SaganApi(user.getLogin(), this.gitHubAccessToken);
Release release = new Release();
release.setVersion(this.version);
release.setApiDocUrl(this.apiDocUrl);
release.setReferenceDocUrl(this.referenceDocUrl);
release.setReferenceDocUrl(referenceDocUrl);
sagan.createReleaseForProject(release, this.projectName);
}
@@ -20,6 +20,9 @@ import org.gradle.api.DefaultTask;
import org.gradle.api.tasks.Input;
import org.gradle.api.tasks.TaskAction;
import org.springframework.gradle.github.user.GitHubUserApi;
import org.springframework.gradle.github.user.User;
public class SaganDeleteReleaseTask extends DefaultTask {
@Input
@@ -31,7 +34,10 @@ public class SaganDeleteReleaseTask extends DefaultTask {
@TaskAction
public void saganCreateRelease() {
SaganApi sagan = new SaganApi(this.gitHubAccessToken);
GitHubUserApi github = new GitHubUserApi(this.gitHubAccessToken);
User user = github.getUser();
SaganApi sagan = new SaganApi(user.getLogin(), this.gitHubAccessToken);
sagan.deleteReleaseForProject(this.version, this.projectName);
}
@@ -42,7 +42,7 @@ public class SaganApiTests {
public void setup() throws Exception {
this.server = new MockWebServer();
this.server.start();
this.sagan = new SaganApi("mock-oauth-token");
this.sagan = new SaganApi("user", "mock-oauth-token");
this.baseUrl = this.server.url("/api").toString();
this.sagan.setBaseUrl(this.baseUrl);
}
@@ -63,7 +63,7 @@ public class SaganApiTests {
RecordedRequest request = this.server.takeRequest(1, TimeUnit.SECONDS);
assertThat(request.getRequestUrl().toString()).isEqualTo(this.baseUrl + "/projects/spring-security/releases");
assertThat(request.getMethod()).isEqualToIgnoringCase("post");
assertThat(request.getHeaders().get("Authorization")).isEqualTo("Basic bm90LXVzZWQ6bW9jay1vYXV0aC10b2tlbg==");
assertThat(request.getHeaders().get("Authorization")).isEqualTo("Basic dXNlcjptb2NrLW9hdXRoLXRva2Vu");
assertThat(request.getBody().readString(Charset.defaultCharset())).isEqualToIgnoringWhitespace("{\n" +
" \"version\":\"5.6.0-SNAPSHOT\",\n" +
" \"current\":false,\n" +
@@ -79,7 +79,7 @@ public class SaganApiTests {
RecordedRequest request = this.server.takeRequest(1, TimeUnit.SECONDS);
assertThat(request.getRequestUrl().toString()).isEqualTo(this.baseUrl + "/projects/spring-security/releases/5.6.0-SNAPSHOT");
assertThat(request.getMethod()).isEqualToIgnoringCase("delete");
assertThat(request.getHeaders().get("Authorization")).isEqualTo("Basic bm90LXVzZWQ6bW9jay1vYXV0aC10b2tlbg==");
assertThat(request.getHeaders().get("Authorization")).isEqualTo("Basic dXNlcjptb2NrLW9hdXRoLXRva2Vu");
assertThat(request.getBody().readString(Charset.defaultCharset())).isEmpty();
}
}
@@ -0,0 +1,106 @@
/*
* Copyright 2020-2023 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 org.springframework.gradle.github.user;
import okhttp3.mockwebserver.MockResponse;
import okhttp3.mockwebserver.MockWebServer;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
/**
* @author Steve Riesenberg
*/
public class GitHubUserApiTests {
private GitHubUserApi gitHubUserApi;
private MockWebServer server;
private String baseUrl;
@BeforeEach
public void setup() throws Exception {
this.server = new MockWebServer();
this.server.start();
this.baseUrl = this.server.url("/api").toString();
this.gitHubUserApi = new GitHubUserApi("mock-oauth-token");
this.gitHubUserApi.setBaseUrl(this.baseUrl);
}
@AfterEach
public void cleanup() throws Exception {
this.server.shutdown();
}
@Test
public void getUserWhenValidParametersThenSuccess() {
// @formatter:off
String responseJson = "{\n" +
" \"avatar_url\": \"https://avatars.githubusercontent.com/u/583231?v=4\",\n" +
" \"bio\": null,\n" +
" \"blog\": \"https://github.blog\",\n" +
" \"company\": \"@github\",\n" +
" \"created_at\": \"2011-01-25T18:44:36Z\",\n" +
" \"email\": null,\n" +
" \"events_url\": \"https://api.github.com/users/octocat/events{/privacy}\",\n" +
" \"followers\": 8481,\n" +
" \"followers_url\": \"https://api.github.com/users/octocat/followers\",\n" +
" \"following\": 9,\n" +
" \"following_url\": \"https://api.github.com/users/octocat/following{/other_user}\",\n" +
" \"gists_url\": \"https://api.github.com/users/octocat/gists{/gist_id}\",\n" +
" \"gravatar_id\": \"\",\n" +
" \"hireable\": null,\n" +
" \"html_url\": \"https://github.com/octocat\",\n" +
" \"id\": 583231,\n" +
" \"location\": \"San Francisco\",\n" +
" \"login\": \"octocat\",\n" +
" \"name\": \"The Octocat\",\n" +
" \"node_id\": \"MDQ6VXNlcjU4MzIzMQ==\",\n" +
" \"organizations_url\": \"https://api.github.com/users/octocat/orgs\",\n" +
" \"public_gists\": 8,\n" +
" \"public_repos\": 8,\n" +
" \"received_events_url\": \"https://api.github.com/users/octocat/received_events\",\n" +
" \"repos_url\": \"https://api.github.com/users/octocat/repos\",\n" +
" \"site_admin\": false,\n" +
" \"starred_url\": \"https://api.github.com/users/octocat/starred{/owner}{/repo}\",\n" +
" \"subscriptions_url\": \"https://api.github.com/users/octocat/subscriptions\",\n" +
" \"twitter_username\": null,\n" +
" \"type\": \"User\",\n" +
" \"updated_at\": \"2023-02-25T12:14:58Z\",\n" +
" \"url\": \"https://api.github.com/users/octocat\"\n" +
"}";
// @formatter:on
this.server.enqueue(new MockResponse().setBody(responseJson));
User user = this.gitHubUserApi.getUser();
assertThat(user.getId()).isEqualTo(583231);
assertThat(user.getLogin()).isEqualTo("octocat");
assertThat(user.getName()).isEqualTo("The Octocat");
assertThat(user.getUrl()).isEqualTo("https://api.github.com/users/octocat");
}
@Test
public void getUserWhenErrorResponseThenException() {
this.server.enqueue(new MockResponse().setResponseCode(400));
// @formatter:off
assertThatExceptionOfType(RuntimeException.class)
.isThrownBy(() -> this.gitHubUserApi.getUser());
// @formatter:on
}
}
@@ -46,6 +46,7 @@ import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.verifyZeroInteractions;
/**
* Tests {@link CasAuthenticationFilter}.
@@ -176,7 +177,7 @@ public class CasAuthenticationFilterTests {
assertThat(SecurityContextHolder.getContext().getAuthentication()).isNotNull()
.withFailMessage("Authentication should not be null");
verify(chain).doFilter(request, response);
verifyNoMoreInteractions(successHandler);
verifyZeroInteractions(successHandler);
// validate for when the filterProcessUrl matches
filter.setFilterProcessesUrl(request.getServletPath());
SecurityContextHolder.clearContext();
@@ -228,7 +229,7 @@ public class CasAuthenticationFilterTests {
filter.setProxyGrantingTicketStorage(mock(ProxyGrantingTicketStorage.class));
filter.setProxyReceptorUrl(request.getServletPath());
filter.doFilter(request, response, chain);
verifyNoMoreInteractions(chain);
verifyZeroInteractions(chain);
}
}
+1 -34
View File
@@ -113,6 +113,7 @@ dependencies {
testRuntimeOnly 'org.hsqldb:hsqldb'
}
rncToXsd {
rncDir = file('src/main/resources/org/springframework/security/config/')
xsdDir = rncDir
@@ -129,37 +130,3 @@ tasks.withType(KotlinCompile).configureEach {
}
build.dependsOn rncToXsd
compileTestJava {
exclude "org/springframework/security/config/annotation/web/configurers/saml2/**", "org/springframework/security/config/http/Saml2*"
}
task compileSaml2TestJava(type: JavaCompile) {
javaCompiler = javaToolchains.compilerFor {
languageVersion = JavaLanguageVersion.of(11)
}
source = sourceSets.test.java.srcDirs
include "org/springframework/security/config/annotation/web/configurers/saml2/**", "org/springframework/security/config/http/Saml2*"
classpath = sourceSets.test.compileClasspath
destinationDirectory = new File("${buildDir}/classes/java/test")
options.sourcepath = sourceSets.test.java.getSourceDirectories()
}
task saml2Tests(type: Test) {
javaLauncher = javaToolchains.launcherFor {
languageVersion = JavaLanguageVersion.of(11)
}
filter {
includeTestsMatching "org.springframework.security.config.annotation.web.configurers.saml2.*"
}
useJUnitPlatform()
dependsOn compileSaml2TestJava
}
test {
shouldRunAfter saml2Tests
}
tasks.named('check') {
dependsOn saml2Tests
}
@@ -95,7 +95,7 @@ public final class SecurityNamespaceHandler implements NamespaceHandler {
if (!namespaceMatchesVersion(element)) {
pc.getReaderContext().fatal("You cannot use a spring-security-2.0.xsd or spring-security-3.0.xsd or "
+ "spring-security-3.1.xsd schema or spring-security-3.2.xsd schema or spring-security-4.0.xsd schema "
+ "with Spring Security 5.8. Please update your schema declarations to the 5.8 schema.", element);
+ "with Spring Security 5.7. Please update your schema declarations to the 5.7 schema.", element);
}
String name = pc.getDelegate().getLocalName(element);
BeanDefinitionParser parser = this.parsers.get(name);
@@ -218,7 +218,7 @@ public final class SecurityNamespaceHandler implements NamespaceHandler {
private boolean matchesVersionInternal(Element element) {
String schemaLocation = element.getAttributeNS("http://www.w3.org/2001/XMLSchema-instance", "schemaLocation");
return schemaLocation.matches("(?m).*spring-security-5\\.8.*.xsd.*")
return schemaLocation.matches("(?m).*spring-security-5\\.7.*.xsd.*")
|| schemaLocation.matches("(?m).*spring-security.xsd.*")
|| !schemaLocation.matches("(?m).*spring-security.*");
}
@@ -221,6 +221,7 @@ public abstract class AbstractConfiguredSecurityBuilder<O, B extends SecurityBui
if (configs == null) {
return new ArrayList<>();
}
removeFromConfigurersAddedInInitializing(clazz);
return new ArrayList<>(configs);
}
@@ -253,11 +254,16 @@ public abstract class AbstractConfiguredSecurityBuilder<O, B extends SecurityBui
if (configs == null) {
return null;
}
removeFromConfigurersAddedInInitializing(clazz);
Assert.state(configs.size() == 1,
() -> "Only one configurer expected for type " + clazz + ", but got " + configs);
return (C) configs.get(0);
}
private <C extends SecurityConfigurer<O, B>> void removeFromConfigurersAddedInInitializing(Class<C> clazz) {
this.configurersAddedInInitializing.removeIf(clazz::isInstance);
}
/**
* Specifies the {@link ObjectPostProcessor} to use.
* @param objectPostProcessor the {@link ObjectPostProcessor} to use. Cannot be null
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 the original author or authors.
* Copyright 2002-2013 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.
@@ -43,9 +43,7 @@ import org.springframework.security.config.annotation.authentication.configurati
*
* @author Rob Winch
* @since 3.2
* @deprecated Use {@link EnableMethodSecurity} instead
*/
@Deprecated
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@@ -26,7 +26,6 @@ import org.springframework.context.annotation.AdviceMode;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.core.Ordered;
import org.springframework.security.authorization.ReactiveAuthorizationManager;
/**
*
@@ -70,11 +69,4 @@ public @interface EnableReactiveMethodSecurity {
*/
int order() default Ordered.LOWEST_PRECEDENCE;
/**
* Indicate whether {@link ReactiveAuthorizationManager} based Method Security to be
* used.
* @since 5.8
*/
boolean useAuthorizationManager() default false;
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 the original author or authors.
* Copyright 2002-2013 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.
@@ -36,9 +36,7 @@ import org.springframework.core.type.AnnotationMetadata;
*
* @author Rob Winch
* @since 3.2
* @deprecated Use {@link EnableMethodSecurity} instead
*/
@Deprecated
class GlobalMethodSecurityAspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
/**
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 the original author or authors.
* Copyright 2002-2021 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.
@@ -73,8 +73,6 @@ import org.springframework.security.config.annotation.ObjectPostProcessor;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
import org.springframework.security.config.core.GrantedAuthorityDefaults;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.context.SecurityContextHolderStrategy;
import org.springframework.util.Assert;
/**
@@ -86,11 +84,7 @@ import org.springframework.util.Assert;
* @author Eddú Meléndez
* @since 3.2
* @see EnableGlobalMethodSecurity
* @deprecated Use {@link PrePostMethodSecurityConfiguration},
* {@link SecuredMethodSecurityConfiguration}, or
* {@link Jsr250MethodSecurityConfiguration} instead
*/
@Deprecated
@Configuration(proxyBeanMethods = false)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public class GlobalMethodSecurityConfiguration implements ImportAware, SmartInitializingSingleton, BeanFactoryAware {
@@ -107,9 +101,6 @@ public class GlobalMethodSecurityConfiguration implements ImportAware, SmartInit
};
private SecurityContextHolderStrategy securityContextHolderStrategy = SecurityContextHolder
.getContextHolderStrategy();
private DefaultMethodSecurityExpressionHandler defaultMethodExpressionHandler = new DefaultMethodSecurityExpressionHandler();
private AuthenticationManager authenticationManager;
@@ -152,7 +143,6 @@ public class GlobalMethodSecurityConfiguration implements ImportAware, SmartInit
this.methodSecurityInterceptor.setAccessDecisionManager(accessDecisionManager());
this.methodSecurityInterceptor.setAfterInvocationManager(afterInvocationManager());
this.methodSecurityInterceptor.setSecurityMetadataSource(methodSecurityMetadataSource);
this.methodSecurityInterceptor.setSecurityContextHolderStrategy(this.securityContextHolderStrategy);
RunAsManager runAsManager = runAsManager();
if (runAsManager != null) {
this.methodSecurityInterceptor.setRunAsManager(runAsManager);
@@ -421,12 +411,6 @@ public class GlobalMethodSecurityConfiguration implements ImportAware, SmartInit
this.expressionHandler = handlers.get(0);
}
@Autowired(required = false)
void setSecurityContextHolderStrategy(SecurityContextHolderStrategy securityContextHolderStrategy) {
Assert.notNull(securityContextHolderStrategy, "securityContextHolderStrategy cannot be null");
this.securityContextHolderStrategy = securityContextHolderStrategy;
}
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
this.context = beanFactory;
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 the original author or authors.
* Copyright 2002-2018 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.
@@ -34,9 +34,7 @@ import org.springframework.util.ClassUtils;
*
* @author Rob Winch
* @since 3.2
* @deprecated Use {@link MethodSecuritySelector} instead
*/
@Deprecated
final class GlobalMethodSecuritySelector implements ImportSelector {
@Override
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 the original author or authors.
* Copyright 2002-2019 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.
@@ -24,7 +24,6 @@ import org.springframework.security.access.annotation.Jsr250MethodSecurityMetada
@Configuration(proxyBeanMethods = false)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
@Deprecated
class Jsr250MetadataSourceConfiguration {
@Bean
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 the original author or authors.
* Copyright 2002-2021 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.
@@ -25,8 +25,6 @@ import org.springframework.context.annotation.Role;
import org.springframework.security.authorization.method.AuthorizationManagerBeforeMethodInterceptor;
import org.springframework.security.authorization.method.Jsr250AuthorizationManager;
import org.springframework.security.config.core.GrantedAuthorityDefaults;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.context.SecurityContextHolderStrategy;
/**
* {@link Configuration} for enabling JSR-250 Spring Security Method Security.
@@ -42,16 +40,10 @@ final class Jsr250MethodSecurityConfiguration {
private final Jsr250AuthorizationManager jsr250AuthorizationManager = new Jsr250AuthorizationManager();
private SecurityContextHolderStrategy securityContextHolderStrategy = SecurityContextHolder
.getContextHolderStrategy();
@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
Advisor jsr250AuthorizationMethodInterceptor() {
AuthorizationManagerBeforeMethodInterceptor interceptor = AuthorizationManagerBeforeMethodInterceptor
.jsr250(this.jsr250AuthorizationManager);
interceptor.setSecurityContextHolderStrategy(this.securityContextHolderStrategy);
return interceptor;
return AuthorizationManagerBeforeMethodInterceptor.jsr250(this.jsr250AuthorizationManager);
}
@Autowired(required = false)
@@ -59,9 +51,4 @@ final class Jsr250MethodSecurityConfiguration {
this.jsr250AuthorizationManager.setRolePrefix(grantedAuthorityDefaults.getRolePrefix());
}
@Autowired(required = false)
void setSecurityContextHolderStrategy(SecurityContextHolderStrategy securityContextHolderStrategy) {
this.securityContextHolderStrategy = securityContextHolderStrategy;
}
}
@@ -1,78 +0,0 @@
/*
* Copyright 2002-2022 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 org.springframework.security.config.annotation.method.configuration;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.type.AnnotationMetadata;
/**
* Registers an
* {@link org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator
* AnnotationAwareAspectJAutoProxyCreator} against the current
* {@link BeanDefinitionRegistry} as appropriate based on a given @
* {@link EnableMethodSecurity} annotation.
*
* <p>
* Note: This class is necessary because AspectJAutoProxyRegistrar only supports
* EnableAspectJAutoProxy.
* </p>
*
* @author Josh Cummings
* @since 5.8
*/
class MethodSecurityAspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
/**
* Register, escalate, and configure the AspectJ auto proxy creator based on the value
* of the @{@link EnableMethodSecurity#proxyTargetClass()} attribute on the importing
* {@code @Configuration} class.
*/
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
registerBeanDefinition("preFilterAuthorizationMethodInterceptor",
"org.springframework.security.authorization.method.aspectj.PreFilterAspect", "preFilterAspect$0",
registry);
registerBeanDefinition("postFilterAuthorizationMethodInterceptor",
"org.springframework.security.authorization.method.aspectj.PostFilterAspect", "postFilterAspect$0",
registry);
registerBeanDefinition("preAuthorizeAuthorizationMethodInterceptor",
"org.springframework.security.authorization.method.aspectj.PreAuthorizeAspect", "preAuthorizeAspect$0",
registry);
registerBeanDefinition("postAuthorizeAuthorizationMethodInterceptor",
"org.springframework.security.authorization.method.aspectj.PostAuthorizeAspect",
"postAuthorizeAspect$0", registry);
registerBeanDefinition("securedAuthorizationMethodInterceptor",
"org.springframework.security.authorization.method.aspectj.SecuredAspect", "securedAspect$0", registry);
}
private void registerBeanDefinition(String beanName, String aspectClassName, String aspectBeanName,
BeanDefinitionRegistry registry) {
if (!registry.containsBeanDefinition(beanName)) {
return;
}
BeanDefinition interceptor = registry.getBeanDefinition(beanName);
BeanDefinitionBuilder aspect = BeanDefinitionBuilder.rootBeanDefinition(aspectClassName);
aspect.setFactoryMethod("aspectOf");
aspect.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
aspect.addPropertyValue("securityInterceptor", interceptor);
registry.registerBeanDefinition(aspectBeanName, aspect.getBeanDefinition());
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 the original author or authors.
* Copyright 2002-2018 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.
@@ -32,9 +32,7 @@ import org.springframework.util.MultiValueMap;
* @author Rob Winch
* @since 4.0.2
* @see GlobalMethodSecuritySelector
* @deprecated Use {@link MethodSecuritySelector} instead
*/
@Deprecated
class MethodSecurityMetadataSourceAdvisorRegistrar implements ImportBeanDefinitionRegistrar {
/**
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 the original author or authors.
* Copyright 2002-2021 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.
@@ -62,17 +62,11 @@ final class MethodSecuritySelector implements ImportSelector {
private static final String[] IMPORTS = new String[] { AutoProxyRegistrar.class.getName() };
private static final String[] ASPECTJ_IMPORTS = new String[] {
MethodSecurityAspectJAutoProxyRegistrar.class.getName() };
@Override
protected String[] selectImports(@NonNull AdviceMode adviceMode) {
if (adviceMode == AdviceMode.PROXY) {
return IMPORTS;
}
if (adviceMode == AdviceMode.ASPECTJ) {
return ASPECTJ_IMPORTS;
}
throw new IllegalStateException("AdviceMode '" + adviceMode + "' is not supported");
}
@@ -34,7 +34,6 @@ import org.springframework.security.authorization.method.PostFilterAuthorization
import org.springframework.security.authorization.method.PreAuthorizeAuthorizationManager;
import org.springframework.security.authorization.method.PreFilterAuthorizationMethodInterceptor;
import org.springframework.security.config.core.GrantedAuthorityDefaults;
import org.springframework.security.core.context.SecurityContextHolderStrategy;
/**
* Base {@link Configuration} for enabling Spring Security Method Security.
@@ -110,14 +109,6 @@ final class PrePostMethodSecurityConfiguration {
this.postFilterAuthorizationMethodInterceptor.setExpressionHandler(methodSecurityExpressionHandler);
}
@Autowired(required = false)
void setSecurityContextHolderStrategy(SecurityContextHolderStrategy strategy) {
this.preFilterAuthorizationMethodInterceptor.setSecurityContextHolderStrategy(strategy);
this.preAuthorizeAuthorizationMethodInterceptor.setSecurityContextHolderStrategy(strategy);
this.postAuthorizeAuthorizaitonMethodInterceptor.setSecurityContextHolderStrategy(strategy);
this.postFilterAuthorizationMethodInterceptor.setSecurityContextHolderStrategy(strategy);
}
@Autowired(required = false)
void setGrantedAuthorityDefaults(GrantedAuthorityDefaults grantedAuthorityDefaults) {
this.expressionHandler.setDefaultRolePrefix(grantedAuthorityDefaults.getRolePrefix());
@@ -1,87 +0,0 @@
/*
* Copyright 2002-2022 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 org.springframework.security.config.annotation.method.configuration;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Role;
import org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler;
import org.springframework.security.access.expression.method.MethodSecurityExpressionHandler;
import org.springframework.security.authentication.ReactiveAuthenticationManager;
import org.springframework.security.authorization.method.AuthorizationManagerAfterReactiveMethodInterceptor;
import org.springframework.security.authorization.method.AuthorizationManagerBeforeReactiveMethodInterceptor;
import org.springframework.security.authorization.method.PostAuthorizeReactiveAuthorizationManager;
import org.springframework.security.authorization.method.PostFilterAuthorizationReactiveMethodInterceptor;
import org.springframework.security.authorization.method.PreAuthorizeReactiveAuthorizationManager;
import org.springframework.security.authorization.method.PreFilterAuthorizationReactiveMethodInterceptor;
import org.springframework.security.config.core.GrantedAuthorityDefaults;
/**
* Configuration for a {@link ReactiveAuthenticationManager} based Method Security.
*
* @author Evgeniy Cheban
* @since 5.8
*/
@Configuration(proxyBeanMethods = false)
final class ReactiveAuthorizationManagerMethodSecurityConfiguration {
@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
PreFilterAuthorizationReactiveMethodInterceptor preFilterInterceptor(
MethodSecurityExpressionHandler expressionHandler) {
return new PreFilterAuthorizationReactiveMethodInterceptor(expressionHandler);
}
@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
AuthorizationManagerBeforeReactiveMethodInterceptor preAuthorizeInterceptor(
MethodSecurityExpressionHandler expressionHandler) {
PreAuthorizeReactiveAuthorizationManager authorizationManager = new PreAuthorizeReactiveAuthorizationManager(
expressionHandler);
return AuthorizationManagerBeforeReactiveMethodInterceptor.preAuthorize(authorizationManager);
}
@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
PostFilterAuthorizationReactiveMethodInterceptor postFilterInterceptor(
MethodSecurityExpressionHandler expressionHandler) {
return new PostFilterAuthorizationReactiveMethodInterceptor(expressionHandler);
}
@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
AuthorizationManagerAfterReactiveMethodInterceptor postAuthorizeInterceptor(
MethodSecurityExpressionHandler expressionHandler) {
PostAuthorizeReactiveAuthorizationManager authorizationManager = new PostAuthorizeReactiveAuthorizationManager(
expressionHandler);
return AuthorizationManagerAfterReactiveMethodInterceptor.postAuthorize(authorizationManager);
}
@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
DefaultMethodSecurityExpressionHandler methodSecurityExpressionHandler(
@Autowired(required = false) GrantedAuthorityDefaults grantedAuthorityDefaults) {
DefaultMethodSecurityExpressionHandler handler = new DefaultMethodSecurityExpressionHandler();
if (grantedAuthorityDefaults != null) {
handler.setDefaultRolePrefix(grantedAuthorityDefaults.getRolePrefix());
}
return handler;
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 the original author or authors.
* Copyright 2002-2017 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.
@@ -17,55 +17,37 @@
package org.springframework.security.config.annotation.method.configuration;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.springframework.context.annotation.AdviceMode;
import org.springframework.context.annotation.AdviceModeImportSelector;
import org.springframework.context.annotation.AutoProxyRegistrar;
import org.springframework.context.annotation.ImportSelector;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.lang.NonNull;
/**
* @author Rob Winch
* @author Evgeniy Cheban
* @since 5.0
*/
class ReactiveMethodSecuritySelector implements ImportSelector {
private final ImportSelector autoProxy = new AutoProxyRegistrarSelector();
class ReactiveMethodSecuritySelector extends AdviceModeImportSelector<EnableReactiveMethodSecurity> {
@Override
public String[] selectImports(AnnotationMetadata importMetadata) {
if (!importMetadata.hasAnnotation(EnableReactiveMethodSecurity.class.getName())) {
return new String[0];
protected String[] selectImports(AdviceMode adviceMode) {
if (adviceMode == AdviceMode.PROXY) {
return getProxyImports();
}
EnableReactiveMethodSecurity annotation = importMetadata.getAnnotations()
.get(EnableReactiveMethodSecurity.class).synthesize();
List<String> imports = new ArrayList<>(Arrays.asList(this.autoProxy.selectImports(importMetadata)));
if (annotation.useAuthorizationManager()) {
imports.add(ReactiveAuthorizationManagerMethodSecurityConfiguration.class.getName());
}
else {
imports.add(ReactiveMethodSecurityConfiguration.class.getName());
}
return imports.toArray(new String[0]);
throw new IllegalStateException("AdviceMode " + adviceMode + " is not supported");
}
private static final class AutoProxyRegistrarSelector
extends AdviceModeImportSelector<EnableReactiveMethodSecurity> {
private static final String[] IMPORTS = new String[] { AutoProxyRegistrar.class.getName() };
@Override
protected String[] selectImports(@NonNull AdviceMode adviceMode) {
if (adviceMode == AdviceMode.PROXY) {
return IMPORTS;
}
throw new IllegalStateException("AdviceMode " + adviceMode + " is not supported");
}
/**
* Return the imports to use if the {@link AdviceMode} is set to
* {@link AdviceMode#PROXY}.
* <p>
* Take care of adding the necessary JSR-107 import if it is available.
*/
private String[] getProxyImports() {
List<String> result = new ArrayList<>();
result.add(AutoProxyRegistrar.class.getName());
result.add(ReactiveMethodSecurityConfiguration.class.getName());
return result.toArray(new String[0]);
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 the original author or authors.
* Copyright 2002-2021 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.
@@ -17,15 +17,12 @@
package org.springframework.security.config.annotation.method.configuration;
import org.springframework.aop.Advisor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Role;
import org.springframework.security.access.annotation.Secured;
import org.springframework.security.authorization.method.AuthorizationManagerBeforeMethodInterceptor;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.context.SecurityContextHolderStrategy;
/**
* {@link Configuration} for enabling {@link Secured} Spring Security Method Security.
@@ -39,20 +36,10 @@ import org.springframework.security.core.context.SecurityContextHolderStrategy;
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
final class SecuredMethodSecurityConfiguration {
private SecurityContextHolderStrategy securityContextHolderStrategy = SecurityContextHolder
.getContextHolderStrategy();
@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
Advisor securedAuthorizationMethodInterceptor() {
AuthorizationManagerBeforeMethodInterceptor interceptor = AuthorizationManagerBeforeMethodInterceptor.secured();
interceptor.setSecurityContextHolderStrategy(this.securityContextHolderStrategy);
return interceptor;
}
@Autowired(required = false)
void setSecurityContextHolderStrategy(SecurityContextHolderStrategy securityContextHolderStrategy) {
this.securityContextHolderStrategy = securityContextHolderStrategy;
return AuthorizationManagerBeforeMethodInterceptor.secured();
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 the original author or authors.
* Copyright 2002-2019 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.
@@ -35,7 +35,6 @@ import org.springframework.security.web.util.matcher.DispatcherTypeRequestMatche
import org.springframework.security.web.util.matcher.RegexRequestMatcher;
import org.springframework.security.web.util.matcher.RequestMatcher;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.web.servlet.handler.HandlerMappingIntrospector;
/**
@@ -51,21 +50,12 @@ public abstract class AbstractRequestMatcherRegistry<C> {
private static final String HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME = "mvcHandlerMappingIntrospector";
private static final String HANDLER_MAPPING_INTROSPECTOR = "org.springframework.web.servlet.handler.HandlerMappingIntrospector";
private static final boolean mvcPresent;
private static final RequestMatcher ANY_REQUEST = AnyRequestMatcher.INSTANCE;
private ApplicationContext context;
private boolean anyRequestConfigured = false;
static {
mvcPresent = ClassUtils.isPresent(HANDLER_MAPPING_INTROSPECTOR,
AbstractRequestMatcherRegistry.class.getClassLoader());
}
protected final void setApplicationContext(ApplicationContext context) {
this.context = context;
}
@@ -95,9 +85,7 @@ public abstract class AbstractRequestMatcherRegistry<C> {
* instances.
* @param method the {@link HttpMethod} to use for any {@link HttpMethod}.
* @return the object that is chained after creating the {@link RequestMatcher}
* @deprecated use {@link #requestMatchers(HttpMethod)} instead
*/
@Deprecated
public C antMatchers(HttpMethod method) {
return antMatchers(method, "/**");
}
@@ -111,9 +99,7 @@ public abstract class AbstractRequestMatcherRegistry<C> {
* @param antPatterns the ant patterns to create. If {@code null} or empty, then
* matches on nothing.
* @return the object that is chained after creating the {@link RequestMatcher}
* @deprecated use {@link #requestMatchers(HttpMethod, String...)} instead
*/
@Deprecated
public C antMatchers(HttpMethod method, String... antPatterns) {
Assert.state(!this.anyRequestConfigured, "Can't configure antMatchers after anyRequest");
return chainRequestMatchers(RequestMatchers.antMatchers(method, antPatterns));
@@ -126,9 +112,7 @@ public abstract class AbstractRequestMatcherRegistry<C> {
* @param antPatterns the ant patterns to create
* {@link org.springframework.security.web.util.matcher.AntPathRequestMatcher} from
* @return the object that is chained after creating the {@link RequestMatcher}
* @deprecated use {@link #requestMatchers(String...)} instead
*/
@Deprecated
public C antMatchers(String... antPatterns) {
Assert.state(!this.anyRequestConfigured, "Can't configure antMatchers after anyRequest");
return chainRequestMatchers(RequestMatchers.antMatchers(antPatterns));
@@ -148,9 +132,7 @@ public abstract class AbstractRequestMatcherRegistry<C> {
* @param mvcPatterns the patterns to match on. The rules for matching are defined by
* Spring MVC
* @return the object that is chained after creating the {@link RequestMatcher}.
* @deprecated use {@link #requestMatchers(String...)} instead
*/
@Deprecated
public abstract C mvcMatchers(String... mvcPatterns);
/**
@@ -168,9 +150,7 @@ public abstract class AbstractRequestMatcherRegistry<C> {
* @param mvcPatterns the patterns to match on. The rules for matching are defined by
* Spring MVC
* @return the object that is chained after creating the {@link RequestMatcher}.
* @deprecated use {@link #requestMatchers(HttpMethod, String...)} instead
*/
@Deprecated
public abstract C mvcMatchers(HttpMethod method, String... mvcPatterns);
/**
@@ -210,10 +190,7 @@ public abstract class AbstractRequestMatcherRegistry<C> {
* @param regexPatterns the regular expressions to create
* {@link org.springframework.security.web.util.matcher.RegexRequestMatcher} from
* @return the object that is chained after creating the {@link RequestMatcher}
* @deprecated use {@link #requestMatchers(RequestMatcher...)} with a
* {@link RegexRequestMatcher} instead
*/
@Deprecated
public C regexMatchers(HttpMethod method, String... regexPatterns) {
Assert.state(!this.anyRequestConfigured, "Can't configure regexMatchers after anyRequest");
return chainRequestMatchers(RequestMatchers.regexMatchers(method, regexPatterns));
@@ -226,10 +203,7 @@ public abstract class AbstractRequestMatcherRegistry<C> {
* @param regexPatterns the regular expressions to create
* {@link org.springframework.security.web.util.matcher.RegexRequestMatcher} from
* @return the object that is chained after creating the {@link RequestMatcher}
* @deprecated use {@link #requestMatchers(RequestMatcher...)} with a
* {@link RegexRequestMatcher} instead
*/
@Deprecated
public C regexMatchers(String... regexPatterns) {
Assert.state(!this.anyRequestConfigured, "Can't configure regexMatchers after anyRequest");
return chainRequestMatchers(RequestMatchers.regexMatchers(regexPatterns));
@@ -276,81 +250,6 @@ public abstract class AbstractRequestMatcherRegistry<C> {
return chainRequestMatchers(Arrays.asList(requestMatchers));
}
/**
* <p>
* If the {@link HandlerMappingIntrospector} is available in the classpath, maps to an
* {@link MvcRequestMatcher} that also specifies a specific {@link HttpMethod} to
* match on. This matcher will use the same rules that Spring MVC uses for matching.
* For example, often times a mapping of the path "/path" will match on "/path",
* "/path/", "/path.html", etc. If the {@link HandlerMappingIntrospector} is not
* available, maps to an {@link AntPathRequestMatcher}.
* </p>
* <p>
* If a specific {@link RequestMatcher} must be specified, use
* {@link #requestMatchers(RequestMatcher...)} instead
* </p>
* @param method the {@link HttpMethod} to use or {@code null} for any
* {@link HttpMethod}.
* @param patterns the patterns to match on. The rules for matching are defined by
* Spring MVC if {@link MvcRequestMatcher} is used
* @return the object that is chained after creating the {@link RequestMatcher}.
* @since 5.8
*/
public C requestMatchers(HttpMethod method, String... patterns) {
List<RequestMatcher> matchers = new ArrayList<>();
if (mvcPresent) {
matchers.addAll(createMvcMatchers(method, patterns));
}
else {
matchers.addAll(RequestMatchers.antMatchers(method, patterns));
}
return requestMatchers(matchers.toArray(new RequestMatcher[0]));
}
/**
* <p>
* If the {@link HandlerMappingIntrospector} is available in the classpath, maps to an
* {@link MvcRequestMatcher} that does not care which {@link HttpMethod} is used. This
* matcher will use the same rules that Spring MVC uses for matching. For example,
* often times a mapping of the path "/path" will match on "/path", "/path/",
* "/path.html", etc. If the {@link HandlerMappingIntrospector} is not available, maps
* to an {@link AntPathRequestMatcher}.
* </p>
* <p>
* If a specific {@link RequestMatcher} must be specified, use
* {@link #requestMatchers(RequestMatcher...)} instead
* </p>
* @param patterns the patterns to match on. The rules for matching are defined by
* Spring MVC if {@link MvcRequestMatcher} is used
* @return the object that is chained after creating the {@link RequestMatcher}.
* @since 5.8
*/
public C requestMatchers(String... patterns) {
return requestMatchers(null, patterns);
}
/**
* <p>
* If the {@link HandlerMappingIntrospector} is available in the classpath, maps to an
* {@link MvcRequestMatcher} that matches on a specific {@link HttpMethod}. This
* matcher will use the same rules that Spring MVC uses for matching. For example,
* often times a mapping of the path "/path" will match on "/path", "/path/",
* "/path.html", etc. If the {@link HandlerMappingIntrospector} is not available, maps
* to an {@link AntPathRequestMatcher}.
* </p>
* <p>
* If a specific {@link RequestMatcher} must be specified, use
* {@link #requestMatchers(RequestMatcher...)} instead
* </p>
* @param method the {@link HttpMethod} to use or {@code null} for any
* {@link HttpMethod}.
* @return the object that is chained after creating the {@link RequestMatcher}.
* @since 5.8
*/
public C requestMatchers(HttpMethod method) {
return requestMatchers(method, "/**");
}
/**
* Subclasses should implement this method for returning the object that is chained to
* the creation of the {@link RequestMatcher} instances.
@@ -23,7 +23,6 @@ import org.springframework.security.config.annotation.SecurityBuilder;
import org.springframework.security.config.annotation.SecurityConfigurer;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.oauth2.server.resource.web.authentication.BearerTokenAuthenticationFilter;
import org.springframework.security.openid.OpenIDAuthenticationFilter;
import org.springframework.security.web.DefaultSecurityFilterChain;
import org.springframework.security.web.access.ExceptionTranslationFilter;
@@ -142,7 +141,7 @@ public interface HttpSecurityBuilder<H extends HttpSecurityBuilder<H>>
* <li>{@link org.springframework.security.web.authentication.ui.DefaultLogoutPageGeneratingFilter}</li>
* <li>{@link ConcurrentSessionFilter}</li>
* <li>{@link DigestAuthenticationFilter}</li>
* <li>{@link BearerTokenAuthenticationFilter}</li>
* <li>{@link org.springframework.security.oauth2.server.resource.web.BearerTokenAuthenticationFilter}</li>
* <li>{@link BasicAuthenticationFilter}</li>
* <li>{@link RequestCacheAwareFilter}</li>
* <li>{@link SecurityContextHolderAwareRequestFilter}</li>
@@ -85,7 +85,7 @@ final class FilterOrderRegistration {
"org.springframework.security.oauth2.client.web.OAuth2AuthorizationRequestRedirectFilter",
order.next());
this.filterToOrder.put(
"org.springframework.security.saml2.provider.service.web.Saml2WebSsoAuthenticationRequestFilter",
"org.springframework.security.saml2.provider.service.servlet.filter.Saml2WebSsoAuthenticationRequestFilter",
order.next());
put(X509AuthenticationFilter.class, order.next());
put(AbstractPreAuthenticatedProcessingFilter.class, order.next());
@@ -93,7 +93,7 @@ final class FilterOrderRegistration {
this.filterToOrder.put("org.springframework.security.oauth2.client.web.OAuth2LoginAuthenticationFilter",
order.next());
this.filterToOrder.put(
"org.springframework.security.saml2.provider.service.web.authentication.Saml2WebSsoAuthenticationFilter",
"org.springframework.security.saml2.provider.service.servlet.filter.Saml2WebSsoAuthenticationFilter",
order.next());
put(UsernamePasswordAuthenticationFilter.class, order.next());
order.next(); // gh-8105
@@ -103,7 +103,7 @@ final class FilterOrderRegistration {
put(ConcurrentSessionFilter.class, order.next());
put(DigestAuthenticationFilter.class, order.next());
this.filterToOrder.put(
"org.springframework.security.oauth2.server.resource.web.authentication.BearerTokenAuthenticationFilter",
"org.springframework.security.oauth2.server.resource.web.BearerTokenAuthenticationFilter",
order.next());
put(BasicAuthenticationFilter.class, order.next());
put(RequestCacheAwareFilter.class, order.next());
@@ -28,7 +28,6 @@ import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.context.ApplicationContext;
import org.springframework.core.OrderComparator;
import org.springframework.core.Ordered;
@@ -93,7 +92,6 @@ import org.springframework.security.web.util.matcher.OrRequestMatcher;
import org.springframework.security.web.util.matcher.RegexRequestMatcher;
import org.springframework.security.web.util.matcher.RequestMatcher;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.filter.CorsFilter;
import org.springframework.web.servlet.handler.HandlerMappingIntrospector;
@@ -119,7 +117,7 @@ import org.springframework.web.servlet.handler.HandlerMappingIntrospector;
*
* &#064;Bean
* public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
* http.authorizeHttpRequests().requestMatchers(&quot;/**&quot;).hasRole(&quot;USER&quot;).and().formLogin();
* http.authorizeRequests().antMatchers(&quot;/**&quot;).hasRole(&quot;USER&quot;).and().formLogin();
* return http.build();
* }
*
@@ -143,12 +141,6 @@ import org.springframework.web.servlet.handler.HandlerMappingIntrospector;
public final class HttpSecurity extends AbstractConfiguredSecurityBuilder<DefaultSecurityFilterChain, HttpSecurity>
implements SecurityBuilder<DefaultSecurityFilterChain>, HttpSecurityBuilder<HttpSecurity> {
private static final String HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME = "mvcHandlerMappingIntrospector";
private static final String HANDLER_MAPPING_INTROSPECTOR = "org.springframework.web.servlet.handler.HandlerMappingIntrospector";
private static final boolean mvcPresent;
private final RequestMatcherConfigurer requestMatcherConfigurer;
private List<OrderedFilter> filters = new ArrayList<>();
@@ -159,10 +151,6 @@ public final class HttpSecurity extends AbstractConfiguredSecurityBuilder<Defaul
private AuthenticationManager authenticationManager;
static {
mvcPresent = ClassUtils.isPresent(HANDLER_MAPPING_INTROSPECTOR, HttpSecurity.class.getClassLoader());
}
/**
* Creates a new instance
* @param objectPostProcessor the {@link ObjectPostProcessor} that should be used
@@ -1293,10 +1281,8 @@ public final class HttpSecurity extends AbstractConfiguredSecurityBuilder<Defaul
* </pre>
* @return the {@link ExpressionUrlAuthorizationConfigurer} for further customizations
* @throws Exception
* @deprecated Use {@link #authorizeHttpRequests()} instead
* @see #requestMatcher(RequestMatcher)
*/
@Deprecated
public ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry authorizeRequests()
throws Exception {
ApplicationContext context = getContext();
@@ -1409,10 +1395,8 @@ public final class HttpSecurity extends AbstractConfiguredSecurityBuilder<Defaul
* for the {@link ExpressionUrlAuthorizationConfigurer.ExpressionInterceptUrlRegistry}
* @return the {@link HttpSecurity} for further customizations
* @throws Exception
* @deprecated Use {@link #authorizeHttpRequests} instead
* @see #requestMatcher(RequestMatcher)
*/
@Deprecated
public HttpSecurity authorizeRequests(
Customizer<ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry> authorizeRequestsCustomizer)
throws Exception {
@@ -3432,9 +3416,7 @@ public final class HttpSecurity extends AbstractConfiguredSecurityBuilder<Defaul
* }
* </pre>
* @return the {@link RequestMatcherConfigurer} for further customizations
* @deprecated use {@link #securityMatchers()} instead
*/
@Deprecated
public RequestMatcherConfigurer requestMatchers() {
return this.requestMatcherConfigurer;
}
@@ -3566,9 +3548,7 @@ public final class HttpSecurity extends AbstractConfiguredSecurityBuilder<Defaul
* @param requestMatcherCustomizer the {@link Customizer} to provide more options for
* the {@link RequestMatcherConfigurer}
* @return the {@link HttpSecurity} for further customizations
* @deprecated use {@link #securityMatchers(Customizer)} instead
*/
@Deprecated
public HttpSecurity requestMatchers(Customizer<RequestMatcherConfigurer> requestMatcherCustomizer) {
requestMatcherCustomizer.customize(this.requestMatcherConfigurer);
return HttpSecurity.this;
@@ -3588,337 +3568,15 @@ public final class HttpSecurity extends AbstractConfiguredSecurityBuilder<Defaul
* @param requestMatcher the {@link RequestMatcher} to use (i.e. new
* AntPathRequestMatcher("/admin/**","GET") )
* @return the {@link HttpSecurity} for further customizations
* @deprecated use {@link #securityMatcher(RequestMatcher)} instead
* @see #requestMatchers()
* @see #antMatcher(String)
* @see #regexMatcher(String)
*/
@Deprecated
public HttpSecurity requestMatcher(RequestMatcher requestMatcher) {
this.requestMatcher = requestMatcher;
return this;
}
/**
* Allows specifying which {@link HttpServletRequest} instances this
* {@link HttpSecurity} will be invoked on. This method allows for easily invoking the
* {@link HttpSecurity} for multiple different {@link RequestMatcher} instances. If
* only a single {@link RequestMatcher} is necessary consider using
* {@link #securityMatcher(String...)}, or {@link #securityMatcher(RequestMatcher)}.
*
* <p>
* Invoking {@link #securityMatchers()} will not override previous invocations of
* {@link #securityMatchers()}}, {@link #securityMatchers(Customizer)}
* {@link #securityMatcher(String...)} and {@link #securityMatcher(RequestMatcher)}
* </p>
*
* <h3>Example Configurations</h3>
*
* The following configuration enables the {@link HttpSecurity} for URLs that begin
* with "/api/" or "/oauth/".
*
* <pre>
* &#064;Configuration
* &#064;EnableWebSecurity
* public class RequestMatchersSecurityConfig {
*
* &#064;Bean
* public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
* http
* .securityMatchers((matchers) -&gt; matchers
* .requestMatchers(&quot;/api/**&quot;, &quot;/oauth/**&quot;)
* )
* .authorizeHttpRequests((authorize) -&gt; authorize
* anyRequest().hasRole(&quot;USER&quot;)
* )
* .httpBasic(withDefaults());
* return http.build();
* }
*
* &#064;Bean
* public UserDetailsService userDetailsService() {
* UserDetails user = User.withDefaultPasswordEncoder()
* .username(&quot;user&quot;)
* .password(&quot;password&quot;)
* .roles(&quot;USER&quot;)
* .build();
* return new InMemoryUserDetailsManager(user);
* }
* }
* </pre>
*
* The configuration below is the same as the previous configuration.
*
* <pre>
* &#064;Configuration
* &#064;EnableWebSecurity
* public class RequestMatchersSecurityConfig {
*
* &#064;Bean
* public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
* http
* .securityMatchers((matchers) -&gt; matchers
* .requestMatchers(&quot;/api/**&quot;)
* .requestMatchers(&quot;/oauth/**&quot;)
* )
* .authorizeHttpRequests((authorize) -&gt; authorize
* anyRequest().hasRole(&quot;USER&quot;)
* )
* .httpBasic(withDefaults());
* return http.build();
* }
*
* &#064;Bean
* public UserDetailsService userDetailsService() {
* UserDetails user = User.withDefaultPasswordEncoder()
* .username(&quot;user&quot;)
* .password(&quot;password&quot;)
* .roles(&quot;USER&quot;)
* .build();
* return new InMemoryUserDetailsManager(user);
* }
* }
* </pre>
*
* The configuration below is also the same as the above configuration.
*
* <pre>
* &#064;Configuration
* &#064;EnableWebSecurity
* public class RequestMatchersSecurityConfig {
*
* &#064;Bean
* public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
* http
* .securityMatchers((matchers) -&gt; matchers
* .requestMatchers(&quot;/api/**&quot;)
* )
* .securityMatchers((matchers) -&gt; matchers
* .requestMatchers(&quot;/oauth/**&quot;)
* )
* .authorizeHttpRequests((authorize) -&gt; authorize
* anyRequest().hasRole(&quot;USER&quot;)
* )
* .httpBasic(withDefaults());
* return http.build();
* }
*
* &#064;Bean
* public UserDetailsService userDetailsService() {
* UserDetails user = User.withDefaultPasswordEncoder()
* .username(&quot;user&quot;)
* .password(&quot;password&quot;)
* .roles(&quot;USER&quot;)
* .build();
* return new InMemoryUserDetailsManager(user);
* }
* }
* </pre>
* @return the {@link RequestMatcherConfigurer} for further customizations
*/
public RequestMatcherConfigurer securityMatchers() {
return this.requestMatcherConfigurer;
}
/**
* Allows specifying which {@link HttpServletRequest} instances this
* {@link HttpSecurity} will be invoked on. This method allows for easily invoking the
* {@link HttpSecurity} for multiple different {@link RequestMatcher} instances. If
* only a single {@link RequestMatcher} is necessary consider using
* {@link #securityMatcher(String...)}, or {@link #securityMatcher(RequestMatcher)}.
*
* <p>
* Invoking {@link #securityMatchers(Customizer)} will not override previous
* invocations of {@link #securityMatchers()}}, {@link #securityMatchers(Customizer)}
* {@link #securityMatcher(String...)} and {@link #securityMatcher(RequestMatcher)}
* </p>
*
* <h3>Example Configurations</h3>
*
* The following configuration enables the {@link HttpSecurity} for URLs that begin
* with "/api/" or "/oauth/".
*
* <pre>
* &#064;Configuration
* &#064;EnableWebSecurity
* public class RequestMatchersSecurityConfig {
*
* &#064;Bean
* public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
* http
* .securityMatchers((matchers) -&gt; matchers
* .requestMatchers(&quot;/api/**&quot;, &quot;/oauth/**&quot;)
* )
* .authorizeHttpRequests((authorize) -&gt; authorize
* .anyRequest().hasRole(&quot;USER&quot;)
* )
* .httpBasic(withDefaults());
* return http.build();
* }
*
* &#064;Bean
* public UserDetailsService userDetailsService() {
* UserDetails user = User.withDefaultPasswordEncoder()
* .username(&quot;user&quot;)
* .password(&quot;password&quot;)
* .roles(&quot;USER&quot;)
* .build();
* return new InMemoryUserDetailsManager(user);
* }
* }
* </pre>
*
* The configuration below is the same as the previous configuration.
*
* <pre>
* &#064;Configuration
* &#064;EnableWebSecurity
* public class RequestMatchersSecurityConfig {
*
* &#064;Bean
* public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
* http
* .securityMatchers((matchers) -&gt; matchers
* .requestMatchers(&quot;/api/**&quot;)
* .requestMatchers(&quot;/oauth/**&quot;)
* )
* .authorizeHttpRequests((authorize) -&gt; authorize
* .anyRequest().hasRole(&quot;USER&quot;)
* )
* .httpBasic(withDefaults());
* return http.build();
* }
*
* &#064;Bean
* public UserDetailsService userDetailsService() {
* UserDetails user = User.withDefaultPasswordEncoder()
* .username(&quot;user&quot;)
* .password(&quot;password&quot;)
* .roles(&quot;USER&quot;)
* .build();
* return new InMemoryUserDetailsManager(user);
* }
* }
* </pre>
*
* The configuration below is also the same as the above configuration.
*
* <pre>
* &#064;Configuration
* &#064;EnableWebSecurity
* public class RequestMatchersSecurityConfig {
*
* &#064;Bean
* public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
* http
* .securityMatchers((matchers) -&gt; matchers
* .requestMatchers(&quot;/api/**&quot;)
* )
* .securityMatchers((matchers) -&gt; matchers
* .requestMatchers(&quot;/oauth/**&quot;)
* )
* .authorizeHttpRequests((authorize) -&gt; authorize
* .anyRequest().hasRole(&quot;USER&quot;)
* )
* .httpBasic(withDefaults());
* return http.build();
* }
*
* &#064;Bean
* public UserDetailsService userDetailsService() {
* UserDetails user = User.withDefaultPasswordEncoder()
* .username(&quot;user&quot;)
* .password(&quot;password&quot;)
* .roles(&quot;USER&quot;)
* .build();
* return new InMemoryUserDetailsManager(user);
* }
* }
* </pre>
* @param requestMatcherCustomizer the {@link Customizer} to provide more options for
* the {@link RequestMatcherConfigurer}
* @return the {@link HttpSecurity} for further customizations
*/
public HttpSecurity securityMatchers(Customizer<RequestMatcherConfigurer> requestMatcherCustomizer) {
requestMatcherCustomizer.customize(this.requestMatcherConfigurer);
return HttpSecurity.this;
}
/**
* Allows configuring the {@link HttpSecurity} to only be invoked when matching the
* provided {@link RequestMatcher}. If more advanced configuration is necessary,
* consider using {@link #securityMatchers(Customizer)} ()}.
*
* <p>
* Invoking {@link #securityMatcher(RequestMatcher)} will override previous
* invocations of {@link #requestMatchers()}, {@link #mvcMatcher(String)},
* {@link #antMatcher(String)}, {@link #regexMatcher(String)},
* {@link #requestMatcher(RequestMatcher)}, {@link #securityMatchers(Customizer)},
* {@link #securityMatchers()} and {@link #securityMatcher(String...)}
* </p>
* @param requestMatcher the {@link RequestMatcher} to use (i.e. new
* AntPathRequestMatcher("/admin/**","GET") )
* @return the {@link HttpSecurity} for further customizations
* @see #securityMatcher(String...)
*/
public HttpSecurity securityMatcher(RequestMatcher requestMatcher) {
this.requestMatcher = requestMatcher;
return this;
}
/**
* Allows configuring the {@link HttpSecurity} to only be invoked when matching the
* provided pattern. This method creates a {@link MvcRequestMatcher} if Spring MVC is
* in the classpath or creates an {@link AntPathRequestMatcher} if not. If more
* advanced configuration is necessary, consider using
* {@link #securityMatchers(Customizer)} or {@link #securityMatcher(RequestMatcher)}.
*
* <p>
* Invoking {@link #securityMatcher(String...)} will override previous invocations of
* {@link #mvcMatcher(String)}}, {@link #requestMatchers()},
* {@link #antMatcher(String)}, {@link #regexMatcher(String)}, and
* {@link #requestMatcher(RequestMatcher)}.
* </p>
* @param patterns the pattern to match on (i.e. "/admin/**")
* @return the {@link HttpSecurity} for further customizations
* @see AntPathRequestMatcher
* @see MvcRequestMatcher
*/
public HttpSecurity securityMatcher(String... patterns) {
if (mvcPresent) {
this.requestMatcher = new OrRequestMatcher(createMvcMatchers(patterns));
return this;
}
this.requestMatcher = new OrRequestMatcher(createAntMatchers(patterns));
return this;
}
private List<RequestMatcher> createAntMatchers(String... patterns) {
List<RequestMatcher> matchers = new ArrayList<>(patterns.length);
for (String pattern : patterns) {
matchers.add(new AntPathRequestMatcher(pattern));
}
return matchers;
}
private List<RequestMatcher> createMvcMatchers(String... mvcPatterns) {
ObjectPostProcessor<Object> opp = getContext().getBean(ObjectPostProcessor.class);
if (!getContext().containsBean(HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME)) {
throw new NoSuchBeanDefinitionException("A Bean named " + HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME
+ " of type " + HandlerMappingIntrospector.class.getName()
+ " is required to use MvcRequestMatcher. Please ensure Spring Security & Spring MVC are configured in a shared ApplicationContext.");
}
HandlerMappingIntrospector introspector = getContext().getBean(HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME,
HandlerMappingIntrospector.class);
List<RequestMatcher> matchers = new ArrayList<>(mvcPatterns.length);
for (String mvcPattern : mvcPatterns) {
MvcRequestMatcher matcher = new MvcRequestMatcher(introspector, mvcPattern);
opp.postProcess(matcher);
matchers.add(matcher);
}
return matchers;
}
/**
* Allows configuring the {@link HttpSecurity} to only be invoked when matching the
* provided ant pattern. If more advanced configuration is necessary, consider using
@@ -3932,10 +3590,8 @@ public final class HttpSecurity extends AbstractConfiguredSecurityBuilder<Defaul
* </p>
* @param antPattern the Ant Pattern to match on (i.e. "/admin/**")
* @return the {@link HttpSecurity} for further customizations
* @deprecated use {@link #securityMatcher(String...)} instead
* @see AntPathRequestMatcher
*/
@Deprecated
public HttpSecurity antMatcher(String antPattern) {
return requestMatcher(new AntPathRequestMatcher(antPattern));
}
@@ -3953,10 +3609,8 @@ public final class HttpSecurity extends AbstractConfiguredSecurityBuilder<Defaul
* </p>
* @param mvcPattern the Spring MVC Pattern to match on (i.e. "/admin/**")
* @return the {@link HttpSecurity} for further customizations
* @deprecated use {@link #securityMatcher(String...)} instead
* @see MvcRequestMatcher
*/
@Deprecated
public HttpSecurity mvcMatcher(String mvcPattern) {
HandlerMappingIntrospector introspector = new HandlerMappingIntrospector(getContext());
return requestMatcher(new MvcRequestMatcher(introspector, mvcPattern));
@@ -3975,10 +3629,8 @@ public final class HttpSecurity extends AbstractConfiguredSecurityBuilder<Defaul
* </p>
* @param pattern the Regular Expression to match on (i.e. "/admin/.+")
* @return the {@link HttpSecurity} for further customizations
* @deprecated use {@link #securityMatcher(RequestMatcher)} with a
* {@link RegexRequestMatcher} instead
* @see RegexRequestMatcher
*/
@Deprecated
public HttpSecurity regexMatcher(String pattern) {
return requestMatcher(new RegexRequestMatcher(pattern, null));
}
@@ -4049,22 +3701,14 @@ public final class HttpSecurity extends AbstractConfiguredSecurityBuilder<Defaul
setApplicationContext(context);
}
/**
* @deprecated use {@link #requestMatchers(HttpMethod, String...)} instead
*/
@Override
@Deprecated
public MvcMatchersRequestMatcherConfigurer mvcMatchers(HttpMethod method, String... mvcPatterns) {
List<MvcRequestMatcher> mvcMatchers = createMvcMatchers(method, mvcPatterns);
setMatchers(mvcMatchers);
return new MvcMatchersRequestMatcherConfigurer(getContext(), mvcMatchers, this.matchers);
}
/**
* @deprecated use {@link #requestMatchers(String...)} instead
*/
@Override
@Deprecated
public MvcMatchersRequestMatcherConfigurer mvcMatchers(String... patterns) {
return mvcMatchers(null, patterns);
}
@@ -4077,7 +3721,7 @@ public final class HttpSecurity extends AbstractConfiguredSecurityBuilder<Defaul
private void setMatchers(List<? extends RequestMatcher> requestMatchers) {
this.matchers.addAll(requestMatchers);
securityMatcher(new OrRequestMatcher(this.matchers));
requestMatcher(new OrRequestMatcher(this.matchers));
}
/**
@@ -138,7 +138,7 @@ public final class WebSecurity extends AbstractConfiguredSecurityBuilder<Filter,
* <pre>
* webSecurityBuilder.ignoring()
* // ignore all URLs that start with /resources/ or /static/
* .requestMatchers(&quot;/resources/**&quot;, &quot;/static/**&quot;);
* .antMatchers(&quot;/resources/**&quot;, &quot;/static/**&quot;);
* </pre>
*
* Alternatively this will accomplish the same result:
@@ -146,7 +146,7 @@ public final class WebSecurity extends AbstractConfiguredSecurityBuilder<Filter,
* <pre>
* webSecurityBuilder.ignoring()
* // ignore all URLs that start with /resources/ or /static/
* .requestMatchers(&quot;/resources/**&quot;).requestMatchers(&quot;/static/**&quot;);
* .antMatchers(&quot;/resources/**&quot;).antMatchers(&quot;/static/**&quot;);
* </pre>
*
* Multiple invocations of ignoring() are also additive, so the following is also
@@ -155,10 +155,10 @@ public final class WebSecurity extends AbstractConfiguredSecurityBuilder<Filter,
* <pre>
* webSecurityBuilder.ignoring()
* // ignore all URLs that start with /resources/
* .requestMatchers(&quot;/resources/**&quot;);
* .antMatchers(&quot;/resources/**&quot;);
* webSecurityBuilder.ignoring()
* // ignore all URLs that start with /static/
* .requestMatchers(&quot;/static/**&quot;);
* .antMatchers(&quot;/static/**&quot;);
* // now both URLs that start with /resources/ and /static/ will be ignored
* </pre>
* @return the {@link IgnoredRequestConfigurer} to use for registering request that
@@ -401,9 +401,7 @@ public final class WebSecurity extends AbstractConfiguredSecurityBuilder<Filter,
* {@link MvcRequestMatcher#setMethod(HttpMethod)}
*
* @author Rob Winch
* @deprecated use {@link MvcRequestMatcher.Builder} instead
*/
@Deprecated
public final class MvcMatchersIgnoredRequestConfigurer extends IgnoredRequestConfigurer {
private final List<MvcRequestMatcher> mvcMatchers;
@@ -435,22 +433,14 @@ public final class WebSecurity extends AbstractConfiguredSecurityBuilder<Filter,
setApplicationContext(context);
}
/**
* @deprecated use {@link #requestMatchers(HttpMethod, String...)} instead
*/
@Override
@Deprecated
public MvcMatchersIgnoredRequestConfigurer mvcMatchers(HttpMethod method, String... mvcPatterns) {
List<MvcRequestMatcher> mvcMatchers = createMvcMatchers(method, mvcPatterns);
WebSecurity.this.ignoredRequests.addAll(mvcMatchers);
return new MvcMatchersIgnoredRequestConfigurer(getApplicationContext(), mvcMatchers);
}
/**
* @deprecated use {@link #requestMatchers(String...)} instead
*/
@Override
@Deprecated
public MvcMatchersIgnoredRequestConfigurer mvcMatchers(String... mvcPatterns) {
return mvcMatchers(null, mvcPatterns);
}
@@ -42,12 +42,12 @@ import org.springframework.security.web.SecurityFilterChain;
* public WebSecurityCustomizer webSecurityCustomizer() {
* return (web) -> web.ignoring()
* // Spring Security should completely ignore URLs starting with /resources/
* .requestMatchers(&quot;/resources/**&quot;);
* .antMatchers(&quot;/resources/**&quot;);
* }
*
* &#064;Bean
* public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
* http.authorizeRequests().requestMatchers(&quot;/public/**&quot;).permitAll().anyRequest()
* http.authorizeRequests().antMatchers(&quot;/public/**&quot;).permitAll().anyRequest()
* .hasRole(&quot;USER&quot;).and()
* // Possibly more configuration ...
* .formLogin() // enable form based log in
@@ -35,11 +35,7 @@ import org.springframework.security.config.annotation.authentication.configurati
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.config.annotation.web.configurers.DefaultLoginPageConfigurer;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.context.SecurityContextHolderStrategy;
import org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter;
import org.springframework.web.accept.ContentNegotiationStrategy;
import org.springframework.web.accept.HeaderContentNegotiationStrategy;
import static org.springframework.security.config.Customizer.withDefaults;
@@ -64,11 +60,6 @@ class HttpSecurityConfiguration {
private ApplicationContext context;
private SecurityContextHolderStrategy securityContextHolderStrategy = SecurityContextHolder
.getContextHolderStrategy();
private ContentNegotiationStrategy contentNegotiationStrategy = new HeaderContentNegotiationStrategy();
@Autowired
void setObjectPostProcessor(ObjectPostProcessor<Object> objectPostProcessor) {
this.objectPostProcessor = objectPostProcessor;
@@ -88,16 +79,6 @@ class HttpSecurityConfiguration {
this.context = context;
}
@Autowired(required = false)
void setSecurityContextHolderStrategy(SecurityContextHolderStrategy securityContextHolderStrategy) {
this.securityContextHolderStrategy = securityContextHolderStrategy;
}
@Autowired(required = false)
void setContentNegotiationStrategy(ContentNegotiationStrategy contentNegotiationStrategy) {
this.contentNegotiationStrategy = contentNegotiationStrategy;
}
@Bean(HTTPSECURITY_BEAN_NAME)
@Scope("prototype")
HttpSecurity httpSecurity() throws Exception {
@@ -108,12 +89,10 @@ class HttpSecurityConfiguration {
authenticationBuilder.parentAuthenticationManager(authenticationManager());
authenticationBuilder.authenticationEventPublisher(getAuthenticationEventPublisher());
HttpSecurity http = new HttpSecurity(this.objectPostProcessor, authenticationBuilder, createSharedObjects());
WebAsyncManagerIntegrationFilter webAsyncManagerIntegrationFilter = new WebAsyncManagerIntegrationFilter();
webAsyncManagerIntegrationFilter.setSecurityContextHolderStrategy(this.securityContextHolderStrategy);
// @formatter:off
http
.csrf(withDefaults())
.addFilter(webAsyncManagerIntegrationFilter)
.addFilter(new WebAsyncManagerIntegrationFilter())
.exceptionHandling(withDefaults())
.headers(withDefaults())
.sessionManagement(withDefaults())
@@ -152,7 +131,6 @@ class HttpSecurityConfiguration {
private Map<Class<?>, Object> createSharedObjects() {
Map<Class<?>, Object> sharedObjects = new HashMap<>();
sharedObjects.put(ApplicationContext.class, this.context);
sharedObjects.put(ContentNegotiationStrategy.class, this.contentNegotiationStrategy);
return sharedObjects;
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 the original author or authors.
* Copyright 2002-2020 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.
@@ -23,7 +23,6 @@ import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.ImportSelector;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.security.core.context.SecurityContextHolderStrategy;
import org.springframework.security.oauth2.client.OAuth2AuthorizedClientManager;
import org.springframework.security.oauth2.client.OAuth2AuthorizedClientProvider;
import org.springframework.security.oauth2.client.OAuth2AuthorizedClientProviderBuilder;
@@ -76,18 +75,11 @@ final class OAuth2ClientConfiguration {
private OAuth2AuthorizedClientManager authorizedClientManager;
private SecurityContextHolderStrategy securityContextHolderStrategy;
@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
OAuth2AuthorizedClientManager authorizedClientManager = getAuthorizedClientManager();
if (authorizedClientManager != null) {
OAuth2AuthorizedClientArgumentResolver resolver = new OAuth2AuthorizedClientArgumentResolver(
authorizedClientManager);
if (this.securityContextHolderStrategy != null) {
resolver.setSecurityContextHolderStrategy(this.securityContextHolderStrategy);
}
argumentResolvers.add(resolver);
argumentResolvers.add(new OAuth2AuthorizedClientArgumentResolver(authorizedClientManager));
}
}
@@ -118,11 +110,6 @@ final class OAuth2ClientConfiguration {
}
}
@Autowired(required = false)
void setSecurityContextHolderStrategy(SecurityContextHolderStrategy strategy) {
this.securityContextHolderStrategy = strategy;
}
private OAuth2AuthorizedClientManager getAuthorizedClientManager() {
if (this.authorizedClientManager != null) {
return this.authorizedClientManager;
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 the original author or authors.
* Copyright 2002-2021 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.
@@ -37,13 +37,10 @@ import reactor.util.context.Context;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.context.SecurityContextHolderStrategy;
import org.springframework.util.Assert;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
@@ -65,37 +62,24 @@ import org.springframework.web.context.request.ServletRequestAttributes;
@Configuration(proxyBeanMethods = false)
class SecurityReactorContextConfiguration {
private SecurityContextHolderStrategy securityContextHolderStrategy = SecurityContextHolder
.getContextHolderStrategy();
@Bean
SecurityReactorContextSubscriberRegistrar securityReactorContextSubscriberRegistrar() {
SecurityReactorContextSubscriberRegistrar registrar = new SecurityReactorContextSubscriberRegistrar();
registrar.setSecurityContextHolderStrategy(this.securityContextHolderStrategy);
return registrar;
}
@Autowired(required = false)
void setSecurityContextHolderStrategy(SecurityContextHolderStrategy securityContextHolderStrategy) {
Assert.notNull(securityContextHolderStrategy, "securityContextHolderStrategy cannot be null");
this.securityContextHolderStrategy = securityContextHolderStrategy;
return new SecurityReactorContextSubscriberRegistrar();
}
static class SecurityReactorContextSubscriberRegistrar implements InitializingBean, DisposableBean {
private static final String SECURITY_REACTOR_CONTEXT_OPERATOR_KEY = "org.springframework.security.SECURITY_REACTOR_CONTEXT_OPERATOR";
private final Map<Object, Supplier<Object>> CONTEXT_ATTRIBUTE_VALUE_LOADERS = new HashMap<>();
private static final Map<Object, Supplier<Object>> CONTEXT_ATTRIBUTE_VALUE_LOADERS = new HashMap<>();
private SecurityContextHolderStrategy securityContextHolderStrategy = SecurityContextHolder
.getContextHolderStrategy();
SecurityReactorContextSubscriberRegistrar() {
this.CONTEXT_ATTRIBUTE_VALUE_LOADERS.put(HttpServletRequest.class,
static {
CONTEXT_ATTRIBUTE_VALUE_LOADERS.put(HttpServletRequest.class,
SecurityReactorContextSubscriberRegistrar::getRequest);
this.CONTEXT_ATTRIBUTE_VALUE_LOADERS.put(HttpServletResponse.class,
CONTEXT_ATTRIBUTE_VALUE_LOADERS.put(HttpServletResponse.class,
SecurityReactorContextSubscriberRegistrar::getResponse);
this.CONTEXT_ATTRIBUTE_VALUE_LOADERS.put(Authentication.class, this::getAuthentication);
CONTEXT_ATTRIBUTE_VALUE_LOADERS.put(Authentication.class,
SecurityReactorContextSubscriberRegistrar::getAuthentication);
}
@Override
@@ -110,11 +94,6 @@ class SecurityReactorContextConfiguration {
Hooks.resetOnLastOperator(SECURITY_REACTOR_CONTEXT_OPERATOR_KEY);
}
void setSecurityContextHolderStrategy(SecurityContextHolderStrategy securityContextHolderStrategy) {
Assert.notNull(securityContextHolderStrategy, "securityContextHolderStrategy cannot be null");
this.securityContextHolderStrategy = securityContextHolderStrategy;
}
<T> CoreSubscriber<T> createSubscriberIfNecessary(CoreSubscriber<T> delegate) {
if (delegate.currentContext().hasKey(SecurityReactorContextSubscriber.SECURITY_CONTEXT_ATTRIBUTES)) {
// Already enriched. No need to create Subscriber so return original
@@ -123,8 +102,8 @@ class SecurityReactorContextConfiguration {
return new SecurityReactorContextSubscriber<>(delegate, getContextAttributes());
}
private Map<Object, Object> getContextAttributes() {
return new LoadingMap<>(this.CONTEXT_ATTRIBUTE_VALUE_LOADERS);
private static Map<Object, Object> getContextAttributes() {
return new LoadingMap<>(CONTEXT_ATTRIBUTE_VALUE_LOADERS);
}
private static HttpServletRequest getRequest() {
@@ -145,8 +124,8 @@ class SecurityReactorContextConfiguration {
return null;
}
private Authentication getAuthentication() {
return this.securityContextHolderStrategy.getContext().getAuthentication();
private static Authentication getAuthentication() {
return SecurityContextHolder.getContext().getAuthentication();
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 the original author or authors.
* Copyright 2002-2019 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.
@@ -24,8 +24,6 @@ import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.expression.BeanFactoryResolver;
import org.springframework.expression.BeanResolver;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.context.SecurityContextHolderStrategy;
import org.springframework.security.web.method.annotation.AuthenticationPrincipalArgumentResolver;
import org.springframework.security.web.method.annotation.CsrfTokenArgumentResolver;
import org.springframework.security.web.method.annotation.CurrentSecurityContextArgumentResolver;
@@ -52,21 +50,16 @@ class WebMvcSecurityConfiguration implements WebMvcConfigurer, ApplicationContex
private BeanResolver beanResolver;
private SecurityContextHolderStrategy securityContextHolderStrategy = SecurityContextHolder
.getContextHolderStrategy();
@Override
@SuppressWarnings("deprecation")
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
AuthenticationPrincipalArgumentResolver authenticationPrincipalResolver = new AuthenticationPrincipalArgumentResolver();
authenticationPrincipalResolver.setBeanResolver(this.beanResolver);
authenticationPrincipalResolver.setSecurityContextHolderStrategy(this.securityContextHolderStrategy);
argumentResolvers.add(authenticationPrincipalResolver);
argumentResolvers
.add(new org.springframework.security.web.bind.support.AuthenticationPrincipalArgumentResolver());
CurrentSecurityContextArgumentResolver currentSecurityContextArgumentResolver = new CurrentSecurityContextArgumentResolver();
currentSecurityContextArgumentResolver.setBeanResolver(this.beanResolver);
currentSecurityContextArgumentResolver.setSecurityContextHolderStrategy(this.securityContextHolderStrategy);
argumentResolvers.add(currentSecurityContextArgumentResolver);
argumentResolvers.add(new CsrfTokenArgumentResolver());
}
@@ -79,9 +72,6 @@ class WebMvcSecurityConfiguration implements WebMvcConfigurer, ApplicationContex
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.beanResolver = new BeanFactoryResolver(applicationContext.getAutowireCapableBeanFactory());
if (applicationContext.getBeanNamesForType(SecurityContextHolderStrategy.class).length == 1) {
this.securityContextHolderStrategy = applicationContext.getBean(SecurityContextHolderStrategy.class);
}
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 the original author or authors.
* Copyright 2002-2023 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.
@@ -103,7 +103,7 @@ import org.springframework.web.accept.HeaderContentNegotiationStrategy;
* }
*
* &#64;Bean
* public WebSecurityCustomizer webSecurityCustomizer(WebSecurity web) {
* public WebSecurityCustomizer webSecurityCustomizer() {
* return (web) -> web.ignoring().antMatchers("/resources/**");
* }
* </pre> See the <a href=
@@ -299,7 +299,6 @@ public abstract class AbstractAuthenticationFilterConfigurer<B extends HttpSecur
.getSecurityContextRepository();
this.authFilter.setSecurityContextRepository(securityContextRepository);
}
this.authFilter.setSecurityContextHolderStrategy(getSecurityContextHolderStrategy());
F filter = postProcess(this.authFilter);
http.addFilter(filter);
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 the original author or authors.
* Copyright 2002-2013 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.
@@ -16,14 +16,11 @@
package org.springframework.security.config.annotation.web.configurers;
import org.springframework.context.ApplicationContext;
import org.springframework.security.config.annotation.ObjectPostProcessor;
import org.springframework.security.config.annotation.SecurityConfigurer;
import org.springframework.security.config.annotation.SecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.HttpSecurityBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.context.SecurityContextHolderStrategy;
import org.springframework.security.web.DefaultSecurityFilterChain;
/**
@@ -35,8 +32,6 @@ import org.springframework.security.web.DefaultSecurityFilterChain;
public abstract class AbstractHttpConfigurer<T extends AbstractHttpConfigurer<T, B>, B extends HttpSecurityBuilder<B>>
extends SecurityConfigurerAdapter<DefaultSecurityFilterChain, B> {
private SecurityContextHolderStrategy securityContextHolderStrategy;
/**
* Disables the {@link AbstractHttpConfigurer} by removing it. After doing so a fresh
* version of the configuration can be applied.
@@ -54,19 +49,4 @@ public abstract class AbstractHttpConfigurer<T extends AbstractHttpConfigurer<T,
return (T) this;
}
protected SecurityContextHolderStrategy getSecurityContextHolderStrategy() {
if (this.securityContextHolderStrategy != null) {
return this.securityContextHolderStrategy;
}
ApplicationContext context = getBuilder().getSharedObject(ApplicationContext.class);
String[] names = context.getBeanNamesForType(SecurityContextHolderStrategy.class);
if (names.length == 1) {
this.securityContextHolderStrategy = context.getBean(SecurityContextHolderStrategy.class);
}
else {
this.securityContextHolderStrategy = SecurityContextHolder.getContextHolderStrategy();
}
return this.securityContextHolderStrategy;
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 the original author or authors.
* Copyright 2002-2013 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.
@@ -60,9 +60,7 @@ import org.springframework.security.web.access.intercept.FilterSecurityIntercept
* @since 3.2
* @see ExpressionUrlAuthorizationConfigurer
* @see UrlAuthorizationConfigurer
* @deprecated Use {@link AuthorizeHttpRequestsConfigurer} instead
*/
@Deprecated
public abstract class AbstractInterceptUrlConfigurer<C extends AbstractInterceptUrlConfigurer<C, H>, H extends HttpSecurityBuilder<H>>
extends AbstractHttpConfigurer<C, H> {
@@ -146,7 +144,6 @@ public abstract class AbstractInterceptUrlConfigurer<C extends AbstractIntercept
securityInterceptor.setSecurityMetadataSource(metadataSource);
securityInterceptor.setAccessDecisionManager(getAccessDecisionManager(http));
securityInterceptor.setAuthenticationManager(authenticationManager);
securityInterceptor.setSecurityContextHolderStrategy(getSecurityContextHolderStrategy());
securityInterceptor.afterPropertiesSet();
return securityInterceptor;
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 the original author or authors.
* Copyright 2002-2013 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.
@@ -146,9 +146,7 @@ public final class AnonymousConfigurer<H extends HttpSecurityBuilder<H>>
}
if (this.authenticationFilter == null) {
this.authenticationFilter = new AnonymousAuthenticationFilter(getKey(), this.principal, this.authorities);
this.authenticationFilter.setSecurityContextHolderStrategy(getSecurityContextHolderStrategy());
}
this.authenticationFilter.setSecurityContextHolderStrategy(getSecurityContextHolderStrategy());
this.authenticationProvider = postProcess(this.authenticationProvider);
http.authenticationProvider(this.authenticationProvider);
}
@@ -86,7 +86,6 @@ public final class AuthorizeHttpRequestsConfigurer<H extends HttpSecurityBuilder
AuthorizationFilter authorizationFilter = new AuthorizationFilter(authorizationManager);
authorizationFilter.setAuthorizationEventPublisher(this.publisher);
authorizationFilter.setShouldFilterAllDispatcherTypes(this.registry.shouldFilterAllDispatcherTypes);
authorizationFilter.setSecurityContextHolderStrategy(getSecurityContextHolderStrategy());
http.addFilter(postProcess(authorizationFilter));
}
@@ -146,20 +145,12 @@ public final class AuthorizeHttpRequestsConfigurer<H extends HttpSecurityBuilder
return postProcess(this.managerBuilder.build());
}
/**
* @deprecated use {@link #requestMatchers(String...)} instead
*/
@Override
@Deprecated
public MvcMatchersAuthorizedUrl mvcMatchers(String... mvcPatterns) {
return mvcMatchers(null, mvcPatterns);
}
/**
* @deprecated use {@link #requestMatchers(HttpMethod, String...)} instead
*/
@Override
@Deprecated
public MvcMatchersAuthorizedUrl mvcMatchers(HttpMethod method, String... mvcPatterns) {
return new MvcMatchersAuthorizedUrl(createMvcMatchers(method, mvcPatterns));
}
@@ -211,9 +202,7 @@ public final class AuthorizeHttpRequestsConfigurer<H extends HttpSecurityBuilder
* configuring the {@link MvcRequestMatcher#setServletPath(String)}.
*
* @author Evgeniy Cheban
* @deprecated use {@link MvcRequestMatcher.Builder} instead
*/
@Deprecated
public final class MvcMatchersAuthorizedUrl extends AuthorizedUrl {
private MvcMatchersAuthorizedUrl(List<MvcRequestMatcher> matchers) {
@@ -328,39 +317,6 @@ public final class AuthorizeHttpRequestsConfigurer<H extends HttpSecurityBuilder
return access(AuthenticatedAuthorizationManager.authenticated());
}
/**
* Specify that URLs are allowed by users who have authenticated and were not
* "remembered".
* @return the {@link AuthorizationManagerRequestMatcherRegistry} for further
* customization
* @since 5.8
* @see RememberMeConfigurer
*/
public AuthorizationManagerRequestMatcherRegistry fullyAuthenticated() {
return access(AuthenticatedAuthorizationManager.fullyAuthenticated());
}
/**
* Specify that URLs are allowed by users that have been remembered.
* @return the {@link AuthorizationManagerRequestMatcherRegistry} for further
* customization
* @since 5.8
* @see RememberMeConfigurer
*/
public AuthorizationManagerRequestMatcherRegistry rememberMe() {
return access(AuthenticatedAuthorizationManager.rememberMe());
}
/**
* Specify that URLs are allowed by anonymous users.
* @return the {@link AuthorizationManagerRequestMatcherRegistry} for further
* customization
* @since 5.8
*/
public AuthorizationManagerRequestMatcherRegistry anonymous() {
return access(AuthenticatedAuthorizationManager.anonymous());
}
/**
* Allows specifying a custom {@link AuthorizationManager}.
* @param manager the {@link AuthorizationManager} to use
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 the original author or authors.
* Copyright 2002-2021 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.
@@ -155,21 +155,13 @@ public final class ChannelSecurityConfigurer<H extends HttpSecurityBuilder<H>>
setApplicationContext(context);
}
/**
* @deprecated use {@link #requestMatchers(HttpMethod, String...)} instead
*/
@Override
@Deprecated
public MvcMatchersRequiresChannelUrl mvcMatchers(HttpMethod method, String... mvcPatterns) {
List<MvcRequestMatcher> mvcMatchers = createMvcMatchers(method, mvcPatterns);
return new MvcMatchersRequiresChannelUrl(mvcMatchers);
}
/**
* @deprecated use {@link #requestMatchers(String...)} instead
*/
@Override
@Deprecated
public MvcMatchersRequiresChannelUrl mvcMatchers(String... patterns) {
return mvcMatchers(null, patterns);
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 the original author or authors.
* Copyright 2002-2021 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.
@@ -36,7 +36,6 @@ import org.springframework.security.web.csrf.CsrfAuthenticationStrategy;
import org.springframework.security.web.csrf.CsrfFilter;
import org.springframework.security.web.csrf.CsrfLogoutHandler;
import org.springframework.security.web.csrf.CsrfTokenRepository;
import org.springframework.security.web.csrf.CsrfTokenRequestHandler;
import org.springframework.security.web.csrf.HttpSessionCsrfTokenRepository;
import org.springframework.security.web.csrf.LazyCsrfTokenRepository;
import org.springframework.security.web.csrf.MissingCsrfTokenException;
@@ -90,8 +89,6 @@ public final class CsrfConfigurer<H extends HttpSecurityBuilder<H>>
private SessionAuthenticationStrategy sessionAuthenticationStrategy;
private CsrfTokenRequestHandler requestHandler;
private final ApplicationContext context;
/**
@@ -127,18 +124,6 @@ public final class CsrfConfigurer<H extends HttpSecurityBuilder<H>>
return this;
}
/**
* Specify a {@link CsrfTokenRequestHandler} to use for making the {@code CsrfToken}
* available as a request attribute.
* @param requestHandler the {@link CsrfTokenRequestHandler} to use
* @return the {@link CsrfConfigurer} for further customizations
* @since 5.8
*/
public CsrfConfigurer<H> csrfTokenRequestHandler(CsrfTokenRequestHandler requestHandler) {
this.requestHandler = requestHandler;
return this;
}
/**
* <p>
* Allows specifying {@link HttpServletRequest} that should not use CSRF Protection
@@ -162,10 +147,7 @@ public final class CsrfConfigurer<H extends HttpSecurityBuilder<H>>
* </pre>
*
* @since 4.0
* @deprecated use {@link #ignoringRequestMatchers(RequestMatcher...)} with an
* {@link org.springframework.security.web.util.matcher.AntPathRequestMatcher} instead
*/
@Deprecated
public CsrfConfigurer<H> ignoringAntMatchers(String... antPatterns) {
return new IgnoreCsrfProtectionRegistry(this.context).antMatchers(antPatterns).and();
}
@@ -199,35 +181,6 @@ public final class CsrfConfigurer<H extends HttpSecurityBuilder<H>>
return new IgnoreCsrfProtectionRegistry(this.context).requestMatchers(requestMatchers).and();
}
/**
* <p>
* Allows specifying {@link HttpServletRequest} that should not use CSRF Protection
* even if they match the {@link #requireCsrfProtectionMatcher(RequestMatcher)}.
* </p>
*
* <p>
* For example, the following configuration will ensure CSRF protection ignores:
* </p>
* <ul>
* <li>Any GET, HEAD, TRACE, OPTIONS (this is the default)</li>
* <li>We also explicitly state to ignore any request that starts with "/sockjs/"</li>
* </ul>
*
* <pre>
* http
* .csrf()
* .ignoringRequestMatchers("/sockjs/**")
* .and()
* ...
* </pre>
*
* @since 5.8
* @see AbstractRequestMatcherRegistry#requestMatchers(String...)
*/
public CsrfConfigurer<H> ignoringRequestMatchers(String... patterns) {
return new IgnoreCsrfProtectionRegistry(this.context).requestMatchers(patterns).and();
}
/**
* <p>
* Specify the {@link SessionAuthenticationStrategy} to use. The default is a
@@ -265,9 +218,6 @@ public final class CsrfConfigurer<H extends HttpSecurityBuilder<H>>
if (sessionConfigurer != null) {
sessionConfigurer.addSessionAuthenticationStrategy(getSessionAuthenticationStrategy());
}
if (this.requestHandler != null) {
filter.setRequestHandler(this.requestHandler);
}
filter = postProcess(filter);
http.addFilter(filter);
}
@@ -356,12 +306,7 @@ public final class CsrfConfigurer<H extends HttpSecurityBuilder<H>>
if (this.sessionAuthenticationStrategy != null) {
return this.sessionAuthenticationStrategy;
}
CsrfAuthenticationStrategy csrfAuthenticationStrategy = new CsrfAuthenticationStrategy(
this.csrfTokenRepository);
if (this.requestHandler != null) {
csrfAuthenticationStrategy.setRequestHandler(this.requestHandler);
}
return csrfAuthenticationStrategy;
return new CsrfAuthenticationStrategy(this.csrfTokenRepository);
}
/**
@@ -378,22 +323,14 @@ public final class CsrfConfigurer<H extends HttpSecurityBuilder<H>>
setApplicationContext(context);
}
/**
* @deprecated use {@link #requestMatchers(HttpMethod, String...)} instead
*/
@Override
@Deprecated
public MvcMatchersIgnoreCsrfProtectionRegistry mvcMatchers(HttpMethod method, String... mvcPatterns) {
List<MvcRequestMatcher> mvcMatchers = createMvcMatchers(method, mvcPatterns);
CsrfConfigurer.this.ignoredCsrfProtectionMatchers.addAll(mvcMatchers);
return new MvcMatchersIgnoreCsrfProtectionRegistry(getApplicationContext(), mvcMatchers);
}
/**
* @deprecated use {@link #requestMatchers(String...)} instead
*/
@Override
@Deprecated
public MvcMatchersIgnoreCsrfProtectionRegistry mvcMatchers(String... mvcPatterns) {
return mvcMatchers(null, mvcPatterns);
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 the original author or authors.
* Copyright 2002-2018 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.
@@ -187,7 +187,6 @@ public final class ExceptionHandlingConfigurer<H extends HttpSecurityBuilder<H>>
getRequestCache(http));
AccessDeniedHandler deniedHandler = getAccessDeniedHandler(http);
exceptionTranslationFilter.setAccessDeniedHandler(deniedHandler);
exceptionTranslationFilter.setSecurityContextHolderStrategy(getSecurityContextHolderStrategy());
exceptionTranslationFilter = postProcess(exceptionTranslationFilter);
http.addFilter(exceptionTranslationFilter);
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 the original author or authors.
* Copyright 2002-2021 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.
@@ -79,9 +79,7 @@ import org.springframework.util.StringUtils;
* @author Yanming Zhou
* @since 3.2
* @see org.springframework.security.config.annotation.web.builders.HttpSecurity#authorizeRequests()
* @deprecated Use {@link AuthorizeHttpRequestsConfigurer} instead
*/
@Deprecated
public final class ExpressionUrlAuthorizationConfigurer<H extends HttpSecurityBuilder<H>>
extends AbstractInterceptUrlConfigurer<ExpressionUrlAuthorizationConfigurer<H>, H> {
@@ -222,20 +220,12 @@ public final class ExpressionUrlAuthorizationConfigurer<H extends HttpSecurityBu
setApplicationContext(context);
}
/**
* @deprecated use {@link #requestMatchers(HttpMethod, String...)} instead
*/
@Override
@Deprecated
public MvcMatchersAuthorizedUrl mvcMatchers(HttpMethod method, String... mvcPatterns) {
return new MvcMatchersAuthorizedUrl(createMvcMatchers(method, mvcPatterns));
}
/**
* @deprecated use {@link #requestMatchers(String...)} instead
*/
@Override
@Deprecated
public MvcMatchersAuthorizedUrl mvcMatchers(String... patterns) {
return mvcMatchers(null, patterns);
}
@@ -266,11 +266,7 @@ public class HeadersConfigurer<H extends HttpSecurityBuilder<H>>
* @return the {@link HpkpConfig} for additional customizations
*
* @since 4.1
* @deprecated see <a href=
* "https://owasp.org/www-community/controls/Certificate_and_Public_Key_Pinning">Certificate
* and Public Key Pinning</a> for more context
*/
@Deprecated
public HpkpConfig httpPublicKeyPinning() {
return this.hpkp.enable();
}
@@ -281,11 +277,7 @@ public class HeadersConfigurer<H extends HttpSecurityBuilder<H>>
* @param hpkpCustomizer the {@link Customizer} to provide more options for the
* {@link HpkpConfig}
* @return the {@link HeadersConfigurer} for additional customizations
* @deprecated see <a href=
* "https://owasp.org/www-community/controls/Certificate_and_Public_Key_Pinning">Certificate
* and Public Key Pinning</a> for more context
*/
@Deprecated
public HeadersConfigurer<H> httpPublicKeyPinning(Customizer<HpkpConfig> hpkpCustomizer) {
hpkpCustomizer.customize(this.hpkp.enable());
return HeadersConfigurer.this;
@@ -737,10 +729,7 @@ public class HeadersConfigurer<H extends HttpSecurityBuilder<H>>
* If false, will not specify the mode as blocked. In this instance, any content
* will be attempted to be fixed. If true, the content will be replaced with "#".
* @param enabled the new value
* @deprecated use
* {@link XXssConfig#headerValue(XXssProtectionHeaderWriter.HeaderValue)} instead
*/
@Deprecated
public XXssConfig block(boolean enabled) {
this.writer.setBlock(enabled);
return this;
@@ -768,49 +757,12 @@ public class HeadersConfigurer<H extends HttpSecurityBuilder<H>>
* X-XSS-Protection: 0
* </pre>
* @param enabled the new value
* @deprecated use
* {@link XXssConfig#headerValue(XXssProtectionHeaderWriter.HeaderValue)} instead
*/
@Deprecated
public XXssConfig xssProtectionEnabled(boolean enabled) {
this.writer.setEnabled(enabled);
return this;
}
/**
* Sets the value of the X-XSS-PROTECTION header. OWASP recommends using
* {@link XXssProtectionHeaderWriter.HeaderValue#DISABLED}.
*
* If {@link XXssProtectionHeaderWriter.HeaderValue#DISABLED}, will specify that
* X-XSS-Protection is disabled. For example:
*
* <pre>
* X-XSS-Protection: 0
* </pre>
*
* If {@link XXssProtectionHeaderWriter.HeaderValue#ENABLED}, will contain a value
* of 1, but will not specify the mode as blocked. In this instance, any content
* will be attempted to be fixed. For example:
*
* <pre>
* X-XSS-Protection: 1
* </pre>
*
* If {@link XXssProtectionHeaderWriter.HeaderValue#ENABLED_MODE_BLOCK}, will
* contain a value of 1 and will specify mode as blocked. The content will be
* replaced with "#". For example:
*
* <pre>
* X-XSS-Protection: 1 ; mode=block
* </pre>
* @param headerValue the new header value
* @since 5.8
*/
public XXssConfig headerValue(XXssProtectionHeaderWriter.HeaderValue headerValue) {
this.writer.setHeaderValue(headerValue);
return this;
}
/**
* Disables X-XSS-Protection header (does not include it)
* @return the {@link HeadersConfigurer} for additional configuration
@@ -1048,12 +1000,6 @@ public class HeadersConfigurer<H extends HttpSecurityBuilder<H>>
}
/**
* @deprecated see <a href=
* "https://owasp.org/www-community/controls/Certificate_and_Public_Key_Pinning">Certificate
* and Public Key Pinning</a> for more context
*/
@Deprecated
public final class HpkpConfig {
private HpkpHeaderWriter writer;
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 the original author or authors.
* Copyright 2002-2019 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.
@@ -199,7 +199,6 @@ public final class HttpBasicConfigurer<B extends HttpSecurityBuilder<B>>
if (rememberMeServices != null) {
basicAuthenticationFilter.setRememberMeServices(rememberMeServices);
}
basicAuthenticationFilter.setSecurityContextHolderStrategy(getSecurityContextHolderStrategy());
basicAuthenticationFilter = postProcess(basicAuthenticationFilter);
http.addFilter(basicAuthenticationFilter);
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 the original author or authors.
* Copyright 2002-2013 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.
@@ -198,8 +198,7 @@ public final class JeeConfigurer<H extends HttpSecurityBuilder<H>> extends Abstr
@Override
public void configure(H http) {
J2eePreAuthenticatedProcessingFilter filter = getFilter(http.getSharedObject(AuthenticationManager.class),
http);
J2eePreAuthenticatedProcessingFilter filter = getFilter(http.getSharedObject(AuthenticationManager.class));
http.addFilter(filter);
}
@@ -209,14 +208,12 @@ public final class JeeConfigurer<H extends HttpSecurityBuilder<H>> extends Abstr
* @param authenticationManager the {@link AuthenticationManager} to use.
* @return the {@link J2eePreAuthenticatedProcessingFilter} to use.
*/
private J2eePreAuthenticatedProcessingFilter getFilter(AuthenticationManager authenticationManager, H http) {
private J2eePreAuthenticatedProcessingFilter getFilter(AuthenticationManager authenticationManager) {
if (this.j2eePreAuthenticatedProcessingFilter == null) {
this.j2eePreAuthenticatedProcessingFilter = new J2eePreAuthenticatedProcessingFilter();
this.j2eePreAuthenticatedProcessingFilter.setAuthenticationManager(authenticationManager);
this.j2eePreAuthenticatedProcessingFilter
.setAuthenticationDetailsSource(createWebAuthenticationDetailsSource());
this.j2eePreAuthenticatedProcessingFilter
.setSecurityContextHolderStrategy(getSecurityContextHolderStrategy());
this.j2eePreAuthenticatedProcessingFilter = postProcess(this.j2eePreAuthenticatedProcessingFilter);
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 the original author or authors.
* Copyright 2002-2023 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.
@@ -35,6 +35,8 @@ import org.springframework.security.web.authentication.logout.LogoutSuccessHandl
import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler;
import org.springframework.security.web.authentication.logout.SimpleUrlLogoutSuccessHandler;
import org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter;
import org.springframework.security.web.context.HttpSessionSecurityContextRepository;
import org.springframework.security.web.context.SecurityContextRepository;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.security.web.util.matcher.OrRequestMatcher;
import org.springframework.security.web.util.matcher.RequestMatcher;
@@ -325,18 +327,24 @@ public final class LogoutConfigurer<H extends HttpSecurityBuilder<H>>
* @return the {@link LogoutFilter} to use.
*/
private LogoutFilter createLogoutFilter(H http) {
this.contextLogoutHandler.setSecurityContextHolderStrategy(getSecurityContextHolderStrategy());
this.contextLogoutHandler.setSecurityContextRepository(getSecurityContextRepository(http));
this.logoutHandlers.add(this.contextLogoutHandler);
this.logoutHandlers.add(postProcess(new LogoutSuccessEventPublishingLogoutHandler()));
LogoutHandler[] handlers = this.logoutHandlers.toArray(new LogoutHandler[0]);
LogoutFilter result = new LogoutFilter(getLogoutSuccessHandler(), handlers);
result.setSecurityContextHolderStrategy(getSecurityContextHolderStrategy());
result.setLogoutRequestMatcher(getLogoutRequestMatcher(http));
result.setSecurityContextHolderStrategy(getSecurityContextHolderStrategy());
result = postProcess(result);
return result;
}
private SecurityContextRepository getSecurityContextRepository(H http) {
SecurityContextRepository securityContextRepository = http.getSharedObject(SecurityContextRepository.class);
if (securityContextRepository == null) {
securityContextRepository = new HttpSessionSecurityContextRepository();
}
return securityContextRepository;
}
private RequestMatcher getLogoutRequestMatcher(H http) {
if (this.logoutRequestMatcher != null) {
return this.logoutRequestMatcher;
@@ -288,7 +288,6 @@ public final class RememberMeConfigurer<H extends HttpSecurityBuilder<H>>
if (this.authenticationSuccessHandler != null) {
rememberMeFilter.setAuthenticationSuccessHandler(this.authenticationSuccessHandler);
}
rememberMeFilter.setSecurityContextHolderStrategy(getSecurityContextHolderStrategy());
rememberMeFilter = postProcess(rememberMeFilter);
http.addFilter(rememberMeFilter);
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 the original author or authors.
* Copyright 2002-2018 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.
@@ -108,13 +108,11 @@ public final class SecurityContextConfigurer<H extends HttpSecurityBuilder<H>>
if (this.requireExplicitSave) {
SecurityContextHolderFilter securityContextHolderFilter = postProcess(
new SecurityContextHolderFilter(securityContextRepository));
securityContextHolderFilter.setSecurityContextHolderStrategy(getSecurityContextHolderStrategy());
http.addFilter(securityContextHolderFilter);
}
else {
SecurityContextPersistenceFilter securityContextFilter = new SecurityContextPersistenceFilter(
securityContextRepository);
securityContextFilter.setSecurityContextHolderStrategy(getSecurityContextHolderStrategy());
SessionManagementConfigurer<?> sessionManagement = http.getConfigurer(SessionManagementConfigurer.class);
SessionCreationPolicy sessionCreationPolicy = (sessionManagement != null)
? sessionManagement.getSessionCreationPolicy() : null;
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 the original author or authors.
* Copyright 2002-2018 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.
@@ -98,7 +98,6 @@ public final class ServletApiConfigurer<H extends HttpSecurityBuilder<H>>
.getBean(grantedAuthorityDefaultsBeanNames[0], GrantedAuthorityDefaults.class);
this.securityContextRequestFilter.setRolePrefix(grantedAuthorityDefaults.getRolePrefix());
}
this.securityContextRequestFilter.setSecurityContextHolderStrategy(getSecurityContextHolderStrategy());
}
this.securityContextRequestFilter = postProcess(this.securityContextRequestFilter);
http.addFilter(this.securityContextRequestFilter);
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 the original author or authors.
* Copyright 2002-2019 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.
@@ -135,8 +135,6 @@ public final class SessionManagementConfigurer<H extends HttpSecurityBuilder<H>>
private AuthenticationFailureHandler sessionAuthenticationFailureHandler;
private boolean requireExplicitAuthenticationStrategy;
/**
* Creates a new instance
* @see HttpSecurity#sessionManagement()
@@ -157,19 +155,6 @@ public final class SessionManagementConfigurer<H extends HttpSecurityBuilder<H>>
return this;
}
/**
* Setting this means that explicit invocation of
* {@link SessionAuthenticationStrategy} is required.
* @param requireExplicitAuthenticationStrategy require explicit invocation of
* {@link SessionAuthenticationStrategy}
* @return the {@link SessionManagementConfigurer} for further customization
*/
public SessionManagementConfigurer<H> requireExplicitAuthenticationStrategy(
boolean requireExplicitAuthenticationStrategy) {
this.requireExplicitAuthenticationStrategy = requireExplicitAuthenticationStrategy;
return this;
}
/**
* Setting this attribute will inject the provided invalidSessionStrategy into the
* {@link SessionManagementFilter}. When an invalid session ID is submitted, the
@@ -303,7 +288,7 @@ public final class SessionManagementConfigurer<H extends HttpSecurityBuilder<H>>
/**
* Controls the maximum number of sessions for a user. The default is to allow any
* number of users.
* number of sessions.
* @param maximumSessions the maximum number of sessions for a user
* @return the {@link SessionManagementConfigurer} for further customizations
*/
@@ -366,28 +351,6 @@ public final class SessionManagementConfigurer<H extends HttpSecurityBuilder<H>>
@Override
public void configure(H http) {
SessionManagementFilter sessionManagementFilter = createSessionManagementFilter(http);
if (sessionManagementFilter != null) {
http.addFilter(sessionManagementFilter);
}
if (isConcurrentSessionControlEnabled()) {
ConcurrentSessionFilter concurrentSessionFilter = createConcurrencyFilter(http);
concurrentSessionFilter = postProcess(concurrentSessionFilter);
http.addFilter(concurrentSessionFilter);
}
if (!this.enableSessionUrlRewriting) {
http.addFilter(new DisableEncodeUrlFilter());
}
if (this.sessionPolicy == SessionCreationPolicy.ALWAYS) {
http.addFilter(new ForceEagerSessionCreationFilter());
}
}
private SessionManagementFilter createSessionManagementFilter(H http) {
if (this.requireExplicitAuthenticationStrategy) {
return null;
}
SecurityContextRepository securityContextRepository = http.getSharedObject(SecurityContextRepository.class);
SessionManagementFilter sessionManagementFilter = new SessionManagementFilter(securityContextRepository,
getSessionAuthenticationStrategy(http));
@@ -407,8 +370,20 @@ public final class SessionManagementConfigurer<H extends HttpSecurityBuilder<H>>
if (trustResolver != null) {
sessionManagementFilter.setTrustResolver(trustResolver);
}
sessionManagementFilter.setSecurityContextHolderStrategy(getSecurityContextHolderStrategy());
return postProcess(sessionManagementFilter);
sessionManagementFilter = postProcess(sessionManagementFilter);
http.addFilter(sessionManagementFilter);
if (isConcurrentSessionControlEnabled()) {
ConcurrentSessionFilter concurrentSessionFilter = createConcurrencyFilter(http);
concurrentSessionFilter = postProcess(concurrentSessionFilter);
http.addFilter(concurrentSessionFilter);
}
if (!this.enableSessionUrlRewriting) {
http.addFilter(new DisableEncodeUrlFilter());
}
if (this.sessionPolicy == SessionCreationPolicy.ALWAYS) {
http.addFilter(new ForceEagerSessionCreationFilter());
}
}
private ConcurrentSessionFilter createConcurrencyFilter(H http) {
@@ -424,7 +399,6 @@ public final class SessionManagementConfigurer<H extends HttpSecurityBuilder<H>>
concurrentSessionFilter.setLogoutHandlers(logoutHandlers);
}
}
concurrentSessionFilter.setSecurityContextHolderStrategy(getSecurityContextHolderStrategy());
return concurrentSessionFilter;
}
@@ -526,6 +500,7 @@ public final class SessionManagementConfigurer<H extends HttpSecurityBuilder<H>>
concurrentSessionControlStrategy.setMaximumSessions(this.maximumSessions);
concurrentSessionControlStrategy.setExceptionIfMaximumExceeded(this.maxSessionsPreventsLogin);
concurrentSessionControlStrategy = postProcess(concurrentSessionControlStrategy);
RegisterSessionAuthenticationStrategy registerSessionStrategy = new RegisterSessionAuthenticationStrategy(
sessionRegistry);
registerSessionStrategy = postProcess(registerSessionStrategy);
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 the original author or authors.
* Copyright 2002-2018 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.
@@ -86,9 +86,7 @@ import org.springframework.util.Assert;
* @author Rob Winch
* @since 3.2
* @see ExpressionUrlAuthorizationConfigurer
* @deprecated Use {@link AuthorizeHttpRequestsConfigurer} instead
*/
@Deprecated
public final class UrlAuthorizationConfigurer<H extends HttpSecurityBuilder<H>>
extends AbstractInterceptUrlConfigurer<UrlAuthorizationConfigurer<H>, H> {
@@ -203,20 +201,12 @@ public final class UrlAuthorizationConfigurer<H extends HttpSecurityBuilder<H>>
setApplicationContext(context);
}
/**
* @deprecated use {@link #requestMatchers(HttpMethod, String...)} instead
*/
@Override
@Deprecated
public MvcMatchersAuthorizedUrl mvcMatchers(HttpMethod method, String... mvcPatterns) {
return new MvcMatchersAuthorizedUrl(createMvcMatchers(method, mvcPatterns));
}
/**
* @deprecated use {@link #requestMatchers(String...)} instead
*/
@Override
@Deprecated
public MvcMatchersAuthorizedUrl mvcMatchers(String... patterns) {
return mvcMatchers(null, patterns);
}
@@ -178,11 +178,11 @@ public final class X509Configurer<H extends HttpSecurityBuilder<H>>
@Override
public void configure(H http) {
X509AuthenticationFilter filter = getFilter(http.getSharedObject(AuthenticationManager.class), http);
X509AuthenticationFilter filter = getFilter(http.getSharedObject(AuthenticationManager.class));
http.addFilter(filter);
}
private X509AuthenticationFilter getFilter(AuthenticationManager authenticationManager, H http) {
private X509AuthenticationFilter getFilter(AuthenticationManager authenticationManager) {
if (this.x509AuthenticationFilter == null) {
this.x509AuthenticationFilter = new X509AuthenticationFilter();
this.x509AuthenticationFilter.setAuthenticationManager(authenticationManager);
@@ -192,7 +192,6 @@ public final class X509Configurer<H extends HttpSecurityBuilder<H>>
if (this.authenticationDetailsSource != null) {
this.x509AuthenticationFilter.setAuthenticationDetailsSource(this.authenticationDetailsSource);
}
this.x509AuthenticationFilter.setSecurityContextHolderStrategy(getSecurityContextHolderStrategy());
this.x509AuthenticationFilter = postProcess(this.x509AuthenticationFilter);
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 the original author or authors.
* Copyright 2002-2020 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.
@@ -34,7 +34,6 @@ import org.springframework.security.oauth2.client.web.OAuth2AuthorizationRequest
import org.springframework.security.oauth2.client.web.OAuth2AuthorizationRequestResolver;
import org.springframework.security.oauth2.client.web.OAuth2AuthorizedClientRepository;
import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationRequest;
import org.springframework.security.web.RedirectStrategy;
import org.springframework.security.web.savedrequest.RequestCache;
import org.springframework.util.Assert;
@@ -172,8 +171,6 @@ public final class OAuth2ClientConfigurer<B extends HttpSecurityBuilder<B>>
private AuthorizationRequestRepository<OAuth2AuthorizationRequest> authorizationRequestRepository;
private RedirectStrategy authorizationRedirectStrategy;
private OAuth2AccessTokenResponseClient<OAuth2AuthorizationCodeGrantRequest> accessTokenResponseClient;
private AuthorizationCodeGrantConfigurer() {
@@ -205,17 +202,6 @@ public final class OAuth2ClientConfigurer<B extends HttpSecurityBuilder<B>>
return this;
}
/**
* Sets the redirect strategy for Authorization Endpoint redirect URI.
* @param authorizationRedirectStrategy the redirect strategy
* @return the {@link AuthorizationCodeGrantConfigurer} for further configuration
*/
public AuthorizationCodeGrantConfigurer authorizationRedirectStrategy(
RedirectStrategy authorizationRedirectStrategy) {
this.authorizationRedirectStrategy = authorizationRedirectStrategy;
return this;
}
/**
* Sets the client used for requesting the access token credential from the Token
* Endpoint.
@@ -261,9 +247,6 @@ public final class OAuth2ClientConfigurer<B extends HttpSecurityBuilder<B>>
authorizationRequestRedirectFilter
.setAuthorizationRequestRepository(this.authorizationRequestRepository);
}
if (this.authorizationRedirectStrategy != null) {
authorizationRequestRedirectFilter.setAuthorizationRedirectStrategy(this.authorizationRedirectStrategy);
}
RequestCache requestCache = builder.getSharedObject(RequestCache.class);
if (requestCache != null) {
authorizationRequestRedirectFilter.setRequestCache(requestCache);
@@ -289,7 +272,6 @@ public final class OAuth2ClientConfigurer<B extends HttpSecurityBuilder<B>>
if (this.authorizationRequestRepository != null) {
authorizationCodeGrantFilter.setAuthorizationRequestRepository(this.authorizationRequestRepository);
}
authorizationCodeGrantFilter.setSecurityContextHolderStrategy(getSecurityContextHolderStrategy());
RequestCache requestCache = builder.getSharedObject(RequestCache.class);
if (requestCache != null) {
authorizationCodeGrantFilter.setRequestCache(requestCache);
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 the original author or authors.
* Copyright 2002-2021 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.
@@ -16,7 +16,6 @@
package org.springframework.security.config.annotation.web.configurers.oauth2.client;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
@@ -68,21 +67,18 @@ import org.springframework.security.oauth2.core.oidc.user.OidcUser;
import org.springframework.security.oauth2.core.user.OAuth2User;
import org.springframework.security.oauth2.jwt.JwtDecoderFactory;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.RedirectStrategy;
import org.springframework.security.web.authentication.DelegatingAuthenticationEntryPoint;
import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint;
import org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter;
import org.springframework.security.web.savedrequest.RequestCache;
import org.springframework.security.web.util.matcher.AndRequestMatcher;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.security.web.util.matcher.AnyRequestMatcher;
import org.springframework.security.web.util.matcher.NegatedRequestMatcher;
import org.springframework.security.web.util.matcher.OrRequestMatcher;
import org.springframework.security.web.util.matcher.RequestHeaderRequestMatcher;
import org.springframework.security.web.util.matcher.RequestMatcher;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.ReflectionUtils;
/**
* An {@link AbstractHttpConfigurer} for OAuth 2.0 Login, which leverages the OAuth 2.0
@@ -294,7 +290,6 @@ public final class OAuth2LoginConfigurer<B extends HttpSecurityBuilder<B>>
OAuth2LoginAuthenticationFilter authenticationFilter = new OAuth2LoginAuthenticationFilter(
OAuth2ClientConfigurerUtils.getClientRegistrationRepository(this.getBuilder()),
OAuth2ClientConfigurerUtils.getAuthorizedClientRepository(this.getBuilder()), this.loginProcessingUrl);
authenticationFilter.setSecurityContextHolderStrategy(getSecurityContextHolderStrategy());
this.setAuthenticationFilter(authenticationFilter);
super.loginProcessingUrl(this.loginProcessingUrl);
if (this.loginPage != null) {
@@ -369,10 +364,6 @@ public final class OAuth2LoginConfigurer<B extends HttpSecurityBuilder<B>>
authorizationRequestFilter
.setAuthorizationRequestRepository(this.authorizationEndpointConfig.authorizationRequestRepository);
}
if (this.authorizationEndpointConfig.authorizationRedirectStrategy != null) {
authorizationRequestFilter
.setAuthorizationRedirectStrategy(this.authorizationEndpointConfig.authorizationRedirectStrategy);
}
RequestCache requestCache = http.getSharedObject(RequestCache.class);
if (requestCache != null) {
authorizationRequestFilter.setRequestCache(requestCache);
@@ -512,28 +503,14 @@ public final class OAuth2LoginConfigurer<B extends HttpSecurityBuilder<B>>
new OrRequestMatcher(loginPageMatcher, faviconMatcher), defaultEntryPointMatcher);
RequestMatcher notXRequestedWith = new NegatedRequestMatcher(
new RequestHeaderRequestMatcher("X-Requested-With", "XMLHttpRequest"));
RequestMatcher formLoginNotEnabled = getFormLoginNotEnabledRequestMatcher(http);
LinkedHashMap<RequestMatcher, AuthenticationEntryPoint> entryPoints = new LinkedHashMap<>();
entryPoints.put(new AndRequestMatcher(notXRequestedWith, new NegatedRequestMatcher(defaultLoginPageMatcher),
formLoginNotEnabled), new LoginUrlAuthenticationEntryPoint(providerLoginPage));
entryPoints.put(new AndRequestMatcher(notXRequestedWith, new NegatedRequestMatcher(defaultLoginPageMatcher)),
new LoginUrlAuthenticationEntryPoint(providerLoginPage));
DelegatingAuthenticationEntryPoint loginEntryPoint = new DelegatingAuthenticationEntryPoint(entryPoints);
loginEntryPoint.setDefaultEntryPoint(this.getAuthenticationEntryPoint());
return loginEntryPoint;
}
private RequestMatcher getFormLoginNotEnabledRequestMatcher(B http) {
DefaultLoginPageGeneratingFilter defaultLoginPageGeneratingFilter = http
.getSharedObject(DefaultLoginPageGeneratingFilter.class);
Field formLoginEnabledField = (defaultLoginPageGeneratingFilter != null)
? ReflectionUtils.findField(DefaultLoginPageGeneratingFilter.class, "formLoginEnabled") : null;
if (formLoginEnabledField != null) {
ReflectionUtils.makeAccessible(formLoginEnabledField);
return (request) -> Boolean.FALSE
.equals(ReflectionUtils.getField(formLoginEnabledField, defaultLoginPageGeneratingFilter));
}
return AnyRequestMatcher.INSTANCE;
}
/**
* Configuration options for the Authorization Server's Authorization Endpoint.
*/
@@ -545,8 +522,6 @@ public final class OAuth2LoginConfigurer<B extends HttpSecurityBuilder<B>>
private AuthorizationRequestRepository<OAuth2AuthorizationRequest> authorizationRequestRepository;
private RedirectStrategy authorizationRedirectStrategy;
private AuthorizationEndpointConfig() {
}
@@ -589,17 +564,6 @@ public final class OAuth2LoginConfigurer<B extends HttpSecurityBuilder<B>>
return this;
}
/**
* Sets the redirect strategy for Authorization Endpoint redirect URI.
* @param authorizationRedirectStrategy the redirect strategy
* @return the {@link AuthorizationEndpointConfig} for further configuration
*/
public AuthorizationEndpointConfig authorizationRedirectStrategy(
RedirectStrategy authorizationRedirectStrategy) {
this.authorizationRedirectStrategy = authorizationRedirectStrategy;
return this;
}
/**
* Returns the {@link OAuth2LoginConfigurer} for further configuration.
* @return the {@link OAuth2LoginConfigurer}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 the original author or authors.
* Copyright 2002-2021 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.
@@ -46,14 +46,13 @@ import org.springframework.security.oauth2.jwt.NimbusJwtDecoder;
import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationConverter;
import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationProvider;
import org.springframework.security.oauth2.server.resource.authentication.OpaqueTokenAuthenticationProvider;
import org.springframework.security.oauth2.server.resource.introspection.OpaqueTokenAuthenticationConverter;
import org.springframework.security.oauth2.server.resource.introspection.OpaqueTokenIntrospector;
import org.springframework.security.oauth2.server.resource.introspection.SpringOpaqueTokenIntrospector;
import org.springframework.security.oauth2.server.resource.web.BearerTokenAuthenticationEntryPoint;
import org.springframework.security.oauth2.server.resource.web.BearerTokenAuthenticationFilter;
import org.springframework.security.oauth2.server.resource.web.BearerTokenResolver;
import org.springframework.security.oauth2.server.resource.web.DefaultBearerTokenResolver;
import org.springframework.security.oauth2.server.resource.web.access.BearerTokenAccessDeniedHandler;
import org.springframework.security.oauth2.server.resource.web.authentication.BearerTokenAuthenticationFilter;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.security.web.access.AccessDeniedHandlerImpl;
@@ -108,8 +107,8 @@ import org.springframework.web.accept.HeaderContentNegotiationStrategy;
* </ul>
*
* <p>
* When using {@link #opaqueToken(Customizer)}, supply an introspection endpoint with its
* client credentials and an OpaqueTokenAuthenticationConverter
* When using {@link #opaqueToken(Customizer)}, supply an introspection endpoint and its
* authentication configuration
* </p>
*
* <h2>Security Filters</h2>
@@ -139,7 +138,6 @@ import org.springframework.web.accept.HeaderContentNegotiationStrategy;
*
* @author Josh Cummings
* @author Evgeniy Cheban
* @author Jerome Wacongne &lt;ch4mp@c4-soft.com&gt;
* @since 5.1
* @see BearerTokenAuthenticationFilter
* @see JwtAuthenticationProvider
@@ -272,7 +270,6 @@ public final class OAuth2ResourceServerConfigurer<H extends HttpSecurityBuilder<
BearerTokenAuthenticationFilter filter = new BearerTokenAuthenticationFilter(resolver);
filter.setBearerTokenResolver(bearerTokenResolver);
filter.setAuthenticationEntryPoint(this.authenticationEntryPoint);
filter.setSecurityContextHolderStrategy(getSecurityContextHolderStrategy());
filter = postProcess(filter);
http.addFilter(filter);
}
@@ -458,8 +455,6 @@ public final class OAuth2ResourceServerConfigurer<H extends HttpSecurityBuilder<
private Supplier<OpaqueTokenIntrospector> introspector;
private OpaqueTokenAuthenticationConverter authenticationConverter;
OpaqueTokenConfigurer(ApplicationContext context) {
this.context = context;
}
@@ -494,13 +489,6 @@ public final class OAuth2ResourceServerConfigurer<H extends HttpSecurityBuilder<
return this;
}
public OpaqueTokenConfigurer authenticationConverter(
OpaqueTokenAuthenticationConverter authenticationConverter) {
Assert.notNull(authenticationConverter, "authenticationConverter cannot be null");
this.authenticationConverter = authenticationConverter;
return this;
}
OpaqueTokenIntrospector getIntrospector() {
if (this.introspector != null) {
return this.introspector.get();
@@ -508,28 +496,12 @@ public final class OAuth2ResourceServerConfigurer<H extends HttpSecurityBuilder<
return this.context.getBean(OpaqueTokenIntrospector.class);
}
OpaqueTokenAuthenticationConverter getAuthenticationConverter() {
if (this.authenticationConverter != null) {
return this.authenticationConverter;
}
if (this.context.getBeanNamesForType(OpaqueTokenAuthenticationConverter.class).length > 0) {
return this.context.getBean(OpaqueTokenAuthenticationConverter.class);
}
return null;
}
AuthenticationProvider getAuthenticationProvider() {
if (this.authenticationManager != null) {
return null;
}
OpaqueTokenIntrospector introspector = getIntrospector();
OpaqueTokenAuthenticationProvider opaqueTokenAuthenticationProvider = new OpaqueTokenAuthenticationProvider(
introspector);
OpaqueTokenAuthenticationConverter authenticationConverter = getAuthenticationConverter();
if (authenticationConverter != null) {
opaqueTokenAuthenticationProvider.setAuthenticationConverter(authenticationConverter);
}
return opaqueTokenAuthenticationProvider;
return new OpaqueTokenAuthenticationProvider(introspector);
}
AuthenticationManager getAuthenticationManager(H http) {
@@ -32,11 +32,15 @@ import org.springframework.security.config.annotation.web.configurers.AbstractHt
import org.springframework.security.config.annotation.web.configurers.CsrfConfigurer;
import org.springframework.security.core.Authentication;
import org.springframework.security.saml2.provider.service.authentication.AbstractSaml2AuthenticationRequest;
import org.springframework.security.saml2.provider.service.authentication.OpenSaml4AuthenticationProvider;
import org.springframework.security.saml2.provider.service.authentication.OpenSaml4AuthenticationRequestFactory;
import org.springframework.security.saml2.provider.service.authentication.OpenSamlAuthenticationProvider;
import org.springframework.security.saml2.provider.service.authentication.OpenSamlAuthenticationRequestFactory;
import org.springframework.security.saml2.provider.service.authentication.Saml2AuthenticationRequestFactory;
import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistration;
import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistrationRepository;
import org.springframework.security.saml2.provider.service.servlet.filter.Saml2WebSsoAuthenticationFilter;
import org.springframework.security.saml2.provider.service.servlet.filter.Saml2WebSsoAuthenticationRequestFilter;
import org.springframework.security.saml2.provider.service.web.DefaultRelyingPartyRegistrationResolver;
import org.springframework.security.saml2.provider.service.web.DefaultSaml2AuthenticationRequestContextResolver;
import org.springframework.security.saml2.provider.service.web.HttpSessionSaml2AuthenticationRequestRepository;
@@ -44,22 +48,13 @@ import org.springframework.security.saml2.provider.service.web.RelyingPartyRegis
import org.springframework.security.saml2.provider.service.web.Saml2AuthenticationRequestContextResolver;
import org.springframework.security.saml2.provider.service.web.Saml2AuthenticationRequestRepository;
import org.springframework.security.saml2.provider.service.web.Saml2AuthenticationTokenConverter;
import org.springframework.security.saml2.provider.service.web.Saml2WebSsoAuthenticationRequestFilter;
import org.springframework.security.saml2.provider.service.web.authentication.Saml2AuthenticationRequestResolver;
import org.springframework.security.saml2.provider.service.web.authentication.Saml2WebSsoAuthenticationFilter;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.authentication.AuthenticationConverter;
import org.springframework.security.web.authentication.DelegatingAuthenticationEntryPoint;
import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint;
import org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter;
import org.springframework.security.web.util.matcher.AndRequestMatcher;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.security.web.util.matcher.NegatedRequestMatcher;
import org.springframework.security.web.util.matcher.OrRequestMatcher;
import org.springframework.security.web.util.matcher.RequestHeaderRequestMatcher;
import org.springframework.security.web.util.matcher.RequestMatcher;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.StringUtils;
/**
@@ -117,8 +112,6 @@ import org.springframework.util.StringUtils;
public final class Saml2LoginConfigurer<B extends HttpSecurityBuilder<B>>
extends AbstractAuthenticationFilterConfigurer<B, Saml2LoginConfigurer<B>, Saml2WebSsoAuthenticationFilter> {
private static final String OPEN_SAML_4_VERSION = "4";
private String loginPage;
private String authenticationRequestUri = "/saml2/authenticate/{registrationId}";
@@ -239,7 +232,6 @@ public final class Saml2LoginConfigurer<B extends HttpSecurityBuilder<B>>
relyingPartyRegistrationRepository(http);
this.saml2WebSsoAuthenticationFilter = new Saml2WebSsoAuthenticationFilter(getAuthenticationConverter(http),
this.loginProcessingUrl);
this.saml2WebSsoAuthenticationFilter.setSecurityContextHolderStrategy(getSecurityContextHolderStrategy());
setAuthenticationRequestRepository(http, this.saml2WebSsoAuthenticationFilter);
setAuthenticationFilter(this.saml2WebSsoAuthenticationFilter);
super.loginProcessingUrl(this.loginProcessingUrl);
@@ -258,7 +250,8 @@ public final class Saml2LoginConfigurer<B extends HttpSecurityBuilder<B>>
this.updateAuthenticationDefaults();
this.updateAccessDefaults(http);
String loginUrl = providerUrlMap.entrySet().iterator().next().getKey();
registerAuthenticationEntryPoint(http, getLoginEntryPoint(http, loginUrl));
final LoginUrlAuthenticationEntryPoint entryPoint = new LoginUrlAuthenticationEntryPoint(loginUrl);
registerAuthenticationEntryPoint(http, entryPoint);
}
else {
super.init(http);
@@ -300,22 +293,6 @@ public final class Saml2LoginConfigurer<B extends HttpSecurityBuilder<B>>
return this.relyingPartyRegistrationRepository;
}
private AuthenticationEntryPoint getLoginEntryPoint(B http, String providerLoginPage) {
RequestMatcher loginPageMatcher = new AntPathRequestMatcher(this.getLoginPage());
RequestMatcher faviconMatcher = new AntPathRequestMatcher("/favicon.ico");
RequestMatcher defaultEntryPointMatcher = this.getAuthenticationEntryPointMatcher(http);
RequestMatcher defaultLoginPageMatcher = new AndRequestMatcher(
new OrRequestMatcher(loginPageMatcher, faviconMatcher), defaultEntryPointMatcher);
RequestMatcher notXRequestedWith = new NegatedRequestMatcher(
new RequestHeaderRequestMatcher("X-Requested-With", "XMLHttpRequest"));
LinkedHashMap<RequestMatcher, AuthenticationEntryPoint> entryPoints = new LinkedHashMap<>();
entryPoints.put(new AndRequestMatcher(notXRequestedWith, new NegatedRequestMatcher(defaultLoginPageMatcher)),
new LoginUrlAuthenticationEntryPoint(providerLoginPage));
DelegatingAuthenticationEntryPoint loginEntryPoint = new DelegatingAuthenticationEntryPoint(entryPoints);
loginEntryPoint.setDefaultEntryPoint(this.getAuthenticationEntryPoint());
return loginEntryPoint;
}
private void setAuthenticationRequestRepository(B http,
Saml2WebSsoAuthenticationFilter saml2WebSsoAuthenticationFilter) {
saml2WebSsoAuthenticationFilter.setAuthenticationRequestRepository(getAuthenticationRequestRepository(http));
@@ -343,9 +320,11 @@ public final class Saml2LoginConfigurer<B extends HttpSecurityBuilder<B>>
return resolver;
}
if (version().startsWith("4")) {
return OpenSaml4LoginSupportFactory.getAuthenticationRequestFactory();
return new OpenSaml4AuthenticationRequestFactory();
}
else {
return new OpenSamlAuthenticationRequestFactory();
}
return new OpenSamlAuthenticationRequestFactory();
}
private Saml2AuthenticationRequestContextResolver getAuthenticationRequestContextResolver(B http) {
@@ -375,9 +354,17 @@ public final class Saml2LoginConfigurer<B extends HttpSecurityBuilder<B>>
return authenticationConverterBean;
}
private String version() {
String version = Version.getVersion();
if (version != null) {
return version;
}
return Version.getVersion();
}
private void registerDefaultAuthenticationProvider(B http) {
if (version().startsWith("4")) {
http.authenticationProvider(postProcess(OpenSaml4LoginSupportFactory.getAuthenticationProvider()));
http.authenticationProvider(postProcess(new OpenSaml4AuthenticationProvider()));
}
else {
http.authenticationProvider(postProcess(new OpenSamlAuthenticationProvider()));
@@ -427,19 +414,6 @@ public final class Saml2LoginConfigurer<B extends HttpSecurityBuilder<B>>
return repository;
}
private String version() {
String version = Version.getVersion();
if (StringUtils.hasText(version)) {
return version;
}
boolean openSaml4ClassPresent = ClassUtils
.isPresent("org.opensaml.core.xml.persist.impl.PassthroughSourceStrategy", null);
if (openSaml4ClassPresent) {
return OPEN_SAML_4_VERSION;
}
throw new IllegalStateException("cannot determine OpenSAML version");
}
private <C> C getSharedOrBean(B http, Class<C> clazz) {
C shared = http.getSharedObject(clazz);
if (shared != null) {
@@ -467,33 +441,4 @@ public final class Saml2LoginConfigurer<B extends HttpSecurityBuilder<B>>
}
}
private static class OpenSaml4LoginSupportFactory {
private static Saml2AuthenticationRequestFactory getAuthenticationRequestFactory() {
try {
Class<?> authenticationRequestFactory = ClassUtils.forName(
"org.springframework.security.saml2.provider.service.authentication.OpenSaml4AuthenticationRequestFactory",
OpenSaml4LoginSupportFactory.class.getClassLoader());
return (Saml2AuthenticationRequestFactory) authenticationRequestFactory.getDeclaredConstructor()
.newInstance();
}
catch (ReflectiveOperationException ex) {
throw new IllegalStateException("Could not instantiate OpenSaml4AuthenticationRequestFactory", ex);
}
}
private static AuthenticationProvider getAuthenticationProvider() {
try {
Class<?> authenticationProvider = ClassUtils.forName(
"org.springframework.security.saml2.provider.service.authentication.OpenSaml4AuthenticationProvider",
OpenSaml4LoginSupportFactory.class.getClassLoader());
return (AuthenticationProvider) authenticationProvider.getDeclaredConstructor().newInstance();
}
catch (ReflectiveOperationException ex) {
throw new IllegalStateException("Could not instantiate OpenSaml4AuthenticationProvider", ex);
}
}
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 the original author or authors.
* Copyright 2002-2021 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.
@@ -34,7 +34,7 @@ import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.config.annotation.web.configurers.LogoutConfigurer;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolderStrategy;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.saml2.provider.service.authentication.Saml2AuthenticatedPrincipal;
import org.springframework.security.saml2.provider.service.authentication.logout.OpenSamlLogoutRequestValidator;
import org.springframework.security.saml2.provider.service.authentication.logout.OpenSamlLogoutResponseValidator;
@@ -47,6 +47,8 @@ import org.springframework.security.saml2.provider.service.web.RelyingPartyRegis
import org.springframework.security.saml2.provider.service.web.authentication.logout.HttpSessionLogoutRequestRepository;
import org.springframework.security.saml2.provider.service.web.authentication.logout.OpenSaml3LogoutRequestResolver;
import org.springframework.security.saml2.provider.service.web.authentication.logout.OpenSaml3LogoutResponseResolver;
import org.springframework.security.saml2.provider.service.web.authentication.logout.OpenSaml4LogoutRequestResolver;
import org.springframework.security.saml2.provider.service.web.authentication.logout.OpenSaml4LogoutResponseResolver;
import org.springframework.security.saml2.provider.service.web.authentication.logout.Saml2LogoutRequestFilter;
import org.springframework.security.saml2.provider.service.web.authentication.logout.Saml2LogoutRequestRepository;
import org.springframework.security.saml2.provider.service.web.authentication.logout.Saml2LogoutRequestResolver;
@@ -65,8 +67,6 @@ import org.springframework.security.web.csrf.CsrfTokenRepository;
import org.springframework.security.web.util.matcher.AndRequestMatcher;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.security.web.util.matcher.RequestMatcher;
import org.springframework.util.ClassUtils;
import org.springframework.util.StringUtils;
/**
* Adds SAML 2.0 logout support.
@@ -113,8 +113,6 @@ import org.springframework.util.StringUtils;
public final class Saml2LogoutConfigurer<H extends HttpSecurityBuilder<H>>
extends AbstractHttpConfigurer<Saml2LogoutConfigurer<H>, H> {
private static final String OPEN_SAML_4_VERSION = "4";
private ApplicationContext context;
private RelyingPartyRegistrationRepository relyingPartyRegistrationRepository;
@@ -150,7 +148,7 @@ public final class Saml2LogoutConfigurer<H extends HttpSecurityBuilder<H>>
* <p>
* The Relying Party triggers logout by POSTing to the endpoint. The Asserting Party
* triggers logout based on what is specified by
* {@link RelyingPartyRegistration#getSingleLogoutServiceBindings()}.
* {@link RelyingPartyRegistration#getSingleLogoutServiceBinding()}.
* @param logoutUrl the URL that will invoke logout
* @return the {@link LogoutConfigurer} for further customizations
* @see LogoutConfigurer#logoutUrl(String)
@@ -255,7 +253,6 @@ public final class Saml2LogoutConfigurer<H extends HttpSecurityBuilder<H>>
Saml2LogoutRequestFilter filter = new Saml2LogoutRequestFilter(registrations,
this.logoutRequestConfigurer.logoutRequestValidator(), logoutResponseResolver, logoutHandlers);
filter.setLogoutRequestMatcher(createLogoutRequestMatcher());
filter.setSecurityContextHolderStrategy(getSecurityContextHolderStrategy());
return postProcess(filter);
}
@@ -272,7 +269,6 @@ public final class Saml2LogoutConfigurer<H extends HttpSecurityBuilder<H>>
LogoutHandler[] logoutHandlers = this.logoutHandlers.toArray(new LogoutHandler[0]);
Saml2RelyingPartyInitiatedLogoutSuccessHandler logoutRequestSuccessHandler = createSaml2LogoutRequestSuccessHandler(
registrations);
logoutRequestSuccessHandler.setLogoutRequestRepository(this.logoutRequestConfigurer.logoutRequestRepository);
LogoutFilter logoutFilter = new LogoutFilter(logoutRequestSuccessHandler, logoutHandlers);
logoutFilter.setLogoutRequestMatcher(createLogoutMatcher());
return postProcess(logoutFilter);
@@ -280,7 +276,7 @@ public final class Saml2LogoutConfigurer<H extends HttpSecurityBuilder<H>>
private RequestMatcher createLogoutMatcher() {
RequestMatcher logout = new AntPathRequestMatcher(this.logoutUrl, "POST");
RequestMatcher saml2 = new Saml2RequestMatcher(getSecurityContextHolderStrategy());
RequestMatcher saml2 = new Saml2RequestMatcher();
return new AndRequestMatcher(logout, saml2);
}
@@ -308,19 +304,6 @@ public final class Saml2LogoutConfigurer<H extends HttpSecurityBuilder<H>>
return this.logoutResponseConfigurer.logoutResponseResolver(relyingPartyRegistrationResolver);
}
private String version() {
String version = Version.getVersion();
if (StringUtils.hasText(version)) {
return version;
}
boolean openSaml4ClassPresent = ClassUtils
.isPresent("org.opensaml.core.xml.persist.impl.PassthroughSourceStrategy", null);
if (openSaml4ClassPresent) {
return OPEN_SAML_4_VERSION;
}
throw new IllegalStateException("cannot determine OpenSAML version");
}
private <C> C getBeanOrNull(Class<C> clazz) {
if (this.context == null) {
return null;
@@ -331,6 +314,14 @@ public final class Saml2LogoutConfigurer<H extends HttpSecurityBuilder<H>>
return this.context.getBean(clazz);
}
private String version() {
String version = Version.getVersion();
if (version != null) {
return version;
}
return Version.getVersion();
}
/**
* A configurer for SAML 2.0 LogoutRequest components
*/
@@ -352,7 +343,7 @@ public final class Saml2LogoutConfigurer<H extends HttpSecurityBuilder<H>>
*
* <p>
* The Asserting Party should use whatever HTTP method specified in
* {@link RelyingPartyRegistration#getSingleLogoutServiceBindings()}.
* {@link RelyingPartyRegistration#getSingleLogoutServiceBinding()}.
* @param logoutUrl the URL that will receive the SAML 2.0 Logout Request
* @return the {@link LogoutRequestConfigurer} for further customizations
* @see Saml2LogoutConfigurer#logoutUrl(String)
@@ -411,7 +402,7 @@ public final class Saml2LogoutConfigurer<H extends HttpSecurityBuilder<H>>
return this.logoutRequestResolver;
}
if (version().startsWith("4")) {
return OpenSaml4LogoutSupportFactory.getLogoutRequestResolver(relyingPartyRegistrationResolver);
return new OpenSaml4LogoutRequestResolver(relyingPartyRegistrationResolver);
}
return new OpenSaml3LogoutRequestResolver(relyingPartyRegistrationResolver);
}
@@ -434,7 +425,7 @@ public final class Saml2LogoutConfigurer<H extends HttpSecurityBuilder<H>>
*
* <p>
* The Asserting Party should use whatever HTTP method specified in
* {@link RelyingPartyRegistration#getSingleLogoutServiceBindings()}.
* {@link RelyingPartyRegistration#getSingleLogoutServiceBinding()}.
* @param logoutUrl the URL that will receive the SAML 2.0 Logout Response
* @return the {@link LogoutResponseConfigurer} for further customizations
* @see Saml2LogoutConfigurer#logoutUrl(String)
@@ -479,28 +470,22 @@ public final class Saml2LogoutConfigurer<H extends HttpSecurityBuilder<H>>
private Saml2LogoutResponseResolver logoutResponseResolver(
RelyingPartyRegistrationResolver relyingPartyRegistrationResolver) {
if (this.logoutResponseResolver != null) {
return this.logoutResponseResolver;
if (this.logoutResponseResolver == null) {
if (version().startsWith("4")) {
return new OpenSaml4LogoutResponseResolver(relyingPartyRegistrationResolver);
}
return new OpenSaml3LogoutResponseResolver(relyingPartyRegistrationResolver);
}
if (version().startsWith("4")) {
return OpenSaml4LogoutSupportFactory.getLogoutResponseResolver(relyingPartyRegistrationResolver);
}
return new OpenSaml3LogoutResponseResolver(relyingPartyRegistrationResolver);
return this.logoutResponseResolver;
}
}
private static class Saml2RequestMatcher implements RequestMatcher {
private final SecurityContextHolderStrategy securityContextHolderStrategy;
Saml2RequestMatcher(SecurityContextHolderStrategy securityContextHolderStrategy) {
this.securityContextHolderStrategy = securityContextHolderStrategy;
}
@Override
public boolean matches(HttpServletRequest request) {
Authentication authentication = this.securityContextHolderStrategy.getContext().getAuthentication();
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (authentication == null) {
return false;
}
@@ -534,38 +519,4 @@ public final class Saml2LogoutConfigurer<H extends HttpSecurityBuilder<H>>
}
private static class OpenSaml4LogoutSupportFactory {
private static Saml2LogoutResponseResolver getLogoutResponseResolver(
RelyingPartyRegistrationResolver relyingPartyRegistrationResolver) {
try {
Class<?> logoutResponseResolver = ClassUtils.forName(
"org.springframework.security.saml2.provider.service.web.authentication.logout.OpenSaml4LogoutResponseResolver",
OpenSaml4LogoutSupportFactory.class.getClassLoader());
return (Saml2LogoutResponseResolver) logoutResponseResolver
.getDeclaredConstructor(RelyingPartyRegistrationResolver.class)
.newInstance(relyingPartyRegistrationResolver);
}
catch (ReflectiveOperationException ex) {
throw new IllegalStateException("Could not instantiate OpenSaml4LogoutResponseResolver", ex);
}
}
private static Saml2LogoutRequestResolver getLogoutRequestResolver(
RelyingPartyRegistrationResolver relyingPartyRegistrationResolver) {
try {
Class<?> logoutRequestResolver = ClassUtils.forName(
"org.springframework.security.saml2.provider.service.web.authentication.logout.OpenSaml4LogoutRequestResolver",
OpenSaml4LogoutSupportFactory.class.getClassLoader());
return (Saml2LogoutRequestResolver) logoutRequestResolver
.getDeclaredConstructor(RelyingPartyRegistrationResolver.class)
.newInstance(relyingPartyRegistrationResolver);
}
catch (ReflectiveOperationException ex) {
throw new IllegalStateException("Could not instantiate OpenSaml4LogoutRequestResolver", ex);
}
}
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 the original author or authors.
* Copyright 2002-2016 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.
@@ -28,7 +28,6 @@ import org.springframework.security.access.expression.SecurityExpressionHandler;
import org.springframework.security.config.annotation.web.configurers.RememberMeConfigurer;
import org.springframework.security.messaging.access.expression.DefaultMessageSecurityExpressionHandler;
import org.springframework.security.messaging.access.expression.ExpressionBasedMessageSecurityMetadataSourceFactory;
import org.springframework.security.messaging.access.intercept.MessageMatcherDelegatingAuthorizationManager;
import org.springframework.security.messaging.access.intercept.MessageSecurityMetadataSource;
import org.springframework.security.messaging.util.matcher.MessageMatcher;
import org.springframework.security.messaging.util.matcher.SimpDestinationMessageMatcher;
@@ -44,9 +43,7 @@ import org.springframework.util.StringUtils;
*
* @author Rob Winch
* @since 4.0
* @deprecated Use {@link MessageMatcherDelegatingAuthorizationManager} instead
*/
@Deprecated
public class MessageSecurityMetadataSourceRegistry {
private static final String permitAll = "permitAll";
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 the original author or authors.
* Copyright 2002-2019 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.
@@ -81,12 +81,9 @@ import org.springframework.web.socket.sockjs.transport.TransportHandlingSockJsSe
*
* @author Rob Winch
* @since 4.0
* @see WebSocketMessageBrokerSecurityConfiguration
* @deprecated Use {@link EnableWebSocketSecurity} instead
*/
@Order(Ordered.HIGHEST_PRECEDENCE + 100)
@Import(ObjectPostProcessorConfiguration.class)
@Deprecated
public abstract class AbstractSecurityWebSocketMessageBrokerConfigurer extends AbstractWebSocketMessageBrokerConfigurer
implements SmartInitializingSingleton {
@@ -1,58 +0,0 @@
/*
* Copyright 2002-2022 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 org.springframework.security.config.annotation.web.socket;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.context.annotation.Import;
/**
* Allows configuring WebSocket Authorization.
*
* <p>
* For example:
* </p>
*
* <pre>
* &#064;Configuration
* &#064;EnableWebSocketSecurity
* public class WebSocketSecurityConfig {
*
* &#064;Bean
* AuthorizationManager&lt;Message&lt;?&gt;&gt; authorizationManager(MessageMatcherDelegatingAuthorizationManager.Builder messages) {
* messages.simpDestMatchers(&quot;/user/queue/errors&quot;).permitAll()
* .simpDestMatchers(&quot;/admin/**&quot;).hasRole(&quot;ADMIN&quot;)
* .anyMessage().authenticated();
* return messages.build();
* }
* }
* </pre>
*
* @author Josh Cummings
* @since 5.8
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Import(WebSocketMessageBrokerSecurityConfiguration.class)
public @interface EnableWebSocketSecurity {
}
@@ -1,38 +0,0 @@
/*
* Copyright 2002-2022 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 org.springframework.security.config.annotation.web.socket;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Scope;
import org.springframework.messaging.simp.annotation.support.SimpAnnotationMethodMessageHandler;
import org.springframework.security.messaging.access.intercept.MessageMatcherDelegatingAuthorizationManager;
import org.springframework.util.AntPathMatcher;
final class MessageMatcherAuthorizationManagerConfiguration {
@Bean
@Scope("prototype")
MessageMatcherDelegatingAuthorizationManager.Builder messageAuthorizationManagerBuilder(
ApplicationContext context) {
return MessageMatcherDelegatingAuthorizationManager.builder().simpDestPathMatcher(
() -> (context.getBeanNamesForType(SimpAnnotationMethodMessageHandler.class).length > 0)
? context.getBean(SimpAnnotationMethodMessageHandler.class).getPathMatcher()
: new AntPathMatcher());
}
}
@@ -1,168 +0,0 @@
/*
* Copyright 2002-2023 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 org.springframework.security.config.annotation.web.socket;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.SmartInitializingSingleton;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Import;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.messaging.Message;
import org.springframework.messaging.handler.invocation.HandlerMethodArgumentResolver;
import org.springframework.messaging.simp.config.ChannelRegistration;
import org.springframework.messaging.support.ChannelInterceptor;
import org.springframework.security.authorization.AuthorizationManager;
import org.springframework.security.authorization.SpringAuthorizationEventPublisher;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.context.SecurityContextHolderStrategy;
import org.springframework.security.messaging.access.intercept.AuthorizationChannelInterceptor;
import org.springframework.security.messaging.access.intercept.MessageMatcherDelegatingAuthorizationManager;
import org.springframework.security.messaging.context.AuthenticationPrincipalArgumentResolver;
import org.springframework.security.messaging.context.SecurityContextChannelInterceptor;
import org.springframework.security.messaging.web.csrf.CsrfChannelInterceptor;
import org.springframework.security.messaging.web.socket.server.CsrfTokenHandshakeInterceptor;
import org.springframework.util.Assert;
import org.springframework.web.servlet.handler.SimpleUrlHandlerMapping;
import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer;
import org.springframework.web.socket.server.HandshakeInterceptor;
import org.springframework.web.socket.server.support.WebSocketHttpRequestHandler;
import org.springframework.web.socket.sockjs.SockJsService;
import org.springframework.web.socket.sockjs.support.SockJsHttpRequestHandler;
import org.springframework.web.socket.sockjs.transport.TransportHandlingSockJsService;
@Order(Ordered.HIGHEST_PRECEDENCE + 100)
@Import(MessageMatcherAuthorizationManagerConfiguration.class)
final class WebSocketMessageBrokerSecurityConfiguration
implements WebSocketMessageBrokerConfigurer, SmartInitializingSingleton {
private static final String SIMPLE_URL_HANDLER_MAPPING_BEAN_NAME = "stompWebSocketHandlerMapping";
private static final String CSRF_CHANNEL_INTERCEPTOR_BEAN_NAME = "csrfChannelInterceptor";
private MessageMatcherDelegatingAuthorizationManager b;
private static final AuthorizationManager<Message<?>> ANY_MESSAGE_AUTHENTICATED = MessageMatcherDelegatingAuthorizationManager
.builder().anyMessage().authenticated().build();
private SecurityContextHolderStrategy securityContextHolderStrategy = SecurityContextHolder
.getContextHolderStrategy();
private final SecurityContextChannelInterceptor securityContextChannelInterceptor = new SecurityContextChannelInterceptor();
private ChannelInterceptor csrfChannelInterceptor = new CsrfChannelInterceptor();
private AuthorizationChannelInterceptor authorizationChannelInterceptor = new AuthorizationChannelInterceptor(
ANY_MESSAGE_AUTHENTICATED);
private ApplicationContext context;
WebSocketMessageBrokerSecurityConfiguration(ApplicationContext context) {
this.context = context;
}
@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
AuthenticationPrincipalArgumentResolver resolver = new AuthenticationPrincipalArgumentResolver();
resolver.setSecurityContextHolderStrategy(this.securityContextHolderStrategy);
argumentResolvers.add(resolver);
}
@Override
public void configureClientInboundChannel(ChannelRegistration registration) {
ChannelInterceptor csrfChannelInterceptor = getBeanOrNull(CSRF_CHANNEL_INTERCEPTOR_BEAN_NAME,
ChannelInterceptor.class);
if (csrfChannelInterceptor != null) {
this.csrfChannelInterceptor = csrfChannelInterceptor;
}
this.authorizationChannelInterceptor
.setAuthorizationEventPublisher(new SpringAuthorizationEventPublisher(this.context));
this.authorizationChannelInterceptor.setSecurityContextHolderStrategy(this.securityContextHolderStrategy);
this.securityContextChannelInterceptor.setSecurityContextHolderStrategy(this.securityContextHolderStrategy);
registration.interceptors(this.securityContextChannelInterceptor, this.csrfChannelInterceptor,
this.authorizationChannelInterceptor);
}
@Autowired(required = false)
void setSecurityContextHolderStrategy(SecurityContextHolderStrategy securityContextHolderStrategy) {
Assert.notNull(securityContextHolderStrategy, "securityContextHolderStrategy cannot be null");
this.securityContextHolderStrategy = securityContextHolderStrategy;
}
@Autowired(required = false)
void setAuthorizationManager(AuthorizationManager<Message<?>> authorizationManager) {
this.authorizationChannelInterceptor = new AuthorizationChannelInterceptor(authorizationManager);
}
@Override
public void afterSingletonsInstantiated() {
SimpleUrlHandlerMapping mapping = getBeanOrNull(SIMPLE_URL_HANDLER_MAPPING_BEAN_NAME,
SimpleUrlHandlerMapping.class);
if (mapping == null) {
return;
}
configureCsrf(mapping);
}
private <T> T getBeanOrNull(String name, Class<T> type) {
Map<String, T> beans = this.context.getBeansOfType(type);
return beans.get(name);
}
private void configureCsrf(SimpleUrlHandlerMapping mapping) {
Map<String, Object> mappings = mapping.getHandlerMap();
for (Object object : mappings.values()) {
if (object instanceof SockJsHttpRequestHandler) {
setHandshakeInterceptors((SockJsHttpRequestHandler) object);
}
else if (object instanceof WebSocketHttpRequestHandler) {
setHandshakeInterceptors((WebSocketHttpRequestHandler) object);
}
else {
throw new IllegalStateException(
"Bean " + SIMPLE_URL_HANDLER_MAPPING_BEAN_NAME + " is expected to contain mappings to either a "
+ "SockJsHttpRequestHandler or a WebSocketHttpRequestHandler but got " + object);
}
}
}
private void setHandshakeInterceptors(SockJsHttpRequestHandler handler) {
SockJsService sockJsService = handler.getSockJsService();
Assert.state(sockJsService instanceof TransportHandlingSockJsService,
() -> "sockJsService must be instance of TransportHandlingSockJsService got " + sockJsService);
TransportHandlingSockJsService transportHandlingSockJsService = (TransportHandlingSockJsService) sockJsService;
List<HandshakeInterceptor> handshakeInterceptors = transportHandlingSockJsService.getHandshakeInterceptors();
List<HandshakeInterceptor> interceptorsToSet = new ArrayList<>(handshakeInterceptors.size() + 1);
interceptorsToSet.add(new CsrfTokenHandshakeInterceptor());
interceptorsToSet.addAll(handshakeInterceptors);
transportHandlingSockJsService.setHandshakeInterceptors(interceptorsToSet);
}
private void setHandshakeInterceptors(WebSocketHttpRequestHandler handler) {
List<HandshakeInterceptor> handshakeInterceptors = handler.getHandshakeInterceptors();
List<HandshakeInterceptor> interceptorsToSet = new ArrayList<>(handshakeInterceptors.size() + 1);
interceptorsToSet.add(new CsrfTokenHandshakeInterceptor());
interceptorsToSet.addAll(handshakeInterceptors);
handler.setHandshakeInterceptors(interceptorsToSet);
}
}
@@ -236,7 +236,6 @@ final class AuthenticationConfigBuilder {
AuthenticationConfigBuilder(Element element, boolean forceAutoConfig, ParserContext pc,
SessionCreationPolicy sessionPolicy, BeanReference requestCache, BeanReference authenticationManager,
BeanMetadataElement authenticationFilterSecurityContextHolderStrategyRef,
BeanReference authenticationFilterSecurityContextRepositoryRef, BeanReference sessionStrategy,
BeanReference portMapper, BeanReference portResolver, BeanMetadataElement csrfLogoutHandler) {
this.httpElt = element;
@@ -248,29 +247,26 @@ final class AuthenticationConfigBuilder {
this.portMapper = portMapper;
this.portResolver = portResolver;
this.csrfLogoutHandler = csrfLogoutHandler;
createAnonymousFilter(authenticationFilterSecurityContextHolderStrategyRef);
createRememberMeFilter(authenticationManager, authenticationFilterSecurityContextHolderStrategyRef);
createBasicFilter(authenticationManager, authenticationFilterSecurityContextHolderStrategyRef);
createBearerTokenAuthenticationFilter(authenticationManager,
authenticationFilterSecurityContextHolderStrategyRef);
createFormLoginFilter(sessionStrategy, authenticationManager,
authenticationFilterSecurityContextHolderStrategyRef, authenticationFilterSecurityContextRepositoryRef);
createAnonymousFilter();
createRememberMeFilter(authenticationManager);
createBasicFilter(authenticationManager);
createBearerTokenAuthenticationFilter(authenticationManager);
createFormLoginFilter(sessionStrategy, authenticationManager, authenticationFilterSecurityContextRepositoryRef);
createOAuth2ClientFilters(sessionStrategy, requestCache, authenticationManager,
authenticationFilterSecurityContextRepositoryRef, authenticationFilterSecurityContextHolderStrategyRef);
authenticationFilterSecurityContextRepositoryRef);
createOpenIDLoginFilter(sessionStrategy, authenticationManager,
authenticationFilterSecurityContextRepositoryRef);
createSaml2LoginFilter(authenticationManager, authenticationFilterSecurityContextRepositoryRef);
createX509Filter(authenticationManager, authenticationFilterSecurityContextHolderStrategyRef);
createJeeFilter(authenticationManager, authenticationFilterSecurityContextHolderStrategyRef);
createLogoutFilter(authenticationFilterSecurityContextHolderStrategyRef);
createSaml2LogoutFilter(authenticationFilterSecurityContextHolderStrategyRef);
createX509Filter(authenticationManager);
createJeeFilter(authenticationManager);
createLogoutFilter();
createSaml2LogoutFilter();
createLoginPageFilterIfNeeded();
createUserDetailsServiceFactory();
createExceptionTranslationFilter(authenticationFilterSecurityContextHolderStrategyRef);
createExceptionTranslationFilter();
}
void createRememberMeFilter(BeanReference authenticationManager,
BeanMetadataElement authenticationFilterSecurityContextHolderStrategyRef) {
void createRememberMeFilter(BeanReference authenticationManager) {
// Parse remember me before logout as RememberMeServices is also a LogoutHandler
// implementation.
Element rememberMeElt = DomUtils.getChildElementByTagName(this.httpElt, Elements.REMEMBER_ME);
@@ -280,7 +276,7 @@ final class AuthenticationConfigBuilder {
key = createKey();
}
RememberMeBeanDefinitionParser rememberMeParser = new RememberMeBeanDefinitionParser(key,
authenticationManager, authenticationFilterSecurityContextHolderStrategyRef);
authenticationManager);
this.rememberMeFilter = rememberMeParser.parse(rememberMeElt, this.pc);
this.rememberMeServicesId = rememberMeParser.getRememberMeServicesId();
createRememberMeProvider(key);
@@ -297,7 +293,6 @@ final class AuthenticationConfigBuilder {
}
void createFormLoginFilter(BeanReference sessionStrategy, BeanReference authManager,
BeanMetadataElement authenticationFilterSecurityContextHolderStrategyRef,
BeanReference authenticationFilterSecurityContextRepositoryRef) {
Element formLoginElt = DomUtils.getChildElementByTagName(this.httpElt, Elements.FORM_LOGIN);
RootBeanDefinition formFilter = null;
@@ -318,8 +313,6 @@ final class AuthenticationConfigBuilder {
formFilter.getPropertyValues().addPropertyValue("securityContextRepository",
authenticationFilterSecurityContextRepositoryRef);
}
formFilter.getPropertyValues().addPropertyValue("securityContextHolderStrategy",
authenticationFilterSecurityContextHolderStrategyRef);
// Id is required by login page filter
this.formFilterId = this.pc.getReaderContext().generateBeanName(formFilter);
this.pc.registerBeanComponent(new BeanComponentDefinition(formFilter, this.formFilterId));
@@ -328,26 +321,22 @@ final class AuthenticationConfigBuilder {
}
void createOAuth2ClientFilters(BeanReference sessionStrategy, BeanReference requestCache,
BeanReference authenticationManager, BeanReference authenticationFilterSecurityContextRepositoryRef,
BeanMetadataElement authenticationFilterSecurityContextHolderStrategy) {
BeanReference authenticationManager, BeanReference authenticationFilterSecurityContextRepositoryRef) {
createOAuth2LoginFilter(sessionStrategy, authenticationManager,
authenticationFilterSecurityContextRepositoryRef, authenticationFilterSecurityContextHolderStrategy);
createOAuth2ClientFilter(requestCache, authenticationManager, authenticationFilterSecurityContextRepositoryRef,
authenticationFilterSecurityContextHolderStrategy);
authenticationFilterSecurityContextRepositoryRef);
createOAuth2ClientFilter(requestCache, authenticationManager, authenticationFilterSecurityContextRepositoryRef);
registerOAuth2ClientPostProcessors();
}
void createOAuth2LoginFilter(BeanReference sessionStrategy, BeanReference authManager,
BeanReference authenticationFilterSecurityContextRepositoryRef,
BeanMetadataElement authenticationFilterSecurityContextHolderStrategy) {
BeanReference authenticationFilterSecurityContextRepositoryRef) {
Element oauth2LoginElt = DomUtils.getChildElementByTagName(this.httpElt, Elements.OAUTH2_LOGIN);
if (oauth2LoginElt == null) {
return;
}
this.oauth2LoginEnabled = true;
OAuth2LoginBeanDefinitionParser parser = new OAuth2LoginBeanDefinitionParser(this.requestCache, this.portMapper,
this.portResolver, sessionStrategy, this.allowSessionCreation,
authenticationFilterSecurityContextHolderStrategy);
this.portResolver, sessionStrategy, this.allowSessionCreation);
BeanDefinition oauth2LoginFilterBean = parser.parse(oauth2LoginElt, this.pc);
BeanDefinition defaultAuthorizedClientRepository = parser.getDefaultAuthorizedClientRepository();
registerDefaultAuthorizedClientRepositoryIfNecessary(defaultAuthorizedClientRepository);
@@ -386,16 +375,14 @@ final class AuthenticationConfigBuilder {
}
void createOAuth2ClientFilter(BeanReference requestCache, BeanReference authenticationManager,
BeanReference authenticationFilterSecurityContextRepositoryRef,
BeanMetadataElement authenticationFilterSecurityContextHolderStrategy) {
BeanReference authenticationFilterSecurityContextRepositoryRef) {
Element oauth2ClientElt = DomUtils.getChildElementByTagName(this.httpElt, Elements.OAUTH2_CLIENT);
if (oauth2ClientElt == null) {
return;
}
this.oauth2ClientEnabled = true;
OAuth2ClientBeanDefinitionParser parser = new OAuth2ClientBeanDefinitionParser(requestCache,
authenticationManager, authenticationFilterSecurityContextRepositoryRef,
authenticationFilterSecurityContextHolderStrategy);
authenticationManager, authenticationFilterSecurityContextRepositoryRef);
parser.parse(oauth2ClientElt, this.pc);
BeanDefinition defaultAuthorizedClientRepository = parser.getDefaultAuthorizedClientRepository();
registerDefaultAuthorizedClientRepositoryIfNecessary(defaultAuthorizedClientRepository);
@@ -577,8 +564,7 @@ final class AuthenticationConfigBuilder {
}
}
void createBasicFilter(BeanReference authManager,
BeanMetadataElement authenticationFilterSecurityContextHolderStrategyRef) {
void createBasicFilter(BeanReference authManager) {
Element basicAuthElt = DomUtils.getChildElementByTagName(this.httpElt, Elements.BASIC_AUTH);
if (basicAuthElt == null && !this.autoConfig) {
// No basic auth, do nothing
@@ -606,13 +592,10 @@ final class AuthenticationConfigBuilder {
}
filterBuilder.addConstructorArgValue(authManager);
filterBuilder.addConstructorArgValue(this.basicEntryPoint);
filterBuilder.addPropertyValue("securityContextHolderStrategy",
authenticationFilterSecurityContextHolderStrategyRef);
this.basicFilter = filterBuilder.getBeanDefinition();
}
void createBearerTokenAuthenticationFilter(BeanReference authManager,
BeanMetadataElement authenticationFilterSecurityContextHolderStrategyRef) {
void createBearerTokenAuthenticationFilter(BeanReference authManager) {
Element resourceServerElt = DomUtils.getChildElementByTagName(this.httpElt, Elements.OAUTH2_RESOURCE_SERVER);
if (resourceServerElt == null) {
// No resource server, do nothing
@@ -620,13 +603,11 @@ final class AuthenticationConfigBuilder {
}
OAuth2ResourceServerBeanDefinitionParser resourceServerBuilder = new OAuth2ResourceServerBeanDefinitionParser(
authManager, this.authenticationProviders, this.defaultEntryPointMappings,
this.defaultDeniedHandlerMappings, this.csrfIgnoreRequestMatchers,
authenticationFilterSecurityContextHolderStrategyRef);
this.defaultDeniedHandlerMappings, this.csrfIgnoreRequestMatchers);
this.bearerTokenAuthenticationFilter = resourceServerBuilder.parse(resourceServerElt, this.pc);
}
void createX509Filter(BeanReference authManager,
BeanMetadataElement authenticationFilterSecurityContextHolderStrategyRef) {
void createX509Filter(BeanReference authManager) {
Element x509Elt = DomUtils.getChildElementByTagName(this.httpElt, Elements.X509);
RootBeanDefinition filter = null;
if (x509Elt != null) {
@@ -634,8 +615,6 @@ final class AuthenticationConfigBuilder {
.rootBeanDefinition(X509AuthenticationFilter.class);
filterBuilder.getRawBeanDefinition().setSource(this.pc.extractSource(x509Elt));
filterBuilder.addPropertyValue("authenticationManager", authManager);
filterBuilder.addPropertyValue("securityContextHolderStrategy",
authenticationFilterSecurityContextHolderStrategyRef);
String regex = x509Elt.getAttribute("subject-principal-regex");
if (StringUtils.hasText(regex)) {
BeanDefinitionBuilder extractor = BeanDefinitionBuilder
@@ -676,8 +655,7 @@ final class AuthenticationConfigBuilder {
}
}
void createJeeFilter(BeanReference authManager,
BeanMetadataElement authenticationFilterSecurityContextHolderStrategyRef) {
void createJeeFilter(BeanReference authManager) {
Element jeeElt = DomUtils.getChildElementByTagName(this.httpElt, Elements.JEE);
RootBeanDefinition filter = null;
if (jeeElt != null) {
@@ -685,8 +663,6 @@ final class AuthenticationConfigBuilder {
.rootBeanDefinition(J2eePreAuthenticatedProcessingFilter.class);
filterBuilder.getRawBeanDefinition().setSource(this.pc.extractSource(jeeElt));
filterBuilder.addPropertyValue("authenticationManager", authManager);
filterBuilder.addPropertyValue("securityContextHolderStrategy",
authenticationFilterSecurityContextHolderStrategyRef);
BeanDefinitionBuilder adsBldr = BeanDefinitionBuilder
.rootBeanDefinition(J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource.class);
adsBldr.addPropertyValue("userRoles2GrantedAuthoritiesMapper",
@@ -763,7 +739,7 @@ final class AuthenticationConfigBuilder {
}
}
void createLogoutFilter(BeanMetadataElement authenticationFilterSecurityContextHolderStrategyRef) {
void createLogoutFilter() {
Element logoutElt = DomUtils.getChildElementByTagName(this.httpElt, Elements.LOGOUT);
if (logoutElt != null || this.autoConfig) {
String formLoginPage = this.formLoginPage;
@@ -771,21 +747,20 @@ final class AuthenticationConfigBuilder {
formLoginPage = DefaultLoginPageGeneratingFilter.DEFAULT_LOGIN_PAGE_URL;
}
LogoutBeanDefinitionParser logoutParser = new LogoutBeanDefinitionParser(formLoginPage,
this.rememberMeServicesId, this.csrfLogoutHandler,
authenticationFilterSecurityContextHolderStrategyRef);
this.rememberMeServicesId, this.csrfLogoutHandler);
this.logoutFilter = logoutParser.parse(logoutElt, this.pc);
this.logoutHandlers = logoutParser.getLogoutHandlers();
this.logoutSuccessHandler = logoutParser.getLogoutSuccessHandler();
}
}
private void createSaml2LogoutFilter(BeanMetadataElement authenticationFilterSecurityContextHolderStrategyRef) {
private void createSaml2LogoutFilter() {
Element saml2LogoutElt = DomUtils.getChildElementByTagName(this.httpElt, Elements.SAML2_LOGOUT);
if (saml2LogoutElt == null) {
return;
}
Saml2LogoutBeanDefinitionParser parser = new Saml2LogoutBeanDefinitionParser(this.logoutHandlers,
this.logoutSuccessHandler, authenticationFilterSecurityContextHolderStrategyRef);
this.logoutSuccessHandler);
parser.parse(saml2LogoutElt, this.pc);
BeanDefinition saml2LogoutFilter = parser.getLogoutFilter();
BeanDefinition saml2LogoutRequestFilter = parser.getLogoutRequestFilter();
@@ -828,7 +803,7 @@ final class AuthenticationConfigBuilder {
return this.csrfIgnoreRequestMatchers;
}
void createAnonymousFilter(BeanMetadataElement authenticationFilterSecurityContextHolderStrategyRef) {
void createAnonymousFilter() {
Element anonymousElt = DomUtils.getChildElementByTagName(this.httpElt, Elements.ANONYMOUS);
if (anonymousElt != null && "false".equals(anonymousElt.getAttribute("enabled"))) {
return;
@@ -858,8 +833,6 @@ final class AuthenticationConfigBuilder {
this.anonymousFilter.getConstructorArgumentValues().addIndexedArgumentValue(1, username);
this.anonymousFilter.getConstructorArgumentValues().addIndexedArgumentValue(2,
AuthorityUtils.commaSeparatedStringToAuthorityList(grantedAuthority));
this.anonymousFilter.getPropertyValues().addPropertyValue("securityContextHolderStrategy",
authenticationFilterSecurityContextHolderStrategyRef);
this.anonymousFilter.setSource(source);
RootBeanDefinition anonymousProviderBean = new RootBeanDefinition(AnonymousAuthenticationProvider.class);
anonymousProviderBean.getConstructorArgumentValues().addIndexedArgumentValue(0, key);
@@ -874,7 +847,7 @@ final class AuthenticationConfigBuilder {
return Long.toString(random.nextLong());
}
void createExceptionTranslationFilter(BeanMetadataElement authenticationFilterSecurityContextHolderStrategyRef) {
void createExceptionTranslationFilter() {
BeanDefinitionBuilder etfBuilder = BeanDefinitionBuilder.rootBeanDefinition(ExceptionTranslationFilter.class);
this.accessDeniedHandler = createAccessDeniedHandler(this.httpElt, this.pc);
etfBuilder.addPropertyValue("accessDeniedHandler", this.accessDeniedHandler);
@@ -882,8 +855,6 @@ final class AuthenticationConfigBuilder {
this.mainEntryPoint = selectEntryPoint();
etfBuilder.addConstructorArgValue(this.mainEntryPoint);
etfBuilder.addConstructorArgValue(this.requestCache);
etfBuilder.addPropertyValue("securityContextHolderStrategy",
authenticationFilterSecurityContextHolderStrategyRef);
this.etf = etfBuilder.getBeanDefinition();
}
@@ -1,203 +0,0 @@
/*
* Copyright 2002-2022 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 org.springframework.security.config.http;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import org.w3c.dom.Element;
import org.springframework.beans.BeanMetadataElement;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.RuntimeBeanReference;
import org.springframework.beans.factory.parsing.BeanComponentDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.ManagedMap;
import org.springframework.beans.factory.xml.AbstractBeanDefinitionParser;
import org.springframework.beans.factory.xml.BeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.beans.factory.xml.XmlReaderContext;
import org.springframework.security.authorization.AuthenticatedAuthorizationManager;
import org.springframework.security.authorization.AuthorizationManager;
import org.springframework.security.config.Elements;
import org.springframework.security.web.access.expression.DefaultHttpSecurityExpressionHandler;
import org.springframework.security.web.access.expression.WebExpressionAuthorizationManager;
import org.springframework.security.web.access.intercept.AuthorizationFilter;
import org.springframework.security.web.access.intercept.RequestAuthorizationContext;
import org.springframework.security.web.access.intercept.RequestMatcherDelegatingAuthorizationManager;
import org.springframework.security.web.util.matcher.AnyRequestMatcher;
import org.springframework.security.web.util.matcher.RequestMatcher;
import org.springframework.util.StringUtils;
import org.springframework.util.xml.DomUtils;
class AuthorizationFilterParser implements BeanDefinitionParser {
private static final String ATT_USE_EXPRESSIONS = "use-expressions";
private static final String ATT_ACCESS_DECISION_MANAGER_REF = "access-decision-manager-ref";
private static final String ATT_HTTP_METHOD = "method";
private static final String ATT_PATTERN = "pattern";
private static final String ATT_ACCESS = "access";
private static final String ATT_SERVLET_PATH = "servlet-path";
private static final String ATT_FILTER_ALL_DISPATCHER_TYPES = "filter-all-dispatcher-types";
private String authorizationManagerRef;
private final BeanMetadataElement securityContextHolderStrategy;
AuthorizationFilterParser(BeanMetadataElement securityContextHolderStrategy) {
this.securityContextHolderStrategy = securityContextHolderStrategy;
}
@Override
public BeanDefinition parse(Element element, ParserContext parserContext) {
if (!isUseExpressions(element)) {
parserContext.getReaderContext().error("AuthorizationManager must be used with `use-expressions=\"true\"",
element);
return null;
}
if (StringUtils.hasText(element.getAttribute(ATT_ACCESS_DECISION_MANAGER_REF))) {
parserContext.getReaderContext().error(
"AuthorizationManager cannot be used in conjunction with `access-decision-manager-ref`", element);
return null;
}
this.authorizationManagerRef = createAuthorizationManager(element, parserContext);
BeanDefinitionBuilder filterBuilder = BeanDefinitionBuilder.rootBeanDefinition(AuthorizationFilter.class);
filterBuilder.getRawBeanDefinition().setSource(parserContext.extractSource(element));
filterBuilder.addConstructorArgReference(this.authorizationManagerRef);
if ("true".equals(element.getAttribute(ATT_FILTER_ALL_DISPATCHER_TYPES))) {
filterBuilder.addPropertyValue("shouldFilterAllDispatcherTypes", Boolean.TRUE);
}
BeanDefinition filter = filterBuilder
.addPropertyValue("securityContextHolderStrategy", this.securityContextHolderStrategy)
.getBeanDefinition();
String id = element.getAttribute(AbstractBeanDefinitionParser.ID_ATTRIBUTE);
if (StringUtils.hasText(id)) {
parserContext.registerComponent(new BeanComponentDefinition(filter, id));
parserContext.getRegistry().registerBeanDefinition(id, filter);
}
return filter;
}
String getAuthorizationManagerRef() {
return this.authorizationManagerRef;
}
private String createAuthorizationManager(Element element, ParserContext parserContext) {
XmlReaderContext context = parserContext.getReaderContext();
String authorizationManagerRef = element.getAttribute("authorization-manager-ref");
if (StringUtils.hasText(authorizationManagerRef)) {
return authorizationManagerRef;
}
Element expressionHandlerElt = DomUtils.getChildElementByTagName(element, Elements.EXPRESSION_HANDLER);
String expressionHandlerRef = (expressionHandlerElt != null) ? expressionHandlerElt.getAttribute("ref") : null;
if (expressionHandlerRef == null) {
expressionHandlerRef = registerDefaultExpressionHandler(parserContext);
}
MatcherType matcherType = MatcherType.fromElement(element);
ManagedMap<BeanMetadataElement, BeanDefinition> matcherToExpression = new ManagedMap<>();
List<Element> interceptMessages = DomUtils.getChildElementsByTagName(element, Elements.INTERCEPT_URL);
for (Element interceptMessage : interceptMessages) {
String accessExpression = interceptMessage.getAttribute(ATT_ACCESS);
BeanDefinitionBuilder authorizationManager = BeanDefinitionBuilder
.rootBeanDefinition(WebExpressionAuthorizationManager.class);
authorizationManager.addPropertyReference("expressionHandler", expressionHandlerRef);
authorizationManager.addConstructorArgValue(accessExpression);
BeanMetadataElement matcher = createMatcher(matcherType, interceptMessage, parserContext);
matcherToExpression.put(matcher, authorizationManager.getBeanDefinition());
}
BeanDefinitionBuilder mds = BeanDefinitionBuilder
.rootBeanDefinition(RequestMatcherDelegatingAuthorizationManagerFactory.class);
mds.setFactoryMethod("createRequestMatcherDelegatingAuthorizationManager");
mds.addConstructorArgValue(matcherToExpression);
return context.registerWithGeneratedName(mds.getBeanDefinition());
}
private BeanMetadataElement createMatcher(MatcherType matcherType, Element urlElt, ParserContext parserContext) {
String path = urlElt.getAttribute(ATT_PATTERN);
String matcherRef = urlElt.getAttribute(HttpSecurityBeanDefinitionParser.ATT_REQUEST_MATCHER_REF);
boolean hasMatcherRef = StringUtils.hasText(matcherRef);
if (!hasMatcherRef && !StringUtils.hasText(path)) {
parserContext.getReaderContext().error("path attribute cannot be empty or null", urlElt);
}
String method = urlElt.getAttribute(ATT_HTTP_METHOD);
if (!StringUtils.hasText(method)) {
method = null;
}
String servletPath = urlElt.getAttribute(ATT_SERVLET_PATH);
if (!StringUtils.hasText(servletPath)) {
servletPath = null;
}
else if (!MatcherType.mvc.equals(matcherType)) {
parserContext.getReaderContext().error(
ATT_SERVLET_PATH + " is not applicable for request-matcher: '" + matcherType.name() + "'", urlElt);
}
return hasMatcherRef ? new RuntimeBeanReference(matcherRef)
: matcherType.createMatcher(parserContext, path, method, servletPath);
}
String registerDefaultExpressionHandler(ParserContext pc) {
BeanDefinition expressionHandler = GrantedAuthorityDefaultsParserUtils.registerWithDefaultRolePrefix(pc,
DefaultWebSecurityExpressionHandlerBeanFactory.class);
String expressionHandlerRef = pc.getReaderContext().generateBeanName(expressionHandler);
pc.registerBeanComponent(new BeanComponentDefinition(expressionHandler, expressionHandlerRef));
return expressionHandlerRef;
}
boolean isUseExpressions(Element elt) {
String useExpressions = elt.getAttribute(ATT_USE_EXPRESSIONS);
return !StringUtils.hasText(useExpressions) || "true".equals(useExpressions);
}
private static class RequestMatcherDelegatingAuthorizationManagerFactory {
private static AuthorizationManager<HttpServletRequest> createRequestMatcherDelegatingAuthorizationManager(
Map<RequestMatcher, AuthorizationManager<RequestAuthorizationContext>> beans) {
RequestMatcherDelegatingAuthorizationManager.Builder builder = RequestMatcherDelegatingAuthorizationManager
.builder();
for (Map.Entry<RequestMatcher, AuthorizationManager<RequestAuthorizationContext>> entry : beans
.entrySet()) {
builder.add(entry.getKey(), entry.getValue());
}
return builder.add(AnyRequestMatcher.INSTANCE, AuthenticatedAuthorizationManager.authenticated()).build();
}
}
static class DefaultWebSecurityExpressionHandlerBeanFactory
extends GrantedAuthorityDefaultsParserUtils.AbstractGrantedAuthorityDefaultsBeanFactory {
private DefaultHttpSecurityExpressionHandler handler = new DefaultHttpSecurityExpressionHandler();
@Override
public DefaultHttpSecurityExpressionHandler getBean() {
if (this.rolePrefix != null) {
this.handler.setDefaultRolePrefix(this.rolePrefix);
}
return this.handler;
}
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 the original author or authors.
* Copyright 2002-2020 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.
@@ -71,16 +71,12 @@ public class CsrfBeanDefinitionParser implements BeanDefinitionParser {
private static final String ATT_REPOSITORY = "token-repository-ref";
private static final String ATT_REQUEST_HANDLER = "request-handler-ref";
private String csrfRepositoryRef;
private BeanDefinition csrfFilter;
private String requestMatcherRef;
private String requestHandlerRef;
@Override
public BeanDefinition parse(Element element, ParserContext pc) {
boolean disabled = element != null && "true".equals(element.getAttribute("disabled"));
@@ -99,7 +95,6 @@ public class CsrfBeanDefinitionParser implements BeanDefinitionParser {
if (element != null) {
this.csrfRepositoryRef = element.getAttribute(ATT_REPOSITORY);
this.requestMatcherRef = element.getAttribute(ATT_MATCHER);
this.requestHandlerRef = element.getAttribute(ATT_REQUEST_HANDLER);
}
if (!StringUtils.hasText(this.csrfRepositoryRef)) {
RootBeanDefinition csrfTokenRepository = new RootBeanDefinition(HttpSessionCsrfTokenRepository.class);
@@ -115,9 +110,6 @@ public class CsrfBeanDefinitionParser implements BeanDefinitionParser {
if (StringUtils.hasText(this.requestMatcherRef)) {
builder.addPropertyReference("requireCsrfProtectionMatcher", this.requestMatcherRef);
}
if (StringUtils.hasText(this.requestHandlerRef)) {
builder.addPropertyReference("requestHandler", this.requestHandlerRef);
}
this.csrfFilter = builder.getBeanDefinition();
return this.csrfFilter;
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 the original author or authors.
* Copyright 2002-2016 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.
@@ -18,13 +18,10 @@ package org.springframework.security.config.http;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.function.Supplier;
import javax.servlet.Filter;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -32,16 +29,11 @@ import org.apache.commons.logging.LogFactory;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.authentication.AnonymousAuthenticationToken;
import org.springframework.security.authentication.TestingAuthenticationToken;
import org.springframework.security.authorization.AuthorizationDecision;
import org.springframework.security.authorization.AuthorizationManager;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.DefaultSecurityFilterChain;
import org.springframework.security.web.FilterChainProxy;
import org.springframework.security.web.FilterInvocation;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.access.ExceptionTranslationFilter;
import org.springframework.security.web.access.intercept.AuthorizationFilter;
import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
import org.springframework.security.web.access.intercept.FilterSecurityInterceptor;
import org.springframework.security.web.authentication.AnonymousAuthenticationFilter;
@@ -58,8 +50,6 @@ import org.springframework.security.web.util.matcher.RequestMatcher;
public class DefaultFilterChainValidator implements FilterChainProxy.FilterChainValidator {
private static final Authentication TEST = new TestingAuthenticationToken("", "", Collections.emptyList());
private final Log logger = LogFactory.getLog(getClass());
@Override
@@ -120,7 +110,6 @@ public class DefaultFilterChainValidator implements FilterChainProxy.FilterChain
checkForDuplicates(JaasApiIntegrationFilter.class, filters);
checkForDuplicates(ExceptionTranslationFilter.class, filters);
checkForDuplicates(FilterSecurityInterceptor.class, filters);
checkForDuplicates(AuthorizationFilter.class, filters);
}
private void checkForDuplicates(Class<? extends Filter> clazz, List<Filter> filters) {
@@ -145,13 +134,11 @@ public class DefaultFilterChainValidator implements FilterChainProxy.FilterChain
* interceptor
*/
private void checkLoginPageIsntProtected(FilterChainProxy fcp, List<Filter> filterStack) {
ExceptionTranslationFilter exceptions = getFilter(ExceptionTranslationFilter.class, filterStack);
if (exceptions == null
|| !(exceptions.getAuthenticationEntryPoint() instanceof LoginUrlAuthenticationEntryPoint)) {
ExceptionTranslationFilter etf = getFilter(ExceptionTranslationFilter.class, filterStack);
if (etf == null || !(etf.getAuthenticationEntryPoint() instanceof LoginUrlAuthenticationEntryPoint)) {
return;
}
String loginPage = ((LoginUrlAuthenticationEntryPoint) exceptions.getAuthenticationEntryPoint())
.getLoginFormUrl();
String loginPage = ((LoginUrlAuthenticationEntryPoint) etf.getAuthenticationEntryPoint()).getLoginFormUrl();
this.logger.info("Checking whether login URL '" + loginPage + "' is accessible with your configuration");
FilterInvocation loginRequest = new FilterInvocation(loginPage, "POST");
List<Filter> filters = null;
@@ -172,26 +159,33 @@ public class DefaultFilterChainValidator implements FilterChainProxy.FilterChain
this.logger.debug("Default generated login page is in use");
return;
}
if (checkLoginPageIsPublic(filters, loginRequest)) {
FilterSecurityInterceptor fsi = getFilter(FilterSecurityInterceptor.class, filters);
FilterInvocationSecurityMetadataSource fids = fsi.getSecurityMetadataSource();
Collection<ConfigAttribute> attributes = fids.getAttributes(loginRequest);
if (attributes == null) {
this.logger.debug("No access attributes defined for login page URL");
if (fsi.isRejectPublicInvocations()) {
this.logger.warn("FilterSecurityInterceptor is configured to reject public invocations."
+ " Your login page may not be accessible.");
}
return;
}
AnonymousAuthenticationFilter anonymous = getFilter(AnonymousAuthenticationFilter.class, filters);
if (anonymous == null) {
AnonymousAuthenticationFilter anonPF = getFilter(AnonymousAuthenticationFilter.class, filters);
if (anonPF == null) {
this.logger.warn("The login page is being protected by the filter chain, but you don't appear to have"
+ " anonymous authentication enabled. This is almost certainly an error.");
return;
}
// Simulate an anonymous access with the supplied attributes.
AnonymousAuthenticationToken token = new AnonymousAuthenticationToken("key", anonymous.getPrincipal(),
anonymous.getAuthorities());
Supplier<Boolean> check = deriveAnonymousCheck(filters, loginRequest, token);
AnonymousAuthenticationToken token = new AnonymousAuthenticationToken("key", anonPF.getPrincipal(),
anonPF.getAuthorities());
try {
boolean allowed = check.get();
if (!allowed) {
this.logger.warn("Anonymous access to the login page doesn't appear to be enabled. "
+ "This is almost certainly an error. Please check your configuration allows unauthenticated "
+ "access to the configured login page. (Simulated access was rejected)");
}
fsi.getAccessDecisionManager().decide(token, loginRequest, attributes);
}
catch (AccessDeniedException ex) {
this.logger.warn("Anonymous access to the login page doesn't appear to be enabled. "
+ "This is almost certainly an error. Please check your configuration allows unauthenticated "
+ "access to the configured login page. (Simulated access was rejected: " + ex + ")");
}
catch (Exception ex) {
// May happen legitimately if a filter-chain request matcher requires more
@@ -202,62 +196,4 @@ public class DefaultFilterChainValidator implements FilterChainProxy.FilterChain
}
}
private boolean checkLoginPageIsPublic(List<Filter> filters, FilterInvocation loginRequest) {
FilterSecurityInterceptor authorizationInterceptor = getFilter(FilterSecurityInterceptor.class, filters);
if (authorizationInterceptor != null) {
FilterInvocationSecurityMetadataSource fids = authorizationInterceptor.getSecurityMetadataSource();
Collection<ConfigAttribute> attributes = fids.getAttributes(loginRequest);
if (attributes == null) {
this.logger.debug("No access attributes defined for login page URL");
if (authorizationInterceptor.isRejectPublicInvocations()) {
this.logger.warn("FilterSecurityInterceptor is configured to reject public invocations."
+ " Your login page may not be accessible.");
}
return true;
}
return false;
}
AuthorizationFilter authorizationFilter = getFilter(AuthorizationFilter.class, filters);
if (authorizationFilter != null) {
AuthorizationManager<HttpServletRequest> authorizationManager = authorizationFilter
.getAuthorizationManager();
try {
AuthorizationDecision decision = authorizationManager.check(() -> TEST, loginRequest.getHttpRequest());
return decision != null && decision.isGranted();
}
catch (Exception ex) {
return false;
}
}
return false;
}
private Supplier<Boolean> deriveAnonymousCheck(List<Filter> filters, FilterInvocation loginRequest,
AnonymousAuthenticationToken token) {
FilterSecurityInterceptor authorizationInterceptor = getFilter(FilterSecurityInterceptor.class, filters);
if (authorizationInterceptor != null) {
return () -> {
FilterInvocationSecurityMetadataSource source = authorizationInterceptor.getSecurityMetadataSource();
Collection<ConfigAttribute> attributes = source.getAttributes(loginRequest);
try {
authorizationInterceptor.getAccessDecisionManager().decide(token, loginRequest, attributes);
return true;
}
catch (AccessDeniedException ex) {
return false;
}
};
}
AuthorizationFilter authorizationFilter = getFilter(AuthorizationFilter.class, filters);
if (authorizationFilter != null) {
return () -> {
AuthorizationManager<HttpServletRequest> authorizationManager = authorizationFilter
.getAuthorizationManager();
AuthorizationDecision decision = authorizationManager.check(() -> token, loginRequest.getHttpRequest());
return decision != null && decision.isGranted();
};
}
return () -> true;
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 the original author or authors.
* Copyright 2002-2016 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.
@@ -46,9 +46,7 @@ import org.springframework.util.xml.DomUtils;
* for use with a FilterSecurityInterceptor.
*
* @author Luke Taylor
* @deprecated Use `use-authorization-manager` property instead
*/
@Deprecated
public class FilterInvocationSecurityMetadataSourceParser implements BeanDefinitionParser {
private static final String ATT_USE_EXPRESSIONS = "use-expressions";
@@ -101,8 +101,6 @@ public class HeadersBeanDefinitionParser implements BeanDefinitionParser {
private static final String ATT_POLICY_DIRECTIVES = "policy-directives";
private static final String ATT_HEADER_VALUE = "header-value";
private static final String CACHE_CONTROL_ELEMENT = "cache-control";
private static final String HPKP_ELEMENT = "hpkp";
@@ -597,14 +595,6 @@ public class HeadersBeanDefinitionParser implements BeanDefinitionParser {
}
builder.addPropertyValue("block", block);
}
XXssProtectionHeaderWriter.HeaderValue headerValue = XXssProtectionHeaderWriter.HeaderValue
.from(xssElt.getAttribute(ATT_HEADER_VALUE));
if (headerValue != null) {
if (disabled) {
attrNotAllowed(parserContext, ATT_HEADER_VALUE, ATT_DISABLED, xssElt);
}
builder.addPropertyValue("headerValue", headerValue);
}
if (disabled) {
return;
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 the original author or authors.
* Copyright 2002-2021 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.
@@ -24,7 +24,6 @@ import javax.servlet.ServletRequest;
import org.w3c.dom.Element;
import org.springframework.beans.BeanMetadataElement;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanReference;
import org.springframework.beans.factory.config.RuntimeBeanReference;
@@ -41,10 +40,7 @@ import org.springframework.security.access.vote.AuthenticatedVoter;
import org.springframework.security.access.vote.RoleVoter;
import org.springframework.security.config.Elements;
import org.springframework.security.config.http.GrantedAuthorityDefaultsParserUtils.AbstractGrantedAuthorityDefaultsBeanFactory;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.context.SecurityContextHolderStrategy;
import org.springframework.security.core.session.SessionRegistryImpl;
import org.springframework.security.web.access.AuthorizationManagerWebInvocationPrivilegeEvaluator;
import org.springframework.security.web.access.DefaultWebInvocationPrivilegeEvaluator;
import org.springframework.security.web.access.channel.ChannelDecisionManagerImpl;
import org.springframework.security.web.access.channel.ChannelProcessingFilter;
@@ -103,16 +99,12 @@ class HttpConfigurationBuilder {
private static final String OPT_CHANGE_SESSION_ID = "changeSessionId";
private static final String ATT_AUTHENTICATION_STRATEGY_EXPLICIT_INVOCATION = "authentication-strategy-explicit-invocation";
private static final String ATT_INVALID_SESSION_URL = "invalid-session-url";
private static final String ATT_SESSION_AUTH_STRATEGY_REF = "session-authentication-strategy-ref";
private static final String ATT_SESSION_AUTH_ERROR_URL = "session-authentication-error-url";
private static final String ATT_SECURITY_CONTEXT_HOLDER_STRATEGY = "security-context-holder-strategy-ref";
private static final String ATT_SECURITY_CONTEXT_REPOSITORY = "security-context-repository-ref";
private static final String ATT_SECURITY_CONTEXT_EXPLICIT_SAVE = "security-context-explicit-save";
@@ -121,10 +113,6 @@ class HttpConfigurationBuilder {
private static final String ATT_DISABLE_URL_REWRITING = "disable-url-rewriting";
private static final String ATT_USE_AUTHORIZATION_MGR = "use-authorization-manager";
private static final String ATT_AUTHORIZATION_MGR = "authorization-manager-ref";
private static final String ATT_ACCESS_MGR = "access-decision-manager-ref";
private static final String ATT_ONCE_PER_REQUEST = "once-per-request";
@@ -163,8 +151,6 @@ class HttpConfigurationBuilder {
private BeanDefinition forceEagerSessionCreationFilter;
private BeanMetadataElement holderStrategyRef;
private BeanReference contextRepoRef;
private BeanReference sessionRegistryRef;
@@ -224,7 +210,6 @@ class HttpConfigurationBuilder {
String createSession = element.getAttribute(ATT_CREATE_SESSION);
this.sessionPolicy = !StringUtils.hasText(createSession) ? SessionCreationPolicy.IF_REQUIRED
: createPolicy(createSession);
createSecurityContextHolderStrategy();
createForceEagerSessionCreationFilter();
createDisableEncodeUrlFilter();
createCsrfFilter();
@@ -235,7 +220,7 @@ class HttpConfigurationBuilder {
createServletApiFilter(authenticationManager);
createJaasApiFilter();
createChannelProcessingFilter();
createFilterSecurity(authenticationManager);
createFilterSecurityInterceptor(authenticationManager);
createAddHeadersFilter();
createCorsFilter();
createWellKnownChangePasswordRedirectFilter();
@@ -304,10 +289,6 @@ class HttpConfigurationBuilder {
return lowerCase ? path.toLowerCase() : path;
}
BeanMetadataElement getSecurityContextHolderStrategyForAuthenticationFilters() {
return this.holderStrategyRef;
}
BeanReference getSecurityContextRepositoryForAuthenticationFilters() {
return (isExplicitSave()) ? this.contextRepoRef : null;
}
@@ -345,22 +326,11 @@ class HttpConfigurationBuilder {
default:
scpf.addPropertyValue("forceEagerSessionCreation", Boolean.FALSE);
}
scpf.addPropertyValue("securityContextHolderStrategy", this.holderStrategyRef);
scpf.addConstructorArgValue(this.contextRepoRef);
this.securityContextPersistenceFilter = scpf.getBeanDefinition();
}
private void createSecurityContextHolderStrategy() {
String holderStrategyRef = this.httpElt.getAttribute(ATT_SECURITY_CONTEXT_HOLDER_STRATEGY);
if (StringUtils.hasText(holderStrategyRef)) {
this.holderStrategyRef = new RuntimeBeanReference(holderStrategyRef);
return;
}
this.holderStrategyRef = BeanDefinitionBuilder.rootBeanDefinition(SecurityContextHolderStrategyFactory.class)
.getBeanDefinition();
}
private void createSecurityContextRepository() {
String repoRef = this.httpElt.getAttribute(ATT_SECURITY_CONTEXT_REPOSITORY);
if (!StringUtils.hasText(repoRef)) {
@@ -384,7 +354,6 @@ class HttpConfigurationBuilder {
contextRepo.addPropertyValue("disableUrlRewriting", Boolean.TRUE);
}
}
contextRepo.addPropertyValue("securityContextHolderStrategy", this.holderStrategyRef);
BeanDefinition repoBean = contextRepo.getBeanDefinition();
repoRef = this.pc.getReaderContext().generateBeanName(repoBean);
this.pc.registerBeanComponent(new BeanComponentDefinition(repoBean, repoRef));
@@ -400,7 +369,6 @@ class HttpConfigurationBuilder {
private void createSecurityContextHolderFilter() {
BeanDefinitionBuilder filter = BeanDefinitionBuilder.rootBeanDefinition(SecurityContextHolderFilter.class);
filter.addPropertyValue("securityContextHolderStrategy", this.holderStrategyRef);
filter.addConstructorArgValue(this.contextRepoRef);
this.securityContextPersistenceFilter = filter.getBeanDefinition();
}
@@ -512,7 +480,6 @@ class HttpConfigurationBuilder {
if (StringUtils.hasText(errorUrl)) {
failureHandler.getPropertyValues().addPropertyValue("defaultFailureUrl", errorUrl);
}
sessionMgmtFilter.addPropertyValue("securityContextHolderStrategy", this.holderStrategyRef);
sessionMgmtFilter.addPropertyValue("authenticationFailureHandler", failureHandler);
sessionMgmtFilter.addConstructorArgValue(this.contextRepoRef);
if (!StringUtils.hasText(sessionAuthStratRef) && sessionFixationStrategy != null && !useChangeSessionId) {
@@ -540,11 +507,7 @@ class HttpConfigurationBuilder {
sessionMgmtFilter.addPropertyReference("invalidSessionStrategy", invalidSessionStrategyRef);
}
sessionMgmtFilter.addConstructorArgReference(sessionAuthStratRef);
boolean registerSessionMgmtFilter = (sessionMgmtElt == null
|| !"true".equals(sessionMgmtElt.getAttribute(ATT_AUTHENTICATION_STRATEGY_EXPLICIT_INVOCATION)));
if (registerSessionMgmtFilter) {
this.sfpf = (RootBeanDefinition) sessionMgmtFilter.getBeanDefinition();
}
this.sfpf = (RootBeanDefinition) sessionMgmtFilter.getBeanDefinition();
this.sessionStrategyRef = new RuntimeBeanReference(sessionAuthStratRef);
}
@@ -594,7 +557,6 @@ class HttpConfigurationBuilder {
boolean asyncSupported = ClassUtils.hasMethod(ServletRequest.class, "startAsync");
if (asyncSupported) {
this.webAsyncManagerFilter = new RootBeanDefinition(WebAsyncManagerIntegrationFilter.class);
this.webAsyncManagerFilter.getPropertyValues().add("securityContextHolderStrategy", this.holderStrategyRef);
}
}
@@ -608,7 +570,6 @@ class HttpConfigurationBuilder {
this.servApiFilter = GrantedAuthorityDefaultsParserUtils.registerWithDefaultRolePrefix(this.pc,
SecurityContextHolderAwareRequestFilterBeanFactory.class);
this.servApiFilter.getPropertyValues().add("authenticationManager", authenticationManager);
this.servApiFilter.getPropertyValues().add("securityContextHolderStrategy", this.holderStrategyRef);
}
}
@@ -619,8 +580,7 @@ class HttpConfigurationBuilder {
provideJaasApi = DEF_JAAS_API_PROVISION;
}
if ("true".equals(provideJaasApi)) {
this.jaasApiFilter = BeanDefinitionBuilder.rootBeanDefinition(JaasApiIntegrationFilter.class)
.addPropertyValue("securityContextHolderStrategy", this.holderStrategyRef).getBeanDefinition();
this.jaasApiFilter = new RootBeanDefinition(JaasApiIntegrationFilter.class);
}
}
@@ -715,35 +675,6 @@ class HttpConfigurationBuilder {
this.requestCacheAwareFilter.getConstructorArgumentValues().addGenericArgumentValue(this.requestCache);
}
private void createFilterSecurity(BeanReference authManager) {
boolean useAuthorizationManager = Boolean.parseBoolean(this.httpElt.getAttribute(ATT_USE_AUTHORIZATION_MGR));
if (useAuthorizationManager) {
createAuthorizationFilter();
return;
}
if (StringUtils.hasText(this.httpElt.getAttribute(ATT_AUTHORIZATION_MGR))) {
createAuthorizationFilter();
return;
}
createFilterSecurityInterceptor(authManager);
}
private void createAuthorizationFilter() {
AuthorizationFilterParser authorizationFilterParser = new AuthorizationFilterParser(this.holderStrategyRef);
BeanDefinition fsiBean = authorizationFilterParser.parse(this.httpElt, this.pc);
String fsiId = this.pc.getReaderContext().generateBeanName(fsiBean);
this.pc.registerBeanComponent(new BeanComponentDefinition(fsiBean, fsiId));
// Create and register a AuthorizationManagerWebInvocationPrivilegeEvaluator for
// use with
// taglibs etc.
BeanDefinition wipe = BeanDefinitionBuilder
.rootBeanDefinition(AuthorizationManagerWebInvocationPrivilegeEvaluator.class)
.addConstructorArgReference(authorizationFilterParser.getAuthorizationManagerRef()).getBeanDefinition();
this.pc.registerBeanComponent(
new BeanComponentDefinition(wipe, this.pc.getReaderContext().generateBeanName(wipe)));
this.fsi = new RuntimeBeanReference(fsiId);
}
private void createFilterSecurityInterceptor(BeanReference authManager) {
boolean useExpressions = FilterInvocationSecurityMetadataSourceParser.isUseExpressions(this.httpElt);
RootBeanDefinition securityMds = FilterInvocationSecurityMetadataSourceParser
@@ -779,7 +710,6 @@ class HttpConfigurationBuilder {
builder.addPropertyValue("observeOncePerRequest", Boolean.FALSE);
}
builder.addPropertyValue("securityMetadataSource", securityMds);
builder.addPropertyValue("securityContextHolderStrategy", this.holderStrategyRef);
BeanDefinition fsiBean = builder.getBeanDefinition();
String fsiId = this.pc.getReaderContext().generateBeanName(fsiBean);
this.pc.registerBeanComponent(new BeanComponentDefinition(fsiBean, fsiId));
@@ -911,34 +841,12 @@ class HttpConfigurationBuilder {
private SecurityContextHolderAwareRequestFilter filter = new SecurityContextHolderAwareRequestFilter();
private SecurityContextHolderStrategy securityContextHolderStrategy = SecurityContextHolder
.getContextHolderStrategy();
@Override
public SecurityContextHolderAwareRequestFilter getBean() {
this.filter.setSecurityContextHolderStrategy(this.securityContextHolderStrategy);
this.filter.setRolePrefix(this.rolePrefix);
return this.filter;
}
void setSecurityContextHolderStrategy(SecurityContextHolderStrategy securityContextHolderStrategy) {
this.securityContextHolderStrategy = securityContextHolderStrategy;
}
}
static class SecurityContextHolderStrategyFactory implements FactoryBean<SecurityContextHolderStrategy> {
@Override
public SecurityContextHolderStrategy getObject() throws Exception {
return SecurityContextHolder.getContextHolderStrategy();
}
@Override
public Class<?> getObjectType() {
return SecurityContextHolderStrategy.class;
}
}
}
@@ -147,7 +147,6 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
httpBldr.getSecurityContextRepositoryForAuthenticationFilters();
AuthenticationConfigBuilder authBldr = new AuthenticationConfigBuilder(element, forceAutoConfig, pc,
httpBldr.getSessionCreationPolicy(), httpBldr.getRequestCache(), authenticationManager,
httpBldr.getSecurityContextHolderStrategyForAuthenticationFilters(),
httpBldr.getSecurityContextRepositoryForAuthenticationFilters(), httpBldr.getSessionStrategy(),
portMapper, portResolver, httpBldr.getCsrfLogoutHandler());
httpBldr.setLogoutHandlers(authBldr.getLogoutHandlers());
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 the original author or authors.
* Copyright 2002-2019 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.
@@ -61,17 +61,13 @@ class LogoutBeanDefinitionParser implements BeanDefinitionParser {
private BeanMetadataElement logoutSuccessHandler;
private BeanMetadataElement authenticationFilterSecurityContextHolderStrategyRef;
LogoutBeanDefinitionParser(String loginPageUrl, String rememberMeServices, BeanMetadataElement csrfLogoutHandler,
BeanMetadataElement authenticationFilterSecurityContextHolderStrategyRef) {
LogoutBeanDefinitionParser(String loginPageUrl, String rememberMeServices, BeanMetadataElement csrfLogoutHandler) {
this.defaultLogoutUrl = loginPageUrl + "?logout";
this.rememberMeServices = rememberMeServices;
this.csrfEnabled = csrfLogoutHandler != null;
if (this.csrfEnabled) {
this.logoutHandlers.add(csrfLogoutHandler);
}
this.authenticationFilterSecurityContextHolderStrategyRef = authenticationFilterSecurityContextHolderStrategyRef;
}
@Override
@@ -127,8 +123,6 @@ class LogoutBeanDefinitionParser implements BeanDefinitionParser {
}
this.logoutHandlers.add(new RootBeanDefinition(LogoutSuccessEventPublishingLogoutHandler.class));
builder.addConstructorArgValue(this.logoutHandlers);
builder.addPropertyValue("securityContextHolderStrategy",
this.authenticationFilterSecurityContextHolderStrategyRef);
return builder.getBeanDefinition();
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 the original author or authors.
* Copyright 2002-2020 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.
@@ -44,8 +44,6 @@ final class OAuth2ClientBeanDefinitionParser implements BeanDefinitionParser {
private static final String ATT_AUTHORIZATION_REQUEST_RESOLVER_REF = "authorization-request-resolver-ref";
private static final String ATT_AUTHORIZATION_REDIRECT_STRATEGY_REF = "authorization-redirect-strategy-ref";
private static final String ATT_ACCESS_TOKEN_RESPONSE_CLIENT_REF = "access-token-response-client-ref";
private final BeanReference requestCache;
@@ -54,8 +52,6 @@ final class OAuth2ClientBeanDefinitionParser implements BeanDefinitionParser {
private final BeanReference authenticationFilterSecurityContextRepositoryRef;
private final BeanMetadataElement authenticationFilterSecurityContextHolderStrategy;
private BeanDefinition defaultAuthorizedClientRepository;
private BeanDefinition authorizationRequestRedirectFilter;
@@ -65,12 +61,10 @@ final class OAuth2ClientBeanDefinitionParser implements BeanDefinitionParser {
private BeanDefinition authorizationCodeAuthenticationProvider;
OAuth2ClientBeanDefinitionParser(BeanReference requestCache, BeanReference authenticationManager,
BeanReference authenticationFilterSecurityContextRepositoryRef,
BeanMetadataElement authenticationFilterSecurityContextHolderStrategy) {
BeanReference authenticationFilterSecurityContextRepositoryRef) {
this.requestCache = requestCache;
this.authenticationManager = authenticationManager;
this.authenticationFilterSecurityContextRepositoryRef = authenticationFilterSecurityContextRepositoryRef;
this.authenticationFilterSecurityContextHolderStrategy = authenticationFilterSecurityContextHolderStrategy;
}
@Override
@@ -89,7 +83,6 @@ final class OAuth2ClientBeanDefinitionParser implements BeanDefinitionParser {
}
BeanMetadataElement authorizationRequestRepository = getAuthorizationRequestRepository(
authorizationCodeGrantElt);
BeanMetadataElement authorizationRedirectStrategy = getAuthorizationRedirectStrategy(authorizationCodeGrantElt);
BeanDefinitionBuilder authorizationRequestRedirectFilterBuilder = BeanDefinitionBuilder
.rootBeanDefinition(OAuth2AuthorizationRequestRedirectFilter.class);
String authorizationRequestResolverRef = (authorizationCodeGrantElt != null)
@@ -102,7 +95,6 @@ final class OAuth2ClientBeanDefinitionParser implements BeanDefinitionParser {
}
this.authorizationRequestRedirectFilter = authorizationRequestRedirectFilterBuilder
.addPropertyValue("authorizationRequestRepository", authorizationRequestRepository)
.addPropertyValue("authorizationRedirectStrategy", authorizationRedirectStrategy)
.addPropertyValue("requestCache", this.requestCache).getBeanDefinition();
BeanDefinitionBuilder authorizationCodeGrantFilterBldr = BeanDefinitionBuilder
.rootBeanDefinition(OAuth2AuthorizationCodeGrantFilter.class)
@@ -134,16 +126,6 @@ final class OAuth2ClientBeanDefinitionParser implements BeanDefinitionParser {
.getBeanDefinition();
}
private BeanMetadataElement getAuthorizationRedirectStrategy(Element element) {
String authorizationRedirectStrategyRef = (element != null)
? element.getAttribute(ATT_AUTHORIZATION_REDIRECT_STRATEGY_REF) : null;
if (StringUtils.hasText(authorizationRedirectStrategyRef)) {
return new RuntimeBeanReference(authorizationRedirectStrategyRef);
}
return BeanDefinitionBuilder.rootBeanDefinition("org.springframework.security.web.DefaultRedirectStrategy")
.getBeanDefinition();
}
private BeanMetadataElement getAccessTokenResponseClient(Element element) {
String accessTokenResponseClientRef = (element != null)
? element.getAttribute(ATT_ACCESS_TOKEN_RESPONSE_CLIENT_REF) : null;
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 the original author or authors.
* Copyright 2002-2020 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.
@@ -87,8 +87,6 @@ final class OAuth2LoginBeanDefinitionParser implements BeanDefinitionParser {
private static final String ATT_AUTHORIZATION_REQUEST_RESOLVER_REF = "authorization-request-resolver-ref";
private static final String ATT_AUTHORIZATION_REDIRECT_STRATEGY_REF = "authorization-redirect-strategy-ref";
private static final String ATT_ACCESS_TOKEN_RESPONSE_CLIENT_REF = "access-token-response-client-ref";
private static final String ATT_USER_AUTHORITIES_MAPPER_REF = "user-authorities-mapper-ref";
@@ -117,8 +115,6 @@ final class OAuth2LoginBeanDefinitionParser implements BeanDefinitionParser {
private final boolean allowSessionCreation;
private final BeanMetadataElement authenticationFilterSecurityContextHolderStrategy;
private BeanDefinition defaultAuthorizedClientRepository;
private BeanDefinition oauth2AuthorizationRequestRedirectFilter;
@@ -132,14 +128,12 @@ final class OAuth2LoginBeanDefinitionParser implements BeanDefinitionParser {
private BeanDefinition oauth2LoginLinks;
OAuth2LoginBeanDefinitionParser(BeanReference requestCache, BeanReference portMapper, BeanReference portResolver,
BeanReference sessionStrategy, boolean allowSessionCreation,
BeanMetadataElement authenticationFilterSecurityContextHolderStrategy) {
BeanReference sessionStrategy, boolean allowSessionCreation) {
this.requestCache = requestCache;
this.portMapper = portMapper;
this.portResolver = portResolver;
this.sessionStrategy = sessionStrategy;
this.allowSessionCreation = allowSessionCreation;
this.authenticationFilterSecurityContextHolderStrategy = authenticationFilterSecurityContextHolderStrategy;
}
@Override
@@ -205,7 +199,6 @@ final class OAuth2LoginBeanDefinitionParser implements BeanDefinitionParser {
}
oauth2AuthorizationRequestRedirectFilterBuilder
.addPropertyValue("authorizationRequestRepository", authorizationRequestRepository)
.addPropertyValue("authorizationRedirectStrategy", getAuthorizationRedirectStrategy(element))
.addPropertyValue("requestCache", this.requestCache);
this.oauth2AuthorizationRequestRedirectFilter = oauth2AuthorizationRequestRedirectFilterBuilder
.getBeanDefinition();
@@ -252,8 +245,6 @@ final class OAuth2LoginBeanDefinitionParser implements BeanDefinitionParser {
oauth2LoginAuthenticationFilterBuilder.addPropertyValue("authenticationFailureHandler",
failureHandlerBuilder.getBeanDefinition());
}
oauth2LoginAuthenticationFilterBuilder.addPropertyValue("securityContextHolderStrategy",
this.authenticationFilterSecurityContextHolderStrategy);
// prepare loginlinks
this.oauth2LoginLinks = BeanDefinitionBuilder.rootBeanDefinition(Map.class)
.setFactoryMethodOnBean("getLoginLinks", oauth2LoginBeanConfigId).getBeanDefinition();
@@ -270,15 +261,6 @@ final class OAuth2LoginBeanDefinitionParser implements BeanDefinitionParser {
.getBeanDefinition();
}
private BeanMetadataElement getAuthorizationRedirectStrategy(Element element) {
String authorizationRedirectStrategyRef = element.getAttribute(ATT_AUTHORIZATION_REDIRECT_STRATEGY_REF);
if (StringUtils.hasText(authorizationRedirectStrategyRef)) {
return new RuntimeBeanReference(authorizationRedirectStrategyRef);
}
return BeanDefinitionBuilder.rootBeanDefinition("org.springframework.security.web.DefaultRedirectStrategy")
.getBeanDefinition();
}
private BeanDefinition getOidcAuthProvider(Element element, BeanMetadataElement accessTokenResponseClient,
String userAuthoritiesMapperRef) {
boolean oidcAuthenticationProviderEnabled = ClassUtils
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 the original author or authors.
* Copyright 2002-2020 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.
@@ -43,10 +43,10 @@ import org.springframework.security.oauth2.server.resource.authentication.JwtAut
import org.springframework.security.oauth2.server.resource.authentication.OpaqueTokenAuthenticationProvider;
import org.springframework.security.oauth2.server.resource.introspection.NimbusOpaqueTokenIntrospector;
import org.springframework.security.oauth2.server.resource.web.BearerTokenAuthenticationEntryPoint;
import org.springframework.security.oauth2.server.resource.web.BearerTokenAuthenticationFilter;
import org.springframework.security.oauth2.server.resource.web.BearerTokenResolver;
import org.springframework.security.oauth2.server.resource.web.DefaultBearerTokenResolver;
import org.springframework.security.oauth2.server.resource.web.access.BearerTokenAccessDeniedHandler;
import org.springframework.security.oauth2.server.resource.web.authentication.BearerTokenAuthenticationFilter;
import org.springframework.security.web.util.matcher.RequestMatcher;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
@@ -86,18 +86,14 @@ final class OAuth2ResourceServerBeanDefinitionParser implements BeanDefinitionPa
private final BeanDefinition accessDeniedHandler = new RootBeanDefinition(BearerTokenAccessDeniedHandler.class);
private final BeanMetadataElement authenticationFilterSecurityContextHolderStrategy;
OAuth2ResourceServerBeanDefinitionParser(BeanReference authenticationManager,
List<BeanReference> authenticationProviders, Map<BeanDefinition, BeanMetadataElement> entryPoints,
Map<BeanDefinition, BeanMetadataElement> deniedHandlers, List<BeanDefinition> ignoreCsrfRequestMatchers,
BeanMetadataElement authenticationFilterSecurityContextHolderStrategy) {
Map<BeanDefinition, BeanMetadataElement> deniedHandlers, List<BeanDefinition> ignoreCsrfRequestMatchers) {
this.authenticationManager = authenticationManager;
this.authenticationProviders = authenticationProviders;
this.entryPoints = entryPoints;
this.deniedHandlers = deniedHandlers;
this.ignoreCsrfRequestMatchers = ignoreCsrfRequestMatchers;
this.authenticationFilterSecurityContextHolderStrategy = authenticationFilterSecurityContextHolderStrategy;
}
/**
@@ -139,8 +135,6 @@ final class OAuth2ResourceServerBeanDefinitionParser implements BeanDefinitionPa
filterBuilder.addConstructorArgValue(authenticationManagerResolver);
filterBuilder.addPropertyValue(BEARER_TOKEN_RESOLVER, bearerTokenResolver);
filterBuilder.addPropertyValue(AUTHENTICATION_ENTRY_POINT, authenticationEntryPoint);
filterBuilder.addPropertyValue("securityContextHolderStrategy",
this.authenticationFilterSecurityContextHolderStrategy);
return filterBuilder.getBeanDefinition();
}
@@ -251,10 +245,6 @@ final class OAuth2ResourceServerBeanDefinitionParser implements BeanDefinitionPa
static final String CLIENT_SECRET = "client-secret";
static final String AUTHENTICATION_CONVERTER_REF = "authentication-converter-ref";
static final String AUTHENTICATION_CONVERTER = "authenticationConverter";
OpaqueTokenBeanDefinitionParser() {
}
@@ -262,13 +252,9 @@ final class OAuth2ResourceServerBeanDefinitionParser implements BeanDefinitionPa
public BeanDefinition parse(Element element, ParserContext pc) {
validateConfiguration(element, pc);
BeanMetadataElement introspector = getIntrospector(element);
String authenticationConverterRef = element.getAttribute(AUTHENTICATION_CONVERTER_REF);
BeanDefinitionBuilder opaqueTokenProviderBuilder = BeanDefinitionBuilder
.rootBeanDefinition(OpaqueTokenAuthenticationProvider.class);
opaqueTokenProviderBuilder.addConstructorArgValue(introspector);
if (StringUtils.hasText(authenticationConverterRef)) {
opaqueTokenProviderBuilder.addPropertyReference(AUTHENTICATION_CONVERTER, authenticationConverterRef);
}
return opaqueTokenProviderBuilder.getBeanDefinition();
}

Some files were not shown because too many files have changed in this diff Show More