parent
							
								
									fa574c8785
								
							
						
					
					
						commit
						990831db85
					
				|  | @ -0,0 +1,29 @@ | |||
| /* | ||||
|  * 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. | ||||
|  * 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; | ||||
| 
 | ||||
| /** | ||||
|  * @author Parikshit Dutta | ||||
|  * @since 5.5 | ||||
|  */ | ||||
| public interface AuthorizationEventPublisher { | ||||
| 
 | ||||
| 	void publishAuthorizationSuccess(AuthorizationDecision authorizationDecision); | ||||
| 
 | ||||
| 	void publishAuthorizationFailure(AuthorizationDecision authorizationDecision); | ||||
| 
 | ||||
| } | ||||
|  | @ -0,0 +1,61 @@ | |||
| /* | ||||
|  * 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. | ||||
|  * 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; | ||||
| 
 | ||||
| import org.springframework.context.ApplicationEventPublisher; | ||||
| import org.springframework.context.ApplicationEventPublisherAware; | ||||
| import org.springframework.security.authorization.event.AuthorizationFailureEvent; | ||||
| import org.springframework.security.authorization.event.AuthorizationSuccessEvent; | ||||
| 
 | ||||
| /** | ||||
|  * Default implementation of {@link AuthorizationEventPublisher} | ||||
|  * | ||||
|  * @author Parikshit Dutta | ||||
|  * @since 5.5 | ||||
|  */ | ||||
| public class DefaultAuthorizationEventPublisher implements AuthorizationEventPublisher, ApplicationEventPublisherAware { | ||||
| 
 | ||||
| 	private ApplicationEventPublisher applicationEventPublisher; | ||||
| 
 | ||||
| 	public DefaultAuthorizationEventPublisher() { | ||||
| 		this(null); | ||||
| 	} | ||||
| 
 | ||||
| 	public DefaultAuthorizationEventPublisher(ApplicationEventPublisher applicationEventPublisher) { | ||||
| 		this.applicationEventPublisher = applicationEventPublisher; | ||||
| 	} | ||||
| 
 | ||||
| 	@Override | ||||
| 	public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) { | ||||
| 		this.applicationEventPublisher = applicationEventPublisher; | ||||
| 	} | ||||
| 
 | ||||
| 	@Override | ||||
| 	public void publishAuthorizationSuccess(AuthorizationDecision authorizationDecision) { | ||||
| 		if (this.applicationEventPublisher != null) { | ||||
| 			this.applicationEventPublisher.publishEvent(new AuthorizationSuccessEvent(authorizationDecision)); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	@Override | ||||
| 	public void publishAuthorizationFailure(AuthorizationDecision authorizationDecision) { | ||||
| 		if (this.applicationEventPublisher != null) { | ||||
| 			this.applicationEventPublisher.publishEvent(new AuthorizationFailureEvent(authorizationDecision)); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| } | ||||
|  | @ -0,0 +1,34 @@ | |||
| /* | ||||
|  * 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. | ||||
|  * 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.event; | ||||
| 
 | ||||
| import org.springframework.context.ApplicationEvent; | ||||
| import org.springframework.security.authorization.AuthorizationDecision; | ||||
| 
 | ||||
| /** | ||||
|  * An {@link ApplicationEvent} which indicates failed authorization. | ||||
|  * | ||||
|  * @author Parikshit Dutta | ||||
|  * @since 5.5 | ||||
|  */ | ||||
| public class AuthorizationFailureEvent extends ApplicationEvent { | ||||
| 
 | ||||
| 	public AuthorizationFailureEvent(AuthorizationDecision authorizationDecision) { | ||||
| 		super(authorizationDecision); | ||||
| 	} | ||||
| 
 | ||||
| } | ||||
|  | @ -0,0 +1,34 @@ | |||
| /* | ||||
|  * 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. | ||||
|  * 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.event; | ||||
| 
 | ||||
| import org.springframework.context.ApplicationEvent; | ||||
| import org.springframework.security.authorization.AuthorizationDecision; | ||||
| 
 | ||||
| /** | ||||
|  * An {@link ApplicationEvent} which indicates successful authorization. | ||||
|  * | ||||
|  * @author Parikshit Dutta | ||||
|  * @since 5.5 | ||||
|  */ | ||||
| public class AuthorizationSuccessEvent extends ApplicationEvent { | ||||
| 
 | ||||
| 	public AuthorizationSuccessEvent(AuthorizationDecision authorizationDecision) { | ||||
| 		super(authorizationDecision); | ||||
| 	} | ||||
| 
 | ||||
| } | ||||
|  | @ -0,0 +1,70 @@ | |||
| /* | ||||
|  * 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. | ||||
|  * 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; | ||||
| 
 | ||||
| import org.junit.jupiter.api.BeforeEach; | ||||
| import org.junit.jupiter.api.Test; | ||||
| 
 | ||||
| import org.springframework.context.ApplicationEventPublisher; | ||||
| import org.springframework.security.authorization.event.AuthorizationFailureEvent; | ||||
| import org.springframework.security.authorization.event.AuthorizationSuccessEvent; | ||||
| 
 | ||||
| import static org.mockito.ArgumentMatchers.any; | ||||
| import static org.mockito.ArgumentMatchers.isA; | ||||
| import static org.mockito.Mockito.mock; | ||||
| import static org.mockito.Mockito.never; | ||||
| import static org.mockito.Mockito.verify; | ||||
| 
 | ||||
| /** | ||||
|  * Tests for {@link DefaultAuthorizationEventPublisher} | ||||
|  * | ||||
|  * @author Parikshit Dutta | ||||
|  */ | ||||
| public class DefaultAuthorizationEventPublisherTests { | ||||
| 
 | ||||
| 	ApplicationEventPublisher applicationEventPublisher; | ||||
| 
 | ||||
| 	DefaultAuthorizationEventPublisher authorizationEventPublisher; | ||||
| 
 | ||||
| 	@BeforeEach | ||||
| 	public void init() { | ||||
| 		this.applicationEventPublisher = mock(ApplicationEventPublisher.class); | ||||
| 		this.authorizationEventPublisher = new DefaultAuthorizationEventPublisher(); | ||||
| 		this.authorizationEventPublisher.setApplicationEventPublisher(this.applicationEventPublisher); | ||||
| 	} | ||||
| 
 | ||||
| 	@Test | ||||
| 	public void testAuthenticationSuccessIsPublished() { | ||||
| 		this.authorizationEventPublisher.publishAuthorizationSuccess(mock(AuthorizationDecision.class)); | ||||
| 		verify(this.applicationEventPublisher).publishEvent(isA(AuthorizationSuccessEvent.class)); | ||||
| 	} | ||||
| 
 | ||||
| 	@Test | ||||
| 	public void testAuthenticationFailureIsPublished() { | ||||
| 		this.authorizationEventPublisher.publishAuthorizationFailure(mock(AuthorizationDecision.class)); | ||||
| 		verify(this.applicationEventPublisher).publishEvent(isA(AuthorizationFailureEvent.class)); | ||||
| 	} | ||||
| 
 | ||||
| 	@Test | ||||
| 	public void testNullPublisherNotInvoked() { | ||||
| 		this.authorizationEventPublisher.setApplicationEventPublisher(null); | ||||
| 		this.authorizationEventPublisher.publishAuthorizationSuccess(mock(AuthorizationDecision.class)); | ||||
| 		this.authorizationEventPublisher.publishAuthorizationFailure(mock(AuthorizationDecision.class)); | ||||
| 		verify(this.applicationEventPublisher, never()).publishEvent(any()); | ||||
| 	} | ||||
| 
 | ||||
| } | ||||
|  | @ -27,6 +27,7 @@ import org.apache.commons.logging.LogFactory; | |||
| 
 | ||||
| import org.springframework.core.log.LogMessage; | ||||
| import org.springframework.security.authorization.AuthorizationDecision; | ||||
| import org.springframework.security.authorization.AuthorizationEventPublisher; | ||||
| import org.springframework.security.authorization.AuthorizationManager; | ||||
| import org.springframework.security.core.Authentication; | ||||
| import org.springframework.security.web.util.matcher.RequestMatcher; | ||||
|  | @ -38,6 +39,7 @@ import org.springframework.util.Assert; | |||
|  * {@link AuthorizationManager} based on a {@link RequestMatcher} evaluation. | ||||
|  * | ||||
|  * @author Evgeniy Cheban | ||||
|  * @author Parikshit Dutta | ||||
|  * @since 5.5 | ||||
|  */ | ||||
| public final class RequestMatcherDelegatingAuthorizationManager implements AuthorizationManager<HttpServletRequest> { | ||||
|  | @ -46,6 +48,8 @@ public final class RequestMatcherDelegatingAuthorizationManager implements Autho | |||
| 
 | ||||
| 	private final Map<RequestMatcher, AuthorizationManager<RequestAuthorizationContext>> mappings; | ||||
| 
 | ||||
| 	private AuthorizationEventPublisher authorizationEventPublisher; | ||||
| 
 | ||||
| 	private RequestMatcherDelegatingAuthorizationManager( | ||||
| 			Map<RequestMatcher, AuthorizationManager<RequestAuthorizationContext>> mappings) { | ||||
| 		Assert.notEmpty(mappings, "mappings cannot be empty"); | ||||
|  | @ -76,14 +80,36 @@ public final class RequestMatcherDelegatingAuthorizationManager implements Autho | |||
| 				if (this.logger.isTraceEnabled()) { | ||||
| 					this.logger.trace(LogMessage.format("Checking authorization on %s using %s", request, manager)); | ||||
| 				} | ||||
| 				return manager.check(authentication, | ||||
| 				AuthorizationDecision authorizationDecision = manager.check(authentication, | ||||
| 						new RequestAuthorizationContext(request, matchResult.getVariables())); | ||||
| 				publishAuthorizationEvent(authorizationDecision); | ||||
| 				return authorizationDecision; | ||||
| 			} | ||||
| 		} | ||||
| 		this.logger.trace("Abstaining since did not find matching RequestMatcher"); | ||||
| 		return null; | ||||
| 	} | ||||
| 
 | ||||
| 	private void publishAuthorizationEvent(AuthorizationDecision authorizationDecision) { | ||||
| 		if (this.authorizationEventPublisher != null) { | ||||
| 			if (authorizationDecision.isGranted()) { | ||||
| 				this.authorizationEventPublisher.publishAuthorizationSuccess(authorizationDecision); | ||||
| 			} | ||||
| 			else { | ||||
| 				this.authorizationEventPublisher.publishAuthorizationFailure(authorizationDecision); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	/** | ||||
| 	 * Set implementation of an {@link AuthorizationEventPublisher} | ||||
| 	 * @param authorizationEventPublisher | ||||
| 	 */ | ||||
| 	public void setAuthorizationEventPublisher(AuthorizationEventPublisher authorizationEventPublisher) { | ||||
| 		Assert.notNull(authorizationEventPublisher, "AuthorizationEventPublisher cannot be null"); | ||||
| 		this.authorizationEventPublisher = authorizationEventPublisher; | ||||
| 	} | ||||
| 
 | ||||
| 	/** | ||||
| 	 * Creates a builder for {@link RequestMatcherDelegatingAuthorizationManager}. | ||||
| 	 * @return the new {@link Builder} instance | ||||
|  |  | |||
|  | @ -1,5 +1,5 @@ | |||
| /* | ||||
|  * Copyright 2002-2020 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,17 +24,21 @@ import org.springframework.mock.web.MockHttpServletRequest; | |||
| import org.springframework.security.authentication.TestingAuthenticationToken; | ||||
| import org.springframework.security.authorization.AuthorityAuthorizationManager; | ||||
| import org.springframework.security.authorization.AuthorizationDecision; | ||||
| import org.springframework.security.authorization.AuthorizationEventPublisher; | ||||
| import org.springframework.security.core.Authentication; | ||||
| import org.springframework.security.web.servlet.util.matcher.MvcRequestMatcher; | ||||
| import org.springframework.security.web.util.matcher.AnyRequestMatcher; | ||||
| 
 | ||||
| import static org.assertj.core.api.Assertions.assertThat; | ||||
| import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; | ||||
| import static org.mockito.Mockito.mock; | ||||
| import static org.mockito.Mockito.verify; | ||||
| 
 | ||||
| /** | ||||
|  * Tests for {@link RequestMatcherDelegatingAuthorizationManager}. | ||||
|  * | ||||
|  * @author Evgeniy Cheban | ||||
|  * @author Parikshit Dutta | ||||
|  */ | ||||
| public class RequestMatcherDelegatingAuthorizationManagerTests { | ||||
| 
 | ||||
|  | @ -98,6 +102,7 @@ public class RequestMatcherDelegatingAuthorizationManagerTests { | |||
| 		Supplier<Authentication> authentication = () -> new TestingAuthenticationToken("user", "password", "ROLE_USER"); | ||||
| 
 | ||||
| 		AuthorizationDecision grant = manager.check(authentication, new MockHttpServletRequest(null, "/grant")); | ||||
| 
 | ||||
| 		assertThat(grant).isNotNull(); | ||||
| 		assertThat(grant.isGranted()).isTrue(); | ||||
| 
 | ||||
|  | @ -121,4 +126,40 @@ public class RequestMatcherDelegatingAuthorizationManagerTests { | |||
| 				.withMessage("mappingsConsumer cannot be null"); | ||||
| 	} | ||||
| 
 | ||||
| 	@Test | ||||
| 	public void testAuthorizationEventPublisherIsNotNull() { | ||||
| 		RequestMatcherDelegatingAuthorizationManager manager = RequestMatcherDelegatingAuthorizationManager.builder() | ||||
| 				.add(new MvcRequestMatcher(null, "/grant"), (a, o) -> new AuthorizationDecision(true)).build(); | ||||
| 		assertThatIllegalArgumentException().isThrownBy(() -> manager.setAuthorizationEventPublisher(null)) | ||||
| 				.withMessage("AuthorizationEventPublisher cannot be null"); | ||||
| 	} | ||||
| 
 | ||||
| 	@Test | ||||
| 	public void testAuthorizationSuccessEventWhenAuthorizationGranted() { | ||||
| 		RequestMatcherDelegatingAuthorizationManager manager = RequestMatcherDelegatingAuthorizationManager.builder() | ||||
| 				.add(new MvcRequestMatcher(null, "/grant"), (a, o) -> new AuthorizationDecision(true)).build(); | ||||
| 
 | ||||
| 		AuthorizationEventPublisher authorizationEventPublisher = mock(AuthorizationEventPublisher.class); | ||||
| 		manager.setAuthorizationEventPublisher(authorizationEventPublisher); | ||||
| 
 | ||||
| 		Supplier<Authentication> authentication = () -> new TestingAuthenticationToken("user", "password", "ROLE_USER"); | ||||
| 
 | ||||
| 		AuthorizationDecision grant = manager.check(authentication, new MockHttpServletRequest(null, "/grant")); | ||||
| 		verify(authorizationEventPublisher).publishAuthorizationSuccess(grant); | ||||
| 	} | ||||
| 
 | ||||
| 	@Test | ||||
| 	public void testAuthorizationFailureEventWhenAuthorizationNotGranted() { | ||||
| 		RequestMatcherDelegatingAuthorizationManager manager = RequestMatcherDelegatingAuthorizationManager.builder() | ||||
| 				.add(new MvcRequestMatcher(null, "/deny"), (a, o) -> new AuthorizationDecision(false)).build(); | ||||
| 
 | ||||
| 		AuthorizationEventPublisher authorizationEventPublisher = mock(AuthorizationEventPublisher.class); | ||||
| 		manager.setAuthorizationEventPublisher(authorizationEventPublisher); | ||||
| 
 | ||||
| 		Supplier<Authentication> authentication = () -> new TestingAuthenticationToken("user", "password", "ROLE_USER"); | ||||
| 
 | ||||
| 		AuthorizationDecision grant = manager.check(authentication, new MockHttpServletRequest(null, "/deny")); | ||||
| 		verify(authorizationEventPublisher).publishAuthorizationFailure(grant); | ||||
| 	} | ||||
| 
 | ||||
| } | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue