NamespaceGlobalMethodSecurity groovy->java
Note that the `WhenUsingAspectJ` tests are still simply verifying structure instead of behavior. This is because the project appearsto be misconfigured in some way such that AspectJ advice isn't getting woven in at runtime. The original Groovy tests also only verified structure and they may be that way for a similar reason. Either way, I will open up a ticket so we can review why that is the case and if there is a good fix. Issue: gh-4939
This commit is contained in:
parent
c91ca0584c
commit
3121f9c000
|
@ -1,92 +0,0 @@
|
|||
/*
|
||||
* 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://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 static org.assertj.core.api.Assertions.assertThat
|
||||
import static org.junit.Assert.fail
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.springframework.context.ConfigurableApplicationContext
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext
|
||||
import org.springframework.context.annotation.Configuration
|
||||
import org.springframework.security.access.AccessDeniedException
|
||||
import org.springframework.security.access.PermissionEvaluator;
|
||||
import org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler
|
||||
import org.springframework.security.access.expression.method.MethodSecurityExpressionHandler
|
||||
import org.springframework.security.authentication.TestingAuthenticationToken
|
||||
import org.springframework.security.config.annotation.BaseSpringSpec
|
||||
import org.springframework.security.config.annotation.method.configuration.NamespaceGlobalMethodSecurityTests.BaseMethodConfig;
|
||||
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
|
||||
import org.springframework.security.config.annotation.method.configuration.GlobalMethodSecurityConfiguration;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.context.SecurityContextHolder
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Rob Winch
|
||||
*/
|
||||
public class NamespaceGlobalMethodSecurityExpressionHandlerTests extends BaseSpringSpec {
|
||||
def setup() {
|
||||
SecurityContextHolder.getContext().setAuthentication(
|
||||
new TestingAuthenticationToken("user", "password","ROLE_USER"))
|
||||
}
|
||||
|
||||
def "global-method-security/expression-handler @PreAuthorize"() {
|
||||
setup:
|
||||
context = new AnnotationConfigApplicationContext(BaseMethodConfig,CustomAccessDecisionManagerConfig)
|
||||
MethodSecurityService service = context.getBean(MethodSecurityService)
|
||||
when:
|
||||
service.hasPermission("granted")
|
||||
then:
|
||||
noExceptionThrown()
|
||||
when:
|
||||
service.hasPermission("denied")
|
||||
then:
|
||||
thrown(AccessDeniedException)
|
||||
}
|
||||
|
||||
def "global-method-security/expression-handler @PostAuthorize"() {
|
||||
setup:
|
||||
context = new AnnotationConfigApplicationContext(BaseMethodConfig,CustomAccessDecisionManagerConfig)
|
||||
MethodSecurityService service = context.getBean(MethodSecurityService)
|
||||
when:
|
||||
service.postHasPermission("granted")
|
||||
then:
|
||||
noExceptionThrown()
|
||||
when:
|
||||
service.postHasPermission("denied")
|
||||
then:
|
||||
thrown(AccessDeniedException)
|
||||
}
|
||||
|
||||
@EnableGlobalMethodSecurity(prePostEnabled = true)
|
||||
public static class CustomAccessDecisionManagerConfig extends GlobalMethodSecurityConfiguration {
|
||||
@Override
|
||||
protected MethodSecurityExpressionHandler createExpressionHandler() {
|
||||
DefaultMethodSecurityExpressionHandler expressionHandler = new DefaultMethodSecurityExpressionHandler()
|
||||
expressionHandler.permissionEvaluator = new PermissionEvaluator() {
|
||||
boolean hasPermission(Authentication authentication, Object targetDomainObject, Object permission) {
|
||||
"granted" == targetDomainObject
|
||||
}
|
||||
boolean hasPermission(Authentication authentication, Serializable targetId, String targetType, Object permission) {
|
||||
throw new UnsupportedOperationException()
|
||||
}
|
||||
}
|
||||
return expressionHandler
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,444 +0,0 @@
|
|||
/*
|
||||
* 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://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.security.access.annotation.Jsr250MethodSecurityMetadataSource
|
||||
import org.springframework.security.access.intercept.aspectj.AspectJMethodSecurityInterceptor
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat
|
||||
import static org.junit.Assert.fail
|
||||
|
||||
import java.lang.reflect.Method
|
||||
|
||||
import org.springframework.security.access.intercept.aspectj.aspect.AnnotationSecurityAspect
|
||||
import org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator
|
||||
import org.springframework.beans.factory.BeanCreationException
|
||||
import org.springframework.context.ConfigurableApplicationContext
|
||||
import org.springframework.context.annotation.AdviceMode
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext
|
||||
import org.springframework.context.annotation.Bean
|
||||
import org.springframework.context.annotation.Configuration
|
||||
import org.springframework.context.annotation.Import
|
||||
import org.springframework.core.Ordered
|
||||
import org.springframework.security.access.AccessDecisionManager
|
||||
import org.springframework.security.access.AccessDeniedException
|
||||
import org.springframework.security.access.ConfigAttribute
|
||||
import org.springframework.security.access.SecurityConfig
|
||||
import org.springframework.security.access.intercept.AfterInvocationManager
|
||||
import org.springframework.security.access.intercept.RunAsManager
|
||||
import org.springframework.security.access.intercept.RunAsManagerImpl
|
||||
import org.springframework.security.access.intercept.aopalliance.MethodSecurityInterceptor
|
||||
import org.springframework.security.access.intercept.aopalliance.MethodSecurityMetadataSourceAdvisor
|
||||
import org.springframework.security.access.method.AbstractMethodSecurityMetadataSource
|
||||
import org.springframework.security.access.method.MethodSecurityMetadataSource
|
||||
import org.springframework.security.authentication.AuthenticationManager
|
||||
import org.springframework.security.authentication.TestingAuthenticationToken
|
||||
import org.springframework.security.config.annotation.BaseSpringSpec
|
||||
import org.springframework.security.config.annotation.authentication.BaseAuthenticationConfig;
|
||||
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
|
||||
import org.springframework.security.config.annotation.method.configuration.GlobalMethodSecurityConfiguration
|
||||
import org.springframework.security.core.Authentication
|
||||
import org.springframework.security.core.context.SecurityContextHolder
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Rob Winch
|
||||
*/
|
||||
public class NamespaceGlobalMethodSecurityTests extends BaseSpringSpec {
|
||||
def setup() {
|
||||
SecurityContextHolder.getContext().setAuthentication(
|
||||
new TestingAuthenticationToken("user", "password","ROLE_USER"))
|
||||
}
|
||||
|
||||
// --- access-decision-manager-ref ---
|
||||
|
||||
def "custom AccessDecisionManager can be used"() {
|
||||
setup: "Create an instance with an AccessDecisionManager that always denies access"
|
||||
context = new AnnotationConfigApplicationContext(BaseMethodConfig,CustomAccessDecisionManagerConfig)
|
||||
MethodSecurityService service = context.getBean(MethodSecurityService)
|
||||
when:
|
||||
service.preAuthorize()
|
||||
then:
|
||||
thrown(AccessDeniedException)
|
||||
when:
|
||||
service.secured()
|
||||
then:
|
||||
thrown(AccessDeniedException)
|
||||
}
|
||||
|
||||
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
|
||||
public static class CustomAccessDecisionManagerConfig extends GlobalMethodSecurityConfiguration {
|
||||
@Override
|
||||
protected AccessDecisionManager accessDecisionManager() {
|
||||
return new DenyAllAccessDecisionManager()
|
||||
}
|
||||
|
||||
public static class DenyAllAccessDecisionManager implements AccessDecisionManager {
|
||||
public void decide(Authentication authentication, Object object, Collection<ConfigAttribute> configAttributes) {
|
||||
throw new AccessDeniedException("Always Denied")
|
||||
}
|
||||
public boolean supports(ConfigAttribute attribute) {
|
||||
return true
|
||||
}
|
||||
public boolean supports(Class<?> clazz) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// --- authentication-manager-ref ---
|
||||
|
||||
def "custom AuthenticationManager can be used"() {
|
||||
when:
|
||||
context = new AnnotationConfigApplicationContext(CustomAuthenticationConfig)
|
||||
MethodSecurityInterceptor interceptor = context.getBean(MethodSecurityInterceptor)
|
||||
interceptor.authenticationManager.authenticate(SecurityContextHolder.context.authentication)
|
||||
then:
|
||||
thrown(UnsupportedOperationException)
|
||||
}
|
||||
|
||||
@EnableGlobalMethodSecurity
|
||||
public static class CustomAuthenticationConfig extends GlobalMethodSecurityConfiguration {
|
||||
@Override
|
||||
protected AuthenticationManager authenticationManager() {
|
||||
return new AuthenticationManager() {
|
||||
Authentication authenticate(Authentication authentication) {
|
||||
throw new UnsupportedOperationException()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// --- jsr250-annotations ---
|
||||
|
||||
def "enable jsr250"() {
|
||||
when:
|
||||
context = new AnnotationConfigApplicationContext(Jsr250Config)
|
||||
MethodSecurityService service = context.getBean(MethodSecurityService)
|
||||
then: "@Secured and @PreAuthorize are ignored"
|
||||
service.secured() == null
|
||||
service.preAuthorize() == null
|
||||
|
||||
when: "@DenyAll method invoked"
|
||||
service.jsr250()
|
||||
then: "access is denied"
|
||||
thrown(AccessDeniedException)
|
||||
when: "@PermitAll method invoked"
|
||||
String jsr250PermitAll = service.jsr250PermitAll()
|
||||
then: "access is allowed"
|
||||
jsr250PermitAll == null
|
||||
}
|
||||
|
||||
@EnableGlobalMethodSecurity(jsr250Enabled = true)
|
||||
@Configuration
|
||||
public static class Jsr250Config extends BaseMethodConfig {
|
||||
}
|
||||
|
||||
// --- metadata-source-ref ---
|
||||
|
||||
def "custom MethodSecurityMetadataSource can be used with higher priority than other sources"() {
|
||||
setup:
|
||||
context = new AnnotationConfigApplicationContext(BaseMethodConfig,CustomMethodSecurityMetadataSourceConfig)
|
||||
MethodSecurityService service = context.getBean(MethodSecurityService)
|
||||
when:
|
||||
service.preAuthorize()
|
||||
then:
|
||||
thrown(AccessDeniedException)
|
||||
when:
|
||||
service.secured()
|
||||
then:
|
||||
thrown(AccessDeniedException)
|
||||
when:
|
||||
service.jsr250()
|
||||
then:
|
||||
thrown(AccessDeniedException)
|
||||
}
|
||||
|
||||
@EnableGlobalMethodSecurity
|
||||
public static class CustomMethodSecurityMetadataSourceConfig extends GlobalMethodSecurityConfiguration {
|
||||
@Override
|
||||
protected MethodSecurityMetadataSource customMethodSecurityMetadataSource() {
|
||||
return new AbstractMethodSecurityMetadataSource() {
|
||||
public Collection<ConfigAttribute> getAttributes(Method method, Class<?> targetClass) {
|
||||
// require ROLE_NOBODY for any method on MethodSecurityService class
|
||||
return MethodSecurityService.isAssignableFrom(targetClass) ? [new SecurityConfig("ROLE_NOBODY")] : []
|
||||
}
|
||||
public Collection<ConfigAttribute> getAllConfigAttributes() {
|
||||
return null
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// --- mode ---
|
||||
|
||||
def "aspectj mode works"() {
|
||||
when:
|
||||
context = new AnnotationConfigApplicationContext(AspectJModeConfig)
|
||||
then:
|
||||
context.getBean(AnnotationSecurityAspect)
|
||||
context.getBean(AspectJMethodSecurityInterceptor)
|
||||
}
|
||||
|
||||
@EnableGlobalMethodSecurity(mode = AdviceMode.ASPECTJ, proxyTargetClass = true)
|
||||
public static class AspectJModeConfig extends BaseMethodConfig {
|
||||
}
|
||||
|
||||
def "aspectj mode works extending GlobalMethodSecurityConfiguration"() {
|
||||
when:
|
||||
context = new AnnotationConfigApplicationContext(BaseMethodConfig,AspectJModeExtendsGMSCConfig)
|
||||
then:
|
||||
context.getBean(AnnotationSecurityAspect)
|
||||
context.getBean(AspectJMethodSecurityInterceptor)
|
||||
}
|
||||
|
||||
@EnableGlobalMethodSecurity(mode = AdviceMode.ASPECTJ)
|
||||
public static class AspectJModeExtendsGMSCConfig extends GlobalMethodSecurityConfiguration {
|
||||
}
|
||||
|
||||
// --- order ---
|
||||
|
||||
def order() {
|
||||
when:
|
||||
context = new AnnotationConfigApplicationContext(CustomOrderConfig)
|
||||
MethodSecurityMetadataSourceAdvisor advisor = context.getBean(MethodSecurityMetadataSourceAdvisor)
|
||||
then:
|
||||
advisor.order == 135
|
||||
}
|
||||
|
||||
@EnableGlobalMethodSecurity(order = 135)
|
||||
public static class CustomOrderConfig extends BaseMethodConfig {
|
||||
}
|
||||
|
||||
def "order is defaulted to Ordered.LOWEST_PRECEDENCE when using @EnableGlobalMethodSecurity"() {
|
||||
when:
|
||||
context = new AnnotationConfigApplicationContext(DefaultOrderConfig)
|
||||
MethodSecurityMetadataSourceAdvisor advisor = context.getBean(MethodSecurityMetadataSourceAdvisor)
|
||||
then:
|
||||
advisor.order == Ordered.LOWEST_PRECEDENCE
|
||||
}
|
||||
|
||||
@EnableGlobalMethodSecurity
|
||||
public static class DefaultOrderConfig extends BaseMethodConfig {
|
||||
}
|
||||
|
||||
def "order is defaulted to Ordered.LOWEST_PRECEDENCE when extending GlobalMethodSecurityConfiguration"() {
|
||||
when:
|
||||
context = new AnnotationConfigApplicationContext(BaseMethodConfig,DefaultOrderExtendsMethodSecurityConfig)
|
||||
MethodSecurityMetadataSourceAdvisor advisor = context.getBean(MethodSecurityMetadataSourceAdvisor)
|
||||
then:
|
||||
advisor.order == Ordered.LOWEST_PRECEDENCE
|
||||
}
|
||||
|
||||
@EnableGlobalMethodSecurity
|
||||
public static class DefaultOrderExtendsMethodSecurityConfig extends GlobalMethodSecurityConfiguration {
|
||||
}
|
||||
|
||||
// --- pre-post-annotations ---
|
||||
|
||||
def preAuthorize() {
|
||||
when:
|
||||
context = new AnnotationConfigApplicationContext(PreAuthorizeConfig)
|
||||
MethodSecurityService service = context.getBean(MethodSecurityService)
|
||||
then:
|
||||
service.secured() == null
|
||||
service.jsr250() == null
|
||||
|
||||
when:
|
||||
service.preAuthorize()
|
||||
then:
|
||||
thrown(AccessDeniedException)
|
||||
}
|
||||
|
||||
@EnableGlobalMethodSecurity(prePostEnabled = true)
|
||||
@Configuration
|
||||
public static class PreAuthorizeConfig extends BaseMethodConfig {
|
||||
}
|
||||
|
||||
def "prePostEnabled extends GlobalMethodSecurityConfiguration"() {
|
||||
when:
|
||||
context = new AnnotationConfigApplicationContext(BaseMethodConfig,PreAuthorizeExtendsGMSCConfig)
|
||||
MethodSecurityService service = context.getBean(MethodSecurityService)
|
||||
then:
|
||||
service.secured() == null
|
||||
service.jsr250() == null
|
||||
|
||||
when:
|
||||
service.preAuthorize()
|
||||
then:
|
||||
thrown(AccessDeniedException)
|
||||
}
|
||||
|
||||
@EnableGlobalMethodSecurity(prePostEnabled = true)
|
||||
@Configuration
|
||||
public static class PreAuthorizeExtendsGMSCConfig extends GlobalMethodSecurityConfiguration {
|
||||
}
|
||||
|
||||
// --- proxy-target-class ---
|
||||
|
||||
def "proxying classes works"() {
|
||||
when:
|
||||
context = new AnnotationConfigApplicationContext(ProxyTargetClass)
|
||||
MethodSecurityServiceImpl service = context.getBean(MethodSecurityServiceImpl)
|
||||
then:
|
||||
noExceptionThrown()
|
||||
}
|
||||
|
||||
@EnableGlobalMethodSecurity(proxyTargetClass = true)
|
||||
@Configuration
|
||||
public static class ProxyTargetClass extends BaseMethodConfig {
|
||||
}
|
||||
|
||||
def "proxying interfaces works"() {
|
||||
when:
|
||||
context = new AnnotationConfigApplicationContext(PreAuthorizeConfig)
|
||||
MethodSecurityService service = context.getBean(MethodSecurityService)
|
||||
then: "we get an instance of the interface"
|
||||
noExceptionThrown()
|
||||
when: "try to cast to the class"
|
||||
MethodSecurityServiceImpl serviceImpl = service
|
||||
then: "we get a class cast exception"
|
||||
thrown(ClassCastException)
|
||||
}
|
||||
|
||||
// --- run-as-manager-ref ---
|
||||
|
||||
def "custom RunAsManager"() {
|
||||
when:
|
||||
context = new AnnotationConfigApplicationContext(BaseMethodConfig,CustomRunAsManagerConfig)
|
||||
MethodSecurityService service = context.getBean(MethodSecurityService)
|
||||
then:
|
||||
service.runAs().authorities.find { it.authority == "ROLE_RUN_AS_SUPER"}
|
||||
}
|
||||
|
||||
@EnableGlobalMethodSecurity(securedEnabled = true)
|
||||
public static class CustomRunAsManagerConfig extends GlobalMethodSecurityConfiguration {
|
||||
@Override
|
||||
protected RunAsManager runAsManager() {
|
||||
RunAsManagerImpl runAsManager = new RunAsManagerImpl()
|
||||
runAsManager.setKey("some key")
|
||||
return runAsManager
|
||||
}
|
||||
}
|
||||
|
||||
// --- secured-annotation ---
|
||||
|
||||
def "secured enabled"() {
|
||||
setup:
|
||||
context = new AnnotationConfigApplicationContext(SecuredConfig)
|
||||
MethodSecurityService service = context.getBean(MethodSecurityService)
|
||||
when:
|
||||
service.secured()
|
||||
then:
|
||||
thrown(AccessDeniedException)
|
||||
and: "service with ROLE_USER allowed"
|
||||
service.securedUser() == null
|
||||
and:
|
||||
service.preAuthorize() == null
|
||||
service.jsr250() == null
|
||||
}
|
||||
|
||||
@EnableGlobalMethodSecurity(securedEnabled = true)
|
||||
@Configuration
|
||||
public static class SecuredConfig extends BaseMethodConfig {
|
||||
}
|
||||
|
||||
// --- after-invocation-provider
|
||||
|
||||
def "custom AfterInvocationManager"() {
|
||||
setup:
|
||||
context = new AnnotationConfigApplicationContext(BaseMethodConfig,CustomAfterInvocationManagerConfig)
|
||||
MethodSecurityService service = context.getBean(MethodSecurityService)
|
||||
when:
|
||||
service.preAuthorizePermitAll()
|
||||
then:
|
||||
AccessDeniedException e = thrown()
|
||||
e.message == "custom AfterInvocationManager"
|
||||
}
|
||||
|
||||
@EnableGlobalMethodSecurity(prePostEnabled = true)
|
||||
public static class CustomAfterInvocationManagerConfig extends GlobalMethodSecurityConfiguration {
|
||||
@Override
|
||||
protected AfterInvocationManager afterInvocationManager() {
|
||||
return new AfterInvocationManagerStub()
|
||||
}
|
||||
|
||||
public static class AfterInvocationManagerStub implements AfterInvocationManager {
|
||||
Object decide(Authentication authentication, Object object, Collection<ConfigAttribute> attributes,
|
||||
Object returnedObject) throws AccessDeniedException {
|
||||
throw new AccessDeniedException("custom AfterInvocationManager")
|
||||
}
|
||||
|
||||
boolean supports(ConfigAttribute attribute) {
|
||||
return true
|
||||
}
|
||||
boolean supports(Class<?> clazz) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// --- misc ---
|
||||
|
||||
def "good error message when no Enable annotation"() {
|
||||
when:
|
||||
context = new AnnotationConfigApplicationContext(ExtendsNoEnableAnntotationConfig)
|
||||
MethodSecurityInterceptor interceptor = context.getBean(MethodSecurityInterceptor)
|
||||
interceptor.authenticationManager.authenticate(SecurityContextHolder.context.authentication)
|
||||
then:
|
||||
BeanCreationException e = thrown()
|
||||
e.message.contains(EnableGlobalMethodSecurity.class.getName() + " is required")
|
||||
}
|
||||
|
||||
@Configuration
|
||||
public static class ExtendsNoEnableAnntotationConfig extends GlobalMethodSecurityConfiguration {
|
||||
@Override
|
||||
protected AuthenticationManager authenticationManager() {
|
||||
return new AuthenticationManager() {
|
||||
Authentication authenticate(Authentication authentication) {
|
||||
throw new UnsupportedOperationException()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def "import subclass of GlobalMethodSecurityConfiguration"() {
|
||||
when:
|
||||
context = new AnnotationConfigApplicationContext(ImportSubclassGMSCConfig)
|
||||
MethodSecurityService service = context.getBean(MethodSecurityService)
|
||||
then:
|
||||
service.secured() == null
|
||||
service.jsr250() == null
|
||||
|
||||
when:
|
||||
service.preAuthorize()
|
||||
then:
|
||||
thrown(AccessDeniedException)
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@Import(PreAuthorizeExtendsGMSCConfig)
|
||||
public static class ImportSubclassGMSCConfig extends BaseMethodConfig {
|
||||
}
|
||||
|
||||
@Configuration
|
||||
public static class BaseMethodConfig extends BaseAuthenticationConfig {
|
||||
@Bean
|
||||
public MethodSecurityService methodSecurityService() {
|
||||
return new MethodSecurityServiceImpl()
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* 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
|
||||
*
|
||||
* http://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.context.annotation.Bean;
|
||||
|
||||
/**
|
||||
* @author Josh Cummings
|
||||
*/
|
||||
public class MethodSecurityServiceConfig {
|
||||
@Bean
|
||||
MethodSecurityService service() {
|
||||
return new MethodSecurityServiceImpl();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,95 @@
|
|||
/*
|
||||
* 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
|
||||
*
|
||||
* http://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.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.access.AccessDeniedException;
|
||||
import org.springframework.security.access.PermissionEvaluator;
|
||||
import org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler;
|
||||
import org.springframework.security.access.expression.method.MethodSecurityExpressionHandler;
|
||||
import org.springframework.security.config.test.SpringTestRule;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.test.context.annotation.SecurityTestExecutionListeners;
|
||||
import org.springframework.security.test.context.support.WithMockUser;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThatCode;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Rob Winch
|
||||
* @author Josh Cummings
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@SecurityTestExecutionListeners
|
||||
public class NamespaceGlobalMethodSecurityExpressionHandlerTests {
|
||||
|
||||
@Rule
|
||||
public final SpringTestRule spring = new SpringTestRule();
|
||||
|
||||
@Autowired(required = false)
|
||||
private MethodSecurityService service;
|
||||
|
||||
@Test
|
||||
@WithMockUser
|
||||
public void methodSecurityWhenUsingCustomPermissionEvaluatorThenPreAuthorizesAccordingly() {
|
||||
this.spring.register(CustomAccessDecisionManagerConfig.class, MethodSecurityServiceConfig.class).autowire();
|
||||
|
||||
assertThatCode(() -> this.service.hasPermission("granted"))
|
||||
.doesNotThrowAnyException();
|
||||
|
||||
assertThatThrownBy(() -> this.service.hasPermission("denied"))
|
||||
.isInstanceOf(AccessDeniedException.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithMockUser
|
||||
public void methodSecurityWhenUsingCustomPermissionEvaluatorThenPostAuthorizesAccordingly() {
|
||||
this.spring.register(CustomAccessDecisionManagerConfig.class, MethodSecurityServiceConfig.class).autowire();
|
||||
|
||||
assertThatCode(() -> this.service.postHasPermission("granted"))
|
||||
.doesNotThrowAnyException();
|
||||
|
||||
assertThatThrownBy(() -> this.service.postHasPermission("denied"))
|
||||
.isInstanceOf(AccessDeniedException.class);
|
||||
}
|
||||
|
||||
@EnableGlobalMethodSecurity(prePostEnabled = true)
|
||||
public static class CustomAccessDecisionManagerConfig extends GlobalMethodSecurityConfiguration {
|
||||
@Override
|
||||
protected MethodSecurityExpressionHandler createExpressionHandler() {
|
||||
DefaultMethodSecurityExpressionHandler expressionHandler = new DefaultMethodSecurityExpressionHandler();
|
||||
|
||||
expressionHandler.setPermissionEvaluator(new PermissionEvaluator() {
|
||||
public boolean hasPermission(Authentication authentication, Object targetDomainObject, Object permission) {
|
||||
return "granted".equals(targetDomainObject);
|
||||
}
|
||||
|
||||
public boolean hasPermission(Authentication authentication, Serializable targetId, String targetType, Object permission) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
});
|
||||
|
||||
return expressionHandler;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,514 @@
|
|||
/*
|
||||
* 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
|
||||
*
|
||||
* http://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.aopalliance.intercept.MethodInterceptor;
|
||||
import org.aopalliance.intercept.MethodInvocation;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
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.*;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.type.AnnotationMetadata;
|
||||
import org.springframework.security.access.AccessDecisionManager;
|
||||
import org.springframework.security.access.AccessDeniedException;
|
||||
import org.springframework.security.access.ConfigAttribute;
|
||||
import org.springframework.security.access.SecurityConfig;
|
||||
import org.springframework.security.access.intercept.AfterInvocationManager;
|
||||
import org.springframework.security.access.intercept.RunAsManager;
|
||||
import org.springframework.security.access.intercept.RunAsManagerImpl;
|
||||
import org.springframework.security.access.intercept.aopalliance.MethodSecurityInterceptor;
|
||||
import org.springframework.security.access.intercept.aopalliance.MethodSecurityMetadataSourceAdvisor;
|
||||
import org.springframework.security.access.intercept.aspectj.AspectJMethodSecurityInterceptor;
|
||||
import org.springframework.security.access.method.AbstractMethodSecurityMetadataSource;
|
||||
import org.springframework.security.access.method.MethodSecurityMetadataSource;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.config.test.SpringTestRule;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.test.context.annotation.SecurityTestExecutionListeners;
|
||||
import org.springframework.security.test.context.support.WithMockUser;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Rob Winch
|
||||
* @author Josh Cummings
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@SecurityTestExecutionListeners
|
||||
public class NamespaceGlobalMethodSecurityTests {
|
||||
|
||||
@Rule
|
||||
public final SpringTestRule spring = new SpringTestRule();
|
||||
|
||||
@Autowired(required = false)
|
||||
private MethodSecurityService service;
|
||||
|
||||
// --- access-decision-manager-ref ---
|
||||
|
||||
@Test
|
||||
@WithMockUser
|
||||
public void methodSecurityWhenCustomAccessDecisionManagerThenAuthorizes() {
|
||||
this.spring.register(CustomAccessDecisionManagerConfig.class, MethodSecurityServiceConfig.class).autowire();
|
||||
|
||||
assertThatThrownBy(() -> this.service.preAuthorize())
|
||||
.isInstanceOf(AccessDeniedException.class);
|
||||
|
||||
assertThatThrownBy(() -> this.service.secured())
|
||||
.isInstanceOf(AccessDeniedException.class);
|
||||
|
||||
}
|
||||
|
||||
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
|
||||
public static class CustomAccessDecisionManagerConfig extends GlobalMethodSecurityConfiguration {
|
||||
|
||||
@Override
|
||||
protected AccessDecisionManager accessDecisionManager() {
|
||||
return new DenyAllAccessDecisionManager();
|
||||
}
|
||||
|
||||
public static class DenyAllAccessDecisionManager implements AccessDecisionManager {
|
||||
public void decide(Authentication authentication, Object object, Collection<ConfigAttribute> configAttributes) {
|
||||
throw new AccessDeniedException("Always Denied");
|
||||
}
|
||||
public boolean supports(ConfigAttribute attribute) {
|
||||
return true;
|
||||
}
|
||||
public boolean supports(Class<?> clazz) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// --- after-invocation-provider
|
||||
|
||||
@Test
|
||||
@WithMockUser
|
||||
public void methodSecurityWhenCustomAfterInvocationManagerThenAuthorizes() {
|
||||
this.spring.register(CustomAfterInvocationManagerConfig.class, MethodSecurityServiceConfig.class).autowire();
|
||||
|
||||
assertThatThrownBy(() -> this.service.preAuthorizePermitAll())
|
||||
.isInstanceOf(AccessDeniedException.class);
|
||||
}
|
||||
|
||||
@EnableGlobalMethodSecurity(prePostEnabled = true)
|
||||
public static class CustomAfterInvocationManagerConfig
|
||||
extends GlobalMethodSecurityConfiguration {
|
||||
|
||||
@Override
|
||||
protected AfterInvocationManager afterInvocationManager() {
|
||||
return new AfterInvocationManagerStub();
|
||||
}
|
||||
|
||||
public static class AfterInvocationManagerStub implements AfterInvocationManager {
|
||||
public Object decide(Authentication authentication,
|
||||
Object object,
|
||||
Collection<ConfigAttribute> attributes,
|
||||
Object returnedObject) throws AccessDeniedException {
|
||||
|
||||
throw new AccessDeniedException("custom AfterInvocationManager");
|
||||
}
|
||||
|
||||
public boolean supports(ConfigAttribute attribute) {
|
||||
return true;
|
||||
}
|
||||
public boolean supports(Class<?> clazz) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// --- authentication-manager-ref ---
|
||||
|
||||
@Test
|
||||
@WithMockUser
|
||||
public void methodSecurityWhenCustomAuthenticationManagerThenAuthorizes() {
|
||||
this.spring.register(CustomAuthenticationConfig.class, MethodSecurityServiceConfig.class).autowire();
|
||||
|
||||
assertThatThrownBy(() -> this.service.preAuthorize())
|
||||
.isInstanceOf(UnsupportedOperationException.class);
|
||||
}
|
||||
|
||||
@EnableGlobalMethodSecurity(prePostEnabled = true)
|
||||
public static class CustomAuthenticationConfig extends GlobalMethodSecurityConfiguration {
|
||||
|
||||
@Override
|
||||
public MethodInterceptor methodSecurityInterceptor() throws Exception {
|
||||
MethodInterceptor interceptor = super.methodSecurityInterceptor();
|
||||
((MethodSecurityInterceptor) interceptor).setAlwaysReauthenticate(true);
|
||||
return interceptor;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AuthenticationManager authenticationManager() {
|
||||
return (authentication) -> {
|
||||
throw new UnsupportedOperationException();
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// --- jsr250-annotations ---
|
||||
|
||||
@Test
|
||||
@WithMockUser
|
||||
public void methodSecurityWhenJsr250EnabledThenAuthorizes() {
|
||||
this.spring.register(Jsr250Config.class, MethodSecurityServiceConfig.class).autowire();
|
||||
|
||||
assertThatCode(() -> this.service.preAuthorize())
|
||||
.doesNotThrowAnyException();
|
||||
|
||||
assertThatCode(() -> this.service.secured())
|
||||
.doesNotThrowAnyException();
|
||||
|
||||
assertThatThrownBy(() -> this.service.jsr250())
|
||||
.isInstanceOf(AccessDeniedException.class);
|
||||
|
||||
assertThatCode(() -> this.service.jsr250PermitAll())
|
||||
.doesNotThrowAnyException();
|
||||
|
||||
}
|
||||
|
||||
@EnableGlobalMethodSecurity(jsr250Enabled = true)
|
||||
@Configuration
|
||||
public static class Jsr250Config {
|
||||
|
||||
}
|
||||
|
||||
// --- metadata-source-ref ---
|
||||
|
||||
@Test
|
||||
@WithMockUser
|
||||
public void methodSecurityWhenCustomMethodSecurityMetadataSourceThenAuthorizes() {
|
||||
this.spring.register(CustomMethodSecurityMetadataSourceConfig.class, MethodSecurityServiceConfig.class).autowire();
|
||||
|
||||
assertThatThrownBy(() -> this.service.preAuthorize())
|
||||
.isInstanceOf(AccessDeniedException.class);
|
||||
|
||||
assertThatThrownBy(() -> this.service.secured())
|
||||
.isInstanceOf(AccessDeniedException.class);
|
||||
|
||||
assertThatThrownBy(() -> this.service.jsr250())
|
||||
.isInstanceOf(AccessDeniedException.class);
|
||||
}
|
||||
|
||||
@EnableGlobalMethodSecurity
|
||||
public static class CustomMethodSecurityMetadataSourceConfig extends GlobalMethodSecurityConfiguration {
|
||||
|
||||
@Override
|
||||
protected MethodSecurityMetadataSource customMethodSecurityMetadataSource() {
|
||||
return new AbstractMethodSecurityMetadataSource() {
|
||||
public Collection<ConfigAttribute> getAttributes(Method method, Class<?> targetClass) {
|
||||
// require ROLE_NOBODY for any method on MethodSecurityService interface
|
||||
return MethodSecurityService.class.isAssignableFrom(targetClass) ?
|
||||
Arrays.asList(new SecurityConfig("ROLE_NOBODY")) :
|
||||
Collections.emptyList();
|
||||
}
|
||||
public Collection<ConfigAttribute> getAllConfigAttributes() {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// --- mode ---
|
||||
|
||||
@Test
|
||||
@WithMockUser
|
||||
public void contextRefreshWhenUsingAspectJThenAutowire() throws Exception {
|
||||
this.spring.register(AspectJModeConfig.class, MethodSecurityServiceConfig.class).autowire();
|
||||
|
||||
assertThat(this.spring.getContext().getBean(Class.forName("org.springframework.security.access.intercept.aspectj.aspect.AnnotationSecurityAspect"))).isNotNull();
|
||||
assertThat(this.spring.getContext().getBean(AspectJMethodSecurityInterceptor.class)).isNotNull();
|
||||
|
||||
//TODO diagnose why aspectj isn't weaving method security advice around MethodSecurityServiceImpl
|
||||
}
|
||||
|
||||
@EnableGlobalMethodSecurity(mode = AdviceMode.ASPECTJ, securedEnabled = true)
|
||||
public static class AspectJModeConfig {
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void contextRefreshWhenUsingAspectJAndCustomGlobalMethodSecurityConfigurationThenAutowire()
|
||||
throws Exception {
|
||||
|
||||
this.spring.register(AspectJModeExtendsGMSCConfig.class).autowire();
|
||||
|
||||
assertThat(this.spring.getContext().getBean(Class.forName("org.springframework.security.access.intercept.aspectj.aspect.AnnotationSecurityAspect"))).isNotNull();
|
||||
assertThat(this.spring.getContext().getBean(AspectJMethodSecurityInterceptor.class)).isNotNull();
|
||||
|
||||
}
|
||||
|
||||
@EnableGlobalMethodSecurity(mode = AdviceMode.ASPECTJ)
|
||||
public static class AspectJModeExtendsGMSCConfig extends GlobalMethodSecurityConfiguration {
|
||||
}
|
||||
|
||||
// --- order ---
|
||||
|
||||
private static class AdvisorOrderConfig
|
||||
implements ImportBeanDefinitionRegistrar {
|
||||
|
||||
private static class ExceptingInterceptor implements MethodInterceptor {
|
||||
@Override
|
||||
public Object invoke(MethodInvocation invocation) {
|
||||
throw new UnsupportedOperationException("Deny All");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
|
||||
BeanDefinitionBuilder advice = BeanDefinitionBuilder
|
||||
.rootBeanDefinition(ExceptingInterceptor.class);
|
||||
registry.registerBeanDefinition("exceptingInterceptor",
|
||||
advice.getBeanDefinition());
|
||||
|
||||
BeanDefinitionBuilder advisor = BeanDefinitionBuilder
|
||||
.rootBeanDefinition(MethodSecurityMetadataSourceAdvisor.class);
|
||||
advisor.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
|
||||
advisor.addConstructorArgValue("exceptingInterceptor");
|
||||
advisor.addConstructorArgReference("methodSecurityMetadataSource");
|
||||
advisor.addConstructorArgValue("methodSecurityMetadataSource");
|
||||
advisor.addPropertyValue("order", 0);
|
||||
registry.registerBeanDefinition("exceptingAdvisor",
|
||||
advisor.getBeanDefinition());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithMockUser
|
||||
public void methodSecurityWhenOrderSpecifiedThenConfigured() {
|
||||
this.spring.register(CustomOrderConfig.class, MethodSecurityServiceConfig.class).autowire();
|
||||
|
||||
assertThat(this.spring.getContext()
|
||||
.getBean("metaDataSourceAdvisor", MethodSecurityMetadataSourceAdvisor.class)
|
||||
.getOrder())
|
||||
.isEqualTo(-135);
|
||||
|
||||
assertThatThrownBy(() -> this.service.jsr250())
|
||||
.isInstanceOf(AccessDeniedException.class);
|
||||
}
|
||||
|
||||
@EnableGlobalMethodSecurity(order = -135, jsr250Enabled = true)
|
||||
@Import(AdvisorOrderConfig.class)
|
||||
public static class CustomOrderConfig {
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithMockUser
|
||||
public void methodSecurityWhenOrderUnspecifiedThenConfiguredToLowestPrecedence() {
|
||||
this.spring.register(DefaultOrderConfig.class, MethodSecurityServiceConfig.class).autowire();
|
||||
|
||||
assertThat(this.spring.getContext()
|
||||
.getBean("metaDataSourceAdvisor", MethodSecurityMetadataSourceAdvisor.class)
|
||||
.getOrder())
|
||||
.isEqualTo(Ordered.LOWEST_PRECEDENCE);
|
||||
|
||||
assertThatThrownBy(() -> this.service.jsr250())
|
||||
.isInstanceOf(UnsupportedOperationException.class);
|
||||
}
|
||||
|
||||
@EnableGlobalMethodSecurity(jsr250Enabled = true)
|
||||
@Import(AdvisorOrderConfig.class)
|
||||
public static class DefaultOrderConfig {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithMockUser
|
||||
public void methodSecurityWhenOrderUnspecifiedAndCustomGlobalMethodSecurityConfigurationThenConfiguredToLowestPrecedence() {
|
||||
this.spring.register(DefaultOrderExtendsMethodSecurityConfig.class, MethodSecurityServiceConfig.class).autowire();
|
||||
|
||||
assertThat(this.spring.getContext()
|
||||
.getBean("metaDataSourceAdvisor", MethodSecurityMetadataSourceAdvisor.class)
|
||||
.getOrder())
|
||||
.isEqualTo(Ordered.LOWEST_PRECEDENCE);
|
||||
|
||||
assertThatThrownBy(() -> this.service.jsr250())
|
||||
.isInstanceOf(UnsupportedOperationException.class);
|
||||
}
|
||||
|
||||
@EnableGlobalMethodSecurity(jsr250Enabled = true)
|
||||
@Import(AdvisorOrderConfig.class)
|
||||
public static class DefaultOrderExtendsMethodSecurityConfig extends GlobalMethodSecurityConfiguration {
|
||||
}
|
||||
|
||||
// --- pre-post-annotations ---
|
||||
|
||||
@Test
|
||||
@WithMockUser
|
||||
public void methodSecurityWhenPrePostEnabledThenPreAuthorizes() {
|
||||
this.spring.register(PreAuthorizeConfig.class, MethodSecurityServiceConfig.class).autowire();
|
||||
|
||||
assertThatCode(() -> this.service.secured())
|
||||
.doesNotThrowAnyException();
|
||||
|
||||
assertThatCode(() -> this.service.jsr250())
|
||||
.doesNotThrowAnyException();
|
||||
|
||||
assertThatThrownBy(() -> this.service.preAuthorize())
|
||||
.isInstanceOf(AccessDeniedException.class);
|
||||
}
|
||||
|
||||
@EnableGlobalMethodSecurity(prePostEnabled = true)
|
||||
public static class PreAuthorizeConfig {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithMockUser
|
||||
public void methodSecurityWhenPrePostEnabledAndCustomGlobalMethodSecurityConfigurationThenPreAuthorizes() {
|
||||
this.spring.register(PreAuthorizeExtendsGMSCConfig.class, MethodSecurityServiceConfig.class).autowire();
|
||||
|
||||
assertThatCode(() -> this.service.secured())
|
||||
.doesNotThrowAnyException();
|
||||
|
||||
assertThatCode(() -> this.service.jsr250())
|
||||
.doesNotThrowAnyException();
|
||||
|
||||
assertThatThrownBy(() -> this.service.preAuthorize())
|
||||
.isInstanceOf(AccessDeniedException.class);
|
||||
}
|
||||
|
||||
@EnableGlobalMethodSecurity(prePostEnabled = true)
|
||||
public static class PreAuthorizeExtendsGMSCConfig extends GlobalMethodSecurityConfiguration {
|
||||
}
|
||||
|
||||
// --- proxy-target-class ---
|
||||
|
||||
@Test
|
||||
@WithMockUser
|
||||
public void methodSecurityWhenProxyTargetClassThenDoesNotWireToInterface() {
|
||||
this.spring.register(ProxyTargetClassConfig.class, MethodSecurityServiceConfig.class).autowire();
|
||||
|
||||
// make sure service was actually proxied
|
||||
assertThat(this.service.getClass().getInterfaces())
|
||||
.doesNotContain(MethodSecurityService.class);
|
||||
|
||||
assertThatThrownBy(() -> this.service.preAuthorize())
|
||||
.isInstanceOf(AccessDeniedException.class);
|
||||
}
|
||||
|
||||
@EnableGlobalMethodSecurity(proxyTargetClass = true, prePostEnabled = true)
|
||||
public static class ProxyTargetClassConfig {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithMockUser
|
||||
public void methodSecurityWhenDefaultProxyThenWiresToInterface() {
|
||||
this.spring.register(DefaultProxyConfig.class, MethodSecurityServiceConfig.class).autowire();
|
||||
|
||||
assertThat(this.service.getClass().getInterfaces())
|
||||
.contains(MethodSecurityService.class);
|
||||
|
||||
assertThatThrownBy(() -> this.service.preAuthorize())
|
||||
.isInstanceOf(AccessDeniedException.class);
|
||||
}
|
||||
|
||||
@EnableGlobalMethodSecurity(prePostEnabled = true)
|
||||
public static class DefaultProxyConfig {
|
||||
}
|
||||
|
||||
// --- run-as-manager-ref ---
|
||||
|
||||
@Test
|
||||
@WithMockUser
|
||||
public void methodSecurityWhenCustomRunAsManagerThenRunAsWrapsAuthentication() {
|
||||
this.spring.register(CustomRunAsManagerConfig.class, MethodSecurityServiceConfig.class).autowire();
|
||||
|
||||
assertThat(service.runAs().getAuthorities())
|
||||
.anyMatch(authority -> "ROLE_RUN_AS_SUPER".equals(authority.getAuthority()));
|
||||
}
|
||||
|
||||
@EnableGlobalMethodSecurity(securedEnabled = true)
|
||||
public static class CustomRunAsManagerConfig extends GlobalMethodSecurityConfiguration {
|
||||
|
||||
@Override
|
||||
protected RunAsManager runAsManager() {
|
||||
RunAsManagerImpl runAsManager = new RunAsManagerImpl();
|
||||
runAsManager.setKey("some key");
|
||||
return runAsManager;
|
||||
}
|
||||
}
|
||||
|
||||
// --- secured-annotation ---
|
||||
|
||||
@Test
|
||||
@WithMockUser
|
||||
public void methodSecurityWhenSecuredEnabledThenSecures() {
|
||||
this.spring.register(SecuredConfig.class, MethodSecurityServiceConfig.class).autowire();
|
||||
|
||||
assertThatThrownBy(() -> this.service.secured())
|
||||
.isInstanceOf(AccessDeniedException.class);
|
||||
|
||||
assertThatCode(() -> this.service.securedUser())
|
||||
.doesNotThrowAnyException();
|
||||
|
||||
assertThatCode(() -> this.service.preAuthorize())
|
||||
.doesNotThrowAnyException();
|
||||
|
||||
assertThatCode(() -> this.service.jsr250())
|
||||
.doesNotThrowAnyException();
|
||||
}
|
||||
|
||||
@EnableGlobalMethodSecurity(securedEnabled = true)
|
||||
public static class SecuredConfig {
|
||||
}
|
||||
|
||||
// --- unsorted ---
|
||||
|
||||
@Test
|
||||
@WithMockUser
|
||||
public void methodSecurityWhenMissingEnableAnnotationThenShowsHelpfulError() {
|
||||
assertThatThrownBy(() ->
|
||||
this.spring.register(ExtendsNoEnableAnntotationConfig.class).autowire())
|
||||
.hasStackTraceContaining(EnableGlobalMethodSecurity.class.getName() + " is required");
|
||||
}
|
||||
|
||||
@Configuration
|
||||
public static class ExtendsNoEnableAnntotationConfig
|
||||
extends GlobalMethodSecurityConfiguration {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithMockUser
|
||||
public void methodSecurityWhenImportingGlobalMethodSecurityConfigurationSubclassThenAuthorizes() {
|
||||
this.spring.register(ImportSubclassGMSCConfig.class, MethodSecurityServiceConfig.class).autowire();
|
||||
|
||||
assertThatCode(() -> this.service.secured())
|
||||
.doesNotThrowAnyException();
|
||||
|
||||
assertThatCode(() -> this.service.jsr250())
|
||||
.doesNotThrowAnyException();
|
||||
|
||||
assertThatThrownBy(() -> this.service.preAuthorize())
|
||||
.isInstanceOf(AccessDeniedException.class);
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@Import(PreAuthorizeExtendsGMSCConfig.class)
|
||||
public static class ImportSubclassGMSCConfig {
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue