mirror of
https://github.com/spring-projects/spring-security.git
synced 2025-06-01 09:42:13 +00:00
SEC-3076: Add Method Level Security Meta Annotations
This commit is contained in:
parent
7708129aad
commit
cbed1d75ee
@ -0,0 +1,39 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2002-2015 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.method;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Rob Winch
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class Contact {
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param name
|
||||||
|
*/
|
||||||
|
public Contact(String name) {
|
||||||
|
super();
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the name
|
||||||
|
*/
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,29 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2002-2015 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.method;
|
||||||
|
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
|
||||||
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Rob Winch
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@PreAuthorize("#contact.name == authentication.name")
|
||||||
|
public @interface ContactPermission {}
|
@ -0,0 +1,31 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2002-2015 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.method;
|
||||||
|
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
|
||||||
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Rob Winch
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@PreAuthorize("hasRole('ADMIN')")
|
||||||
|
public @interface PreAuthorizeAdminRole {
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,30 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2002-2015 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.method;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Rob Winch
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class PreAuthorizeServiceImpl {
|
||||||
|
|
||||||
|
@PreAuthorizeAdminRole
|
||||||
|
public void preAuthorizeAdminRole() {}
|
||||||
|
|
||||||
|
@ContactPermission
|
||||||
|
public void contactPermission(Contact contact) {}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,67 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2002-2015 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.method;
|
||||||
|
|
||||||
|
import org.junit.After;
|
||||||
|
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.authentication.TestingAuthenticationToken;
|
||||||
|
import org.springframework.security.core.context.SecurityContextHolder;
|
||||||
|
import org.springframework.test.context.ContextConfiguration;
|
||||||
|
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Rob Winch
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
@RunWith(SpringJUnit4ClassRunner.class)
|
||||||
|
@ContextConfiguration
|
||||||
|
public class PreAuthorizeTests {
|
||||||
|
@Autowired
|
||||||
|
PreAuthorizeServiceImpl service;
|
||||||
|
|
||||||
|
@After
|
||||||
|
public void cleanup() {
|
||||||
|
SecurityContextHolder.clearContext();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = AccessDeniedException.class)
|
||||||
|
public void preAuthorizeAdminRoleDenied() {
|
||||||
|
SecurityContextHolder.getContext().setAuthentication(new TestingAuthenticationToken("user", "pass", "ROLE_USER"));
|
||||||
|
service.preAuthorizeAdminRole();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void preAuthorizeAdminRoleGranted() {
|
||||||
|
SecurityContextHolder.getContext().setAuthentication(new TestingAuthenticationToken("user", "pass", "ROLE_ADMIN"));
|
||||||
|
service.preAuthorizeAdminRole();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void preAuthorizeContactPermissionGranted() {
|
||||||
|
SecurityContextHolder.getContext().setAuthentication(new TestingAuthenticationToken("user", "pass", "ROLE_ADMIN"));
|
||||||
|
service.contactPermission(new Contact("user"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = AccessDeniedException.class)
|
||||||
|
public void preAuthorizeContactPermissionDenied() {
|
||||||
|
SecurityContextHolder.getContext().setAuthentication(new TestingAuthenticationToken("user", "pass", "ROLE_ADMIN"));
|
||||||
|
service.contactPermission(new Contact("admin"));
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,29 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2002-2015 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.method;
|
||||||
|
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
|
||||||
|
import org.springframework.security.access.annotation.Secured;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Rob Winch
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Secured("ROLE_ADMIN")
|
||||||
|
public @interface SecuredAdminRole { }
|
@ -0,0 +1,26 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2002-2015 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.method;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Rob Winch
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class SecuredServiceImpl {
|
||||||
|
@SecuredAdminRole
|
||||||
|
public void securedAdminRole() {}
|
||||||
|
}
|
@ -0,0 +1,55 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2002-2015 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.method;
|
||||||
|
|
||||||
|
import org.junit.After;
|
||||||
|
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.authentication.TestingAuthenticationToken;
|
||||||
|
import org.springframework.security.core.context.SecurityContextHolder;
|
||||||
|
import org.springframework.test.context.ContextConfiguration;
|
||||||
|
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Rob Winch
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
@RunWith(SpringJUnit4ClassRunner.class)
|
||||||
|
@ContextConfiguration
|
||||||
|
public class SecuredTests {
|
||||||
|
@Autowired
|
||||||
|
SecuredServiceImpl service;
|
||||||
|
|
||||||
|
@After
|
||||||
|
public void cleanup() {
|
||||||
|
SecurityContextHolder.clearContext();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = AccessDeniedException.class)
|
||||||
|
public void securedAdminRoleDenied() {
|
||||||
|
SecurityContextHolder.getContext().setAuthentication(new TestingAuthenticationToken("user", "pass", "ROLE_USER"));
|
||||||
|
service.securedAdminRole();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void securedAdminRoleGranted() {
|
||||||
|
SecurityContextHolder.getContext().setAuthentication(new TestingAuthenticationToken("user", "pass", "ROLE_ADMIN"));
|
||||||
|
service.securedAdminRole();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,13 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<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"
|
||||||
|
xmlns:c="http://www.springframework.org/schema/c"
|
||||||
|
xsi:schemaLocation="http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-4.0.xsd
|
||||||
|
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
|
||||||
|
|
||||||
|
<global-method-security pre-post-annotations="enabled"/>
|
||||||
|
|
||||||
|
<b:bean class="org.springframework.security.config.method.PreAuthorizeServiceImpl"/>
|
||||||
|
|
||||||
|
</b:beans>
|
@ -0,0 +1,13 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<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"
|
||||||
|
xmlns:c="http://www.springframework.org/schema/c"
|
||||||
|
xsi:schemaLocation="http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-4.0.xsd
|
||||||
|
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
|
||||||
|
|
||||||
|
<global-method-security secured-annotations="enabled"/>
|
||||||
|
|
||||||
|
<b:bean class="org.springframework.security.config.method.SecuredServiceImpl"/>
|
||||||
|
|
||||||
|
</b:beans>
|
@ -369,7 +369,9 @@ This will give you access to the entire project history (including all releases
|
|||||||
[[new]]
|
[[new]]
|
||||||
== What's new in Spring Security 4.1
|
== What's new in Spring Security 4.1
|
||||||
|
|
||||||
* <<test-method-meta-annotations>>
|
* Meta Annotation Support
|
||||||
|
** <<test-method-meta-annotations>>
|
||||||
|
** <<method-security-meta-annotations>>
|
||||||
|
|
||||||
=== What's new in Spring Security 4.0
|
=== What's new in Spring Security 4.0
|
||||||
|
|
||||||
@ -4727,6 +4729,29 @@ To use `hasPermission()` expressions, you have to explicitly configure a `Permis
|
|||||||
|
|
||||||
Where `myPermissionEvaluator` is the bean which implements `PermissionEvaluator`. Usually this will be the implementation from the ACL module which is called`AclPermissionEvaluator`. See the "Contacts" sample application configuration for more details.
|
Where `myPermissionEvaluator` is the bean which implements `PermissionEvaluator`. Usually this will be the implementation from the ACL module which is called`AclPermissionEvaluator`. See the "Contacts" sample application configuration for more details.
|
||||||
|
|
||||||
|
===== Method Security Meta Annotations
|
||||||
|
|
||||||
|
You can make use of meta annotations for method security to make your code more readable.
|
||||||
|
This is especially convenient if you find that you are repeating the same complex expression throughout your code base.
|
||||||
|
For example, consider the following:
|
||||||
|
|
||||||
|
[source,java]
|
||||||
|
----
|
||||||
|
@PreAuthorize("#contact.name == authentication.name")
|
||||||
|
----
|
||||||
|
|
||||||
|
Instead of repeating this everywhere, we can create a meta annotation that can be used instead.
|
||||||
|
|
||||||
|
[source,java]
|
||||||
|
----
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@PreAuthorize("#contact.name == authentication.name")
|
||||||
|
public @interface ContactPermission {}
|
||||||
|
----
|
||||||
|
|
||||||
|
Meta annotations can be used for any of the Spring Security method security annotations.
|
||||||
|
In order to remain compliant with the specification JSR-250 annotations do not support meta annotations.
|
||||||
|
|
||||||
[[advanced-topics]]
|
[[advanced-topics]]
|
||||||
= Additional Topics
|
= Additional Topics
|
||||||
In this part we cover features which require a knowledge of previous chapters as well as some of the more advanced and less-commonly used features of the framework.
|
In this part we cover features which require a knowledge of previous chapters as well as some of the more advanced and less-commonly used features of the framework.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user