Compare commits
77 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 6d3f1699c0 | |||
| 0cf95dbf61 | |||
| 39c43159f4 | |||
| 0a022a348c | |||
| afec90c8e8 | |||
| c7ccba66c7 | |||
| a6599f9874 | |||
| 9f581850a1 | |||
| 6e13927b48 | |||
| cead207c5b | |||
| 9e22d40264 | |||
| c54a191042 | |||
| 0da2e5a33e | |||
| 08b84502e3 | |||
| dbcff3f1af | |||
| e87fae40df | |||
| 32d25e8f23 | |||
| 9656f79afe | |||
| 81723fca9a | |||
| ac32095bc8 | |||
| 30206b6d0c | |||
| 3e22c1e8de | |||
| d67c11cfbd | |||
| a387f401b7 | |||
| 9bd04ed0e0 | |||
| 68cec50bad | |||
| 04692d9ee8 | |||
| 2279f9fd39 | |||
| e834543eed | |||
| 783f674704 | |||
| 933debebeb | |||
| 7250abc185 | |||
| 06e58e4c34 | |||
| bcc1cfc28a | |||
| 663f5cf76b | |||
| a53cbb838b | |||
| 8287289bcb | |||
| 1eefd433b6 | |||
| b6f3cb71e6 | |||
| 3469bcb822 | |||
| b4083f1b9e | |||
| 1e093db1b6 | |||
| e61adcb0cd | |||
| caa4093619 | |||
| 8bec14009e | |||
| 556ae316ba | |||
| 53d007f062 | |||
| d6eeafb10c | |||
| 2d52fb8e4b | |||
| 37d8846652 | |||
| 74b8c6715b | |||
| 8c9275067e | |||
| 4b8bfee7c5 | |||
| b727f24c95 | |||
| d55c8aac4f | |||
| c4e9fb885d | |||
| 442faccb5f | |||
| e25117856e | |||
| c69df9fba0 | |||
| 39cee36065 | |||
| a106188add | |||
| 5eefe9dcff | |||
| 98321b769a | |||
| 3d7e22a4e9 | |||
| 84cca81edf | |||
| 094bf1b527 | |||
| 66665344c5 | |||
| 6c7703789a | |||
| fabf7f649c | |||
| 7b88ab289d | |||
| 26566af431 | |||
| 5257e36ffc | |||
| 0421e25cba | |||
| 1c885cf3a3 | |||
| 1c3ce1e401 | |||
| b851a8bf6d | |||
| faadadf71a |
+1
-1
@@ -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.
|
||||
|
||||
+4
-20
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+1
-16
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+2
-2
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+2
-22
@@ -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 {
|
||||
|
||||
|
||||
-18
@@ -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
-3
@@ -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 {
|
||||
|
||||
/**
|
||||
|
||||
-61
@@ -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;
|
||||
}
|
||||
}
|
||||
-98
@@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
-44
@@ -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);
|
||||
}
|
||||
-45
@@ -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);
|
||||
|
||||
}
|
||||
-44
@@ -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);
|
||||
}
|
||||
-45
@@ -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);
|
||||
|
||||
}
|
||||
-56
@@ -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();
|
||||
}
|
||||
-160
@@ -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() {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
-66
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
-160
@@ -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() {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
-66
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
-143
@@ -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
@@ -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')) {
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
+16
-2
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
+106
@@ -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
|
||||
}
|
||||
}
|
||||
+3
-2
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
+2
-2
@@ -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.*");
|
||||
}
|
||||
|
||||
+6
@@ -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
-3
@@ -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
|
||||
|
||||
-8
@@ -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
-3
@@ -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
-17
@@ -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
-3
@@ -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
-2
@@ -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
|
||||
|
||||
+2
-15
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
-78
@@ -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
-3
@@ -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
-7
@@ -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");
|
||||
}
|
||||
|
||||
|
||||
-9
@@ -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());
|
||||
|
||||
-87
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
+17
-35
@@ -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]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+2
-15
@@ -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
-102
@@ -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.
|
||||
|
||||
+1
-2
@@ -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>
|
||||
|
||||
+3
-3
@@ -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());
|
||||
|
||||
+3
-359
@@ -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;
|
||||
*
|
||||
* @Bean
|
||||
* public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
|
||||
* http.authorizeHttpRequests().requestMatchers("/**").hasRole("USER").and().formLogin();
|
||||
* http.authorizeRequests().antMatchers("/**").hasRole("USER").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>
|
||||
* @Configuration
|
||||
* @EnableWebSecurity
|
||||
* public class RequestMatchersSecurityConfig {
|
||||
*
|
||||
* @Bean
|
||||
* public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
|
||||
* http
|
||||
* .securityMatchers((matchers) -> matchers
|
||||
* .requestMatchers("/api/**", "/oauth/**")
|
||||
* )
|
||||
* .authorizeHttpRequests((authorize) -> authorize
|
||||
* anyRequest().hasRole("USER")
|
||||
* )
|
||||
* .httpBasic(withDefaults());
|
||||
* return http.build();
|
||||
* }
|
||||
*
|
||||
* @Bean
|
||||
* public UserDetailsService userDetailsService() {
|
||||
* UserDetails user = User.withDefaultPasswordEncoder()
|
||||
* .username("user")
|
||||
* .password("password")
|
||||
* .roles("USER")
|
||||
* .build();
|
||||
* return new InMemoryUserDetailsManager(user);
|
||||
* }
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* The configuration below is the same as the previous configuration.
|
||||
*
|
||||
* <pre>
|
||||
* @Configuration
|
||||
* @EnableWebSecurity
|
||||
* public class RequestMatchersSecurityConfig {
|
||||
*
|
||||
* @Bean
|
||||
* public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
|
||||
* http
|
||||
* .securityMatchers((matchers) -> matchers
|
||||
* .requestMatchers("/api/**")
|
||||
* .requestMatchers("/oauth/**")
|
||||
* )
|
||||
* .authorizeHttpRequests((authorize) -> authorize
|
||||
* anyRequest().hasRole("USER")
|
||||
* )
|
||||
* .httpBasic(withDefaults());
|
||||
* return http.build();
|
||||
* }
|
||||
*
|
||||
* @Bean
|
||||
* public UserDetailsService userDetailsService() {
|
||||
* UserDetails user = User.withDefaultPasswordEncoder()
|
||||
* .username("user")
|
||||
* .password("password")
|
||||
* .roles("USER")
|
||||
* .build();
|
||||
* return new InMemoryUserDetailsManager(user);
|
||||
* }
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* The configuration below is also the same as the above configuration.
|
||||
*
|
||||
* <pre>
|
||||
* @Configuration
|
||||
* @EnableWebSecurity
|
||||
* public class RequestMatchersSecurityConfig {
|
||||
*
|
||||
* @Bean
|
||||
* public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
|
||||
* http
|
||||
* .securityMatchers((matchers) -> matchers
|
||||
* .requestMatchers("/api/**")
|
||||
* )
|
||||
* .securityMatchers((matchers) -> matchers
|
||||
* .requestMatchers("/oauth/**")
|
||||
* )
|
||||
* .authorizeHttpRequests((authorize) -> authorize
|
||||
* anyRequest().hasRole("USER")
|
||||
* )
|
||||
* .httpBasic(withDefaults());
|
||||
* return http.build();
|
||||
* }
|
||||
*
|
||||
* @Bean
|
||||
* public UserDetailsService userDetailsService() {
|
||||
* UserDetails user = User.withDefaultPasswordEncoder()
|
||||
* .username("user")
|
||||
* .password("password")
|
||||
* .roles("USER")
|
||||
* .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>
|
||||
* @Configuration
|
||||
* @EnableWebSecurity
|
||||
* public class RequestMatchersSecurityConfig {
|
||||
*
|
||||
* @Bean
|
||||
* public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
|
||||
* http
|
||||
* .securityMatchers((matchers) -> matchers
|
||||
* .requestMatchers("/api/**", "/oauth/**")
|
||||
* )
|
||||
* .authorizeHttpRequests((authorize) -> authorize
|
||||
* .anyRequest().hasRole("USER")
|
||||
* )
|
||||
* .httpBasic(withDefaults());
|
||||
* return http.build();
|
||||
* }
|
||||
*
|
||||
* @Bean
|
||||
* public UserDetailsService userDetailsService() {
|
||||
* UserDetails user = User.withDefaultPasswordEncoder()
|
||||
* .username("user")
|
||||
* .password("password")
|
||||
* .roles("USER")
|
||||
* .build();
|
||||
* return new InMemoryUserDetailsManager(user);
|
||||
* }
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* The configuration below is the same as the previous configuration.
|
||||
*
|
||||
* <pre>
|
||||
* @Configuration
|
||||
* @EnableWebSecurity
|
||||
* public class RequestMatchersSecurityConfig {
|
||||
*
|
||||
* @Bean
|
||||
* public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
|
||||
* http
|
||||
* .securityMatchers((matchers) -> matchers
|
||||
* .requestMatchers("/api/**")
|
||||
* .requestMatchers("/oauth/**")
|
||||
* )
|
||||
* .authorizeHttpRequests((authorize) -> authorize
|
||||
* .anyRequest().hasRole("USER")
|
||||
* )
|
||||
* .httpBasic(withDefaults());
|
||||
* return http.build();
|
||||
* }
|
||||
*
|
||||
* @Bean
|
||||
* public UserDetailsService userDetailsService() {
|
||||
* UserDetails user = User.withDefaultPasswordEncoder()
|
||||
* .username("user")
|
||||
* .password("password")
|
||||
* .roles("USER")
|
||||
* .build();
|
||||
* return new InMemoryUserDetailsManager(user);
|
||||
* }
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* The configuration below is also the same as the above configuration.
|
||||
*
|
||||
* <pre>
|
||||
* @Configuration
|
||||
* @EnableWebSecurity
|
||||
* public class RequestMatchersSecurityConfig {
|
||||
*
|
||||
* @Bean
|
||||
* public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
|
||||
* http
|
||||
* .securityMatchers((matchers) -> matchers
|
||||
* .requestMatchers("/api/**")
|
||||
* )
|
||||
* .securityMatchers((matchers) -> matchers
|
||||
* .requestMatchers("/oauth/**")
|
||||
* )
|
||||
* .authorizeHttpRequests((authorize) -> authorize
|
||||
* .anyRequest().hasRole("USER")
|
||||
* )
|
||||
* .httpBasic(withDefaults());
|
||||
* return http.build();
|
||||
* }
|
||||
*
|
||||
* @Bean
|
||||
* public UserDetailsService userDetailsService() {
|
||||
* UserDetails user = User.withDefaultPasswordEncoder()
|
||||
* .username("user")
|
||||
* .password("password")
|
||||
* .roles("USER")
|
||||
* .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));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+4
-14
@@ -138,7 +138,7 @@ public final class WebSecurity extends AbstractConfiguredSecurityBuilder<Filter,
|
||||
* <pre>
|
||||
* webSecurityBuilder.ignoring()
|
||||
* // ignore all URLs that start with /resources/ or /static/
|
||||
* .requestMatchers("/resources/**", "/static/**");
|
||||
* .antMatchers("/resources/**", "/static/**");
|
||||
* </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("/resources/**").requestMatchers("/static/**");
|
||||
* .antMatchers("/resources/**").antMatchers("/static/**");
|
||||
* </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("/resources/**");
|
||||
* .antMatchers("/resources/**");
|
||||
* webSecurityBuilder.ignoring()
|
||||
* // ignore all URLs that start with /static/
|
||||
* .requestMatchers("/static/**");
|
||||
* .antMatchers("/static/**");
|
||||
* // 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);
|
||||
}
|
||||
|
||||
+2
-2
@@ -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("/resources/**");
|
||||
* .antMatchers("/resources/**");
|
||||
* }
|
||||
*
|
||||
* @Bean
|
||||
* public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
|
||||
* http.authorizeRequests().requestMatchers("/public/**").permitAll().anyRequest()
|
||||
* http.authorizeRequests().antMatchers("/public/**").permitAll().anyRequest()
|
||||
* .hasRole("USER").and()
|
||||
* // Possibly more configuration ...
|
||||
* .formLogin() // enable form based log in
|
||||
|
||||
+1
-23
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
+2
-15
@@ -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;
|
||||
|
||||
+12
-33
@@ -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
-11
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+2
-2
@@ -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;
|
||||
* }
|
||||
*
|
||||
* @Bean
|
||||
* public WebSecurityCustomizer webSecurityCustomizer(WebSecurity web) {
|
||||
* public WebSecurityCustomizer webSecurityCustomizer() {
|
||||
* return (web) -> web.ignoring().antMatchers("/resources/**");
|
||||
* }
|
||||
* </pre> See the <a href=
|
||||
|
||||
-1
@@ -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
-21
@@ -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
-4
@@ -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
-3
@@ -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);
|
||||
}
|
||||
|
||||
-44
@@ -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
-9
@@ -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);
|
||||
}
|
||||
|
||||
+2
-65
@@ -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
-2
@@ -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
-11
@@ -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);
|
||||
}
|
||||
|
||||
-54
@@ -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
-2
@@ -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);
|
||||
}
|
||||
|
||||
+3
-6
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
+12
-4
@@ -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;
|
||||
|
||||
-1
@@ -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
-3
@@ -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
-2
@@ -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);
|
||||
|
||||
+17
-42
@@ -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
-11
@@ -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);
|
||||
}
|
||||
|
||||
+2
-3
@@ -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
-19
@@ -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);
|
||||
|
||||
+3
-39
@@ -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}
|
||||
|
||||
+5
-33
@@ -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 <ch4mp@c4-soft.com>
|
||||
* @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) {
|
||||
|
||||
+19
-74
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+24
-73
@@ -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
-4
@@ -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
-4
@@ -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 {
|
||||
|
||||
|
||||
-58
@@ -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>
|
||||
* @Configuration
|
||||
* @EnableWebSocketSecurity
|
||||
* public class WebSocketSecurityConfig {
|
||||
*
|
||||
* @Bean
|
||||
* AuthorizationManager<Message<?>> authorizationManager(MessageMatcherDelegatingAuthorizationManager.Builder messages) {
|
||||
* messages.simpDestMatchers("/user/queue/errors").permitAll()
|
||||
* .simpDestMatchers("/admin/**").hasRole("ADMIN")
|
||||
* .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 {
|
||||
|
||||
}
|
||||
-38
@@ -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());
|
||||
}
|
||||
|
||||
}
|
||||
-168
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
+31
-60
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
-203
@@ -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
-9
@@ -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;
|
||||
}
|
||||
|
||||
+23
-87
@@ -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
-3
@@ -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";
|
||||
|
||||
-10
@@ -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;
|
||||
}
|
||||
|
||||
+4
-96
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
-1
@@ -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());
|
||||
|
||||
+2
-8
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
+2
-20
@@ -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;
|
||||
|
||||
+2
-20
@@ -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
|
||||
|
||||
+3
-17
@@ -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
Reference in New Issue
Block a user