|
|
|
@ -1,5 +1,5 @@ |
|
|
|
/* |
|
|
|
/* |
|
|
|
* Copyright 2002-2021 the original author or authors. |
|
|
|
* Copyright 2002-2022 the original author or authors. |
|
|
|
* |
|
|
|
* |
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
|
|
|
* you may not use this file except in compliance with the License. |
|
|
|
* you may not use this file except in compliance with the License. |
|
|
|
@ -16,15 +16,20 @@ |
|
|
|
|
|
|
|
|
|
|
|
package org.springframework.security.web.access.intercept; |
|
|
|
package org.springframework.security.web.access.intercept; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import java.io.IOException; |
|
|
|
import java.util.function.Supplier; |
|
|
|
import java.util.function.Supplier; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import javax.servlet.DispatcherType; |
|
|
|
import javax.servlet.FilterChain; |
|
|
|
import javax.servlet.FilterChain; |
|
|
|
|
|
|
|
import javax.servlet.ServletException; |
|
|
|
import javax.servlet.http.HttpServletRequest; |
|
|
|
import javax.servlet.http.HttpServletRequest; |
|
|
|
|
|
|
|
|
|
|
|
import org.junit.After; |
|
|
|
import org.junit.After; |
|
|
|
|
|
|
|
import org.junit.Before; |
|
|
|
import org.junit.Test; |
|
|
|
import org.junit.Test; |
|
|
|
import org.mockito.ArgumentCaptor; |
|
|
|
import org.mockito.ArgumentCaptor; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import org.springframework.mock.web.MockFilterChain; |
|
|
|
import org.springframework.mock.web.MockHttpServletRequest; |
|
|
|
import org.springframework.mock.web.MockHttpServletRequest; |
|
|
|
import org.springframework.mock.web.MockHttpServletResponse; |
|
|
|
import org.springframework.mock.web.MockHttpServletResponse; |
|
|
|
import org.springframework.security.access.AccessDeniedException; |
|
|
|
import org.springframework.security.access.AccessDeniedException; |
|
|
|
@ -36,6 +41,7 @@ import org.springframework.security.core.Authentication; |
|
|
|
import org.springframework.security.core.context.SecurityContext; |
|
|
|
import org.springframework.security.core.context.SecurityContext; |
|
|
|
import org.springframework.security.core.context.SecurityContextHolder; |
|
|
|
import org.springframework.security.core.context.SecurityContextHolder; |
|
|
|
import org.springframework.security.core.context.SecurityContextImpl; |
|
|
|
import org.springframework.security.core.context.SecurityContextImpl; |
|
|
|
|
|
|
|
import org.springframework.test.util.ReflectionTestUtils; |
|
|
|
|
|
|
|
|
|
|
|
import static org.assertj.core.api.Assertions.assertThat; |
|
|
|
import static org.assertj.core.api.Assertions.assertThat; |
|
|
|
import static org.assertj.core.api.Assertions.assertThatExceptionOfType; |
|
|
|
import static org.assertj.core.api.Assertions.assertThatExceptionOfType; |
|
|
|
@ -43,6 +49,7 @@ import static org.mockito.ArgumentMatchers.any; |
|
|
|
import static org.mockito.ArgumentMatchers.eq; |
|
|
|
import static org.mockito.ArgumentMatchers.eq; |
|
|
|
import static org.mockito.BDDMockito.willThrow; |
|
|
|
import static org.mockito.BDDMockito.willThrow; |
|
|
|
import static org.mockito.Mockito.mock; |
|
|
|
import static org.mockito.Mockito.mock; |
|
|
|
|
|
|
|
import static org.mockito.Mockito.spy; |
|
|
|
import static org.mockito.Mockito.verify; |
|
|
|
import static org.mockito.Mockito.verify; |
|
|
|
import static org.mockito.Mockito.verifyNoInteractions; |
|
|
|
import static org.mockito.Mockito.verifyNoInteractions; |
|
|
|
|
|
|
|
|
|
|
|
@ -53,6 +60,24 @@ import static org.mockito.Mockito.verifyNoInteractions; |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
public class AuthorizationFilterTests { |
|
|
|
public class AuthorizationFilterTests { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private static final String ALREADY_FILTERED_ATTRIBUTE_NAME = "org.springframework.security.web.access.intercept.AuthorizationFilter.APPLIED"; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private AuthorizationFilter filter; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private AuthorizationManager<HttpServletRequest> authorizationManager; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private MockHttpServletRequest request = new MockHttpServletRequest(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private final MockHttpServletResponse response = new MockHttpServletResponse(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private final FilterChain chain = new MockFilterChain(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Before |
|
|
|
|
|
|
|
public void setup() { |
|
|
|
|
|
|
|
this.authorizationManager = mock(AuthorizationManager.class); |
|
|
|
|
|
|
|
this.filter = new AuthorizationFilter(this.authorizationManager); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@After |
|
|
|
@After |
|
|
|
public void tearDown() { |
|
|
|
public void tearDown() { |
|
|
|
SecurityContextHolder.clearContext(); |
|
|
|
SecurityContextHolder.clearContext(); |
|
|
|
@ -132,4 +157,102 @@ public class AuthorizationFilterTests { |
|
|
|
assertThat(authorizationFilter.getAuthorizationManager()).isSameAs(authorizationManager); |
|
|
|
assertThat(authorizationFilter.getAuthorizationManager()).isSameAs(authorizationManager); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
|
|
|
|
public void doFilterWhenObserveOncePerRequestTrueAndIsAppliedThenNotInvoked() throws ServletException, IOException { |
|
|
|
|
|
|
|
setIsAppliedTrue(); |
|
|
|
|
|
|
|
this.filter.setObserveOncePerRequest(true); |
|
|
|
|
|
|
|
this.filter.doFilter(this.request, this.response, this.chain); |
|
|
|
|
|
|
|
verifyNoInteractions(this.authorizationManager); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
|
|
|
|
public void doFilterWhenObserveOncePerRequestTrueAndNotAppliedThenInvoked() throws ServletException, IOException { |
|
|
|
|
|
|
|
this.filter.setObserveOncePerRequest(true); |
|
|
|
|
|
|
|
this.filter.doFilter(this.request, this.response, this.chain); |
|
|
|
|
|
|
|
verify(this.authorizationManager).verify(any(), any()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
|
|
|
|
public void doFilterWhenObserveOncePerRequestFalseAndIsAppliedThenInvoked() throws ServletException, IOException { |
|
|
|
|
|
|
|
setIsAppliedTrue(); |
|
|
|
|
|
|
|
this.filter.setObserveOncePerRequest(false); |
|
|
|
|
|
|
|
this.filter.doFilter(this.request, this.response, this.chain); |
|
|
|
|
|
|
|
verify(this.authorizationManager).verify(any(), any()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
|
|
|
|
public void doFilterWhenObserveOncePerRequestFalseAndNotAppliedThenInvoked() throws ServletException, IOException { |
|
|
|
|
|
|
|
this.filter.setObserveOncePerRequest(false); |
|
|
|
|
|
|
|
this.filter.doFilter(this.request, this.response, this.chain); |
|
|
|
|
|
|
|
verify(this.authorizationManager).verify(any(), any()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
|
|
|
|
public void doFilterWhenFilterErrorDispatchFalseAndIsErrorThenNotInvoked() throws ServletException, IOException { |
|
|
|
|
|
|
|
this.request.setDispatcherType(DispatcherType.ERROR); |
|
|
|
|
|
|
|
this.filter.setFilterErrorDispatch(false); |
|
|
|
|
|
|
|
this.filter.doFilter(this.request, this.response, this.chain); |
|
|
|
|
|
|
|
verifyNoInteractions(this.authorizationManager); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
|
|
|
|
public void doFilterWhenFilterErrorDispatchTrueAndIsErrorThenInvoked() throws ServletException, IOException { |
|
|
|
|
|
|
|
this.request.setDispatcherType(DispatcherType.ERROR); |
|
|
|
|
|
|
|
this.filter.setFilterErrorDispatch(true); |
|
|
|
|
|
|
|
this.filter.doFilter(this.request, this.response, this.chain); |
|
|
|
|
|
|
|
verify(this.authorizationManager).verify(any(), any()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
|
|
|
|
public void doFilterWhenFilterThenSetAlreadyFilteredAttribute() throws ServletException, IOException { |
|
|
|
|
|
|
|
this.request = mock(MockHttpServletRequest.class); |
|
|
|
|
|
|
|
this.filter.doFilter(this.request, this.response, this.chain); |
|
|
|
|
|
|
|
verify(this.request).setAttribute(ALREADY_FILTERED_ATTRIBUTE_NAME, Boolean.TRUE); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
|
|
|
|
public void doFilterWhenFilterThenRemoveAlreadyFilteredAttribute() throws ServletException, IOException { |
|
|
|
|
|
|
|
this.request = spy(MockHttpServletRequest.class); |
|
|
|
|
|
|
|
this.filter.doFilter(this.request, this.response, this.chain); |
|
|
|
|
|
|
|
verify(this.request).setAttribute(ALREADY_FILTERED_ATTRIBUTE_NAME, Boolean.TRUE); |
|
|
|
|
|
|
|
assertThat(this.request.getAttribute(ALREADY_FILTERED_ATTRIBUTE_NAME)).isNull(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
|
|
|
|
public void doFilterWhenFilterAsyncDispatchTrueAndIsAsyncThenInvoked() throws ServletException, IOException { |
|
|
|
|
|
|
|
this.request.setDispatcherType(DispatcherType.ASYNC); |
|
|
|
|
|
|
|
this.filter.setFilterAsyncDispatch(true); |
|
|
|
|
|
|
|
this.filter.doFilter(this.request, this.response, this.chain); |
|
|
|
|
|
|
|
verify(this.authorizationManager).verify(any(), any()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
|
|
|
|
public void doFilterWhenFilterAsyncDispatchFalseAndIsAsyncThenNotInvoked() throws ServletException, IOException { |
|
|
|
|
|
|
|
this.request.setDispatcherType(DispatcherType.ASYNC); |
|
|
|
|
|
|
|
this.filter.setFilterAsyncDispatch(false); |
|
|
|
|
|
|
|
this.filter.doFilter(this.request, this.response, this.chain); |
|
|
|
|
|
|
|
verifyNoInteractions(this.authorizationManager); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
|
|
|
|
public void filterWhenFilterErrorDispatchDefaultThenFalse() { |
|
|
|
|
|
|
|
Boolean filterErrorDispatch = (Boolean) ReflectionTestUtils.getField(this.filter, "filterErrorDispatch"); |
|
|
|
|
|
|
|
assertThat(filterErrorDispatch).isFalse(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
|
|
|
|
public void filterWhenFilterAsyncDispatchDefaultThenFalse() { |
|
|
|
|
|
|
|
Boolean filterAsyncDispatch = (Boolean) ReflectionTestUtils.getField(this.filter, "filterAsyncDispatch"); |
|
|
|
|
|
|
|
assertThat(filterAsyncDispatch).isFalse(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
|
|
|
|
public void filterWhenObserveOncePerRequestDefaultThenTrue() { |
|
|
|
|
|
|
|
assertThat(this.filter.isObserveOncePerRequest()).isTrue(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private void setIsAppliedTrue() { |
|
|
|
|
|
|
|
this.request.setAttribute(ALREADY_FILTERED_ATTRIBUTE_NAME, Boolean.TRUE); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|