21 changed files with 571 additions and 43 deletions
@ -0,0 +1,34 @@
@@ -0,0 +1,34 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<!-- |
||||
~ 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. |
||||
~ 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. |
||||
--> |
||||
|
||||
<b:beans xmlns:b="http://www.springframework.org/schema/beans" |
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
||||
xmlns="http://www.springframework.org/schema/security" |
||||
xsi:schemaLocation=" |
||||
http://www.springframework.org/schema/security |
||||
https://www.springframework.org/schema/security/spring-security.xsd |
||||
http://www.springframework.org/schema/beans |
||||
https://www.springframework.org/schema/beans/spring-beans.xsd"> |
||||
|
||||
<http security-context-explicit-save="true"> |
||||
<form-login/> |
||||
<intercept-url pattern="/**" access="authenticated"/> |
||||
</http> |
||||
|
||||
<b:import resource="MiscHttpConfigTests-controllers.xml"/> |
||||
<b:import resource="userservice.xml"/> |
||||
</b:beans> |
||||
@ -0,0 +1,38 @@
@@ -0,0 +1,38 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<!-- |
||||
~ 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. |
||||
~ 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. |
||||
--> |
||||
|
||||
<b:beans xmlns:b="http://www.springframework.org/schema/beans" |
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
||||
xmlns="http://www.springframework.org/schema/security" |
||||
xsi:schemaLocation=" |
||||
http://www.springframework.org/schema/security |
||||
https://www.springframework.org/schema/security/spring-security.xsd |
||||
http://www.springframework.org/schema/beans |
||||
https://www.springframework.org/schema/beans/spring-beans.xsd"> |
||||
|
||||
<http create-session="always" security-context-repository-ref="repo" security-context-explicit-save="true"> |
||||
<form-login/> |
||||
<intercept-url pattern="/**" access="authenticated"/> |
||||
</http> |
||||
|
||||
<b:bean name="repo" class="org.mockito.Mockito" factory-method="mock"> |
||||
<b:constructor-arg value="org.springframework.security.web.context.SecurityContextRepository"/> |
||||
</b:bean> |
||||
|
||||
<b:import resource="MiscHttpConfigTests-controllers.xml"/> |
||||
<b:import resource="userservice.xml"/> |
||||
</b:beans> |
||||
Binary file not shown.
|
After Width: | Height: | Size: 102 KiB |
@ -0,0 +1,86 @@
@@ -0,0 +1,86 @@
|
||||
/* |
||||
* 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.web.context; |
||||
|
||||
import java.io.IOException; |
||||
|
||||
import jakarta.servlet.FilterChain; |
||||
import jakarta.servlet.ServletException; |
||||
import jakarta.servlet.http.HttpServletRequest; |
||||
import jakarta.servlet.http.HttpServletResponse; |
||||
|
||||
import org.springframework.security.core.context.SecurityContext; |
||||
import org.springframework.security.core.context.SecurityContextHolder; |
||||
import org.springframework.util.Assert; |
||||
import org.springframework.web.filter.OncePerRequestFilter; |
||||
|
||||
/** |
||||
* A {@link jakarta.servlet.Filter} that uses the {@link SecurityContextRepository} to |
||||
* obtain the {@link SecurityContext} and set it on the {@link SecurityContextHolder}. |
||||
* This is similar to {@link SecurityContextPersistenceFilter} except that the |
||||
* {@link SecurityContextRepository#saveContext(SecurityContext, HttpServletRequest, HttpServletResponse)} |
||||
* must be explicitly invoked to save the {@link SecurityContext}. This improves the |
||||
* efficiency and provides better flexibility by allowing different authentication |
||||
* mechanisms to choose individually if authentication should be persisted. |
||||
* |
||||
* @author Rob Winch |
||||
* @since 5.7 |
||||
*/ |
||||
public class SecurityContextHolderFilter extends OncePerRequestFilter { |
||||
|
||||
private final SecurityContextRepository securityContextRepository; |
||||
|
||||
private boolean shouldNotFilterErrorDispatch; |
||||
|
||||
/** |
||||
* Creates a new instance. |
||||
* @param securityContextRepository the repository to use. Cannot be null. |
||||
*/ |
||||
public SecurityContextHolderFilter(SecurityContextRepository securityContextRepository) { |
||||
Assert.notNull(securityContextRepository, "securityContextRepository cannot be null"); |
||||
this.securityContextRepository = securityContextRepository; |
||||
} |
||||
|
||||
@Override |
||||
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) |
||||
throws ServletException, IOException { |
||||
SecurityContext securityContext = this.securityContextRepository |
||||
.loadContext(new HttpRequestResponseHolder(request, response)); |
||||
try { |
||||
SecurityContextHolder.setContext(securityContext); |
||||
filterChain.doFilter(request, response); |
||||
} |
||||
finally { |
||||
SecurityContextHolder.clearContext(); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
protected boolean shouldNotFilterErrorDispatch() { |
||||
return this.shouldNotFilterErrorDispatch; |
||||
} |
||||
|
||||
/** |
||||
* Disables {@link SecurityContextHolderFilter} for error dispatch. |
||||
* @param shouldNotFilterErrorDispatch if the Filter should be disabled for error |
||||
* dispatch. Default is false. |
||||
*/ |
||||
public void setShouldNotFilterErrorDispatch(boolean shouldNotFilterErrorDispatch) { |
||||
this.shouldNotFilterErrorDispatch = shouldNotFilterErrorDispatch; |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,95 @@
@@ -0,0 +1,95 @@
|
||||
/* |
||||
* 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.web.context; |
||||
|
||||
import jakarta.servlet.FilterChain; |
||||
import jakarta.servlet.http.HttpServletRequest; |
||||
import jakarta.servlet.http.HttpServletResponse; |
||||
|
||||
import org.junit.jupiter.api.AfterEach; |
||||
import org.junit.jupiter.api.BeforeEach; |
||||
import org.junit.jupiter.api.Test; |
||||
import org.junit.jupiter.api.extension.ExtendWith; |
||||
import org.mockito.ArgumentCaptor; |
||||
import org.mockito.Captor; |
||||
import org.mockito.Mock; |
||||
import org.mockito.junit.jupiter.MockitoExtension; |
||||
|
||||
import org.springframework.security.authentication.TestAuthentication; |
||||
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.SecurityContextImpl; |
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat; |
||||
import static org.mockito.BDDMockito.given; |
||||
|
||||
@ExtendWith(MockitoExtension.class) |
||||
class SecurityContextHolderFilterTests { |
||||
|
||||
@Mock |
||||
private SecurityContextRepository repository; |
||||
|
||||
@Mock |
||||
private HttpServletRequest request; |
||||
|
||||
@Mock |
||||
private HttpServletResponse response; |
||||
|
||||
@Mock |
||||
private FilterChain chain; |
||||
|
||||
@Captor |
||||
private ArgumentCaptor<HttpRequestResponseHolder> requestResponse; |
||||
|
||||
private SecurityContextHolderFilter filter; |
||||
|
||||
@BeforeEach |
||||
void setup() { |
||||
this.filter = new SecurityContextHolderFilter(this.repository); |
||||
} |
||||
|
||||
@AfterEach |
||||
void cleanup() { |
||||
SecurityContextHolder.clearContext(); |
||||
} |
||||
|
||||
@Test |
||||
void doFilterThenSetsAndClearsSecurityContextHolder() throws Exception { |
||||
Authentication authentication = TestAuthentication.authenticatedUser(); |
||||
SecurityContext expectedContext = new SecurityContextImpl(authentication); |
||||
given(this.repository.loadContext(this.requestResponse.capture())).willReturn(expectedContext); |
||||
FilterChain filterChain = (request, response) -> assertThat(SecurityContextHolder.getContext()) |
||||
.isEqualTo(expectedContext); |
||||
|
||||
this.filter.doFilter(this.request, this.response, filterChain); |
||||
|
||||
assertThat(SecurityContextHolder.getContext()).isEqualTo(SecurityContextHolder.createEmptyContext()); |
||||
} |
||||
|
||||
@Test |
||||
void shouldNotFilterErrorDispatchWhenDefault() { |
||||
assertThat(this.filter.shouldNotFilterErrorDispatch()).isFalse(); |
||||
} |
||||
|
||||
@Test |
||||
void shouldNotFilterErrorDispatchWhenOverridden() { |
||||
this.filter.setShouldNotFilterErrorDispatch(true); |
||||
assertThat(this.filter.shouldNotFilterErrorDispatch()).isTrue(); |
||||
} |
||||
|
||||
} |
||||
Loading…
Reference in new issue