Add AuthorizationManagerFactory
Signed-off-by: Steve Riesenberg <5248162+sjohnr@users.noreply.github.com>
This commit is contained in:
committed by
Rob Winch
parent
a4f813ab29
commit
eeb4574bb3
@@ -144,6 +144,43 @@ Another manager is the `AuthenticatedAuthorizationManager`.
|
||||
It can be used to differentiate between anonymous, fully-authenticated and remember-me authenticated users.
|
||||
Many sites allow certain limited access under remember-me authentication, but require a user to confirm their identity by logging in for full access.
|
||||
|
||||
[[authz-authorization-manager-factory]]
|
||||
=== Creating AuthorizationManager instances
|
||||
|
||||
The javadoc:org.springframework.security.authorization.AuthorizationManagerFactory[] interface (introduced in Spring Security 7.0) is used to create generic ``AuthorizationManager``s in xref:servlet/authorization/authorize-http-requests.adoc[request-based] and xref:servlet/authorization/method-security.adoc[method-based] authorization components.
|
||||
The following is a sketch of the `AuthorizationManagerFactory` interface:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
public interface AuthorizationManagerFactory<T> {
|
||||
AuthorizationManager<T> permitAll();
|
||||
AuthorizationManager<T> denyAll();
|
||||
AuthorizationManager<T> hasRole(String role);
|
||||
AuthorizationManager<T> hasAnyRole(String... roles);
|
||||
AuthorizationManager<T> hasAuthority(String authority);
|
||||
AuthorizationManager<T> hasAnyAuthority(String... authorities);
|
||||
AuthorizationManager<T> authenticated();
|
||||
AuthorizationManager<T> fullyAuthenticated();
|
||||
AuthorizationManager<T> rememberMe();
|
||||
AuthorizationManager<T> anonymous();
|
||||
}
|
||||
----
|
||||
|
||||
The default implementation is javadoc:org.springframework.security.authorization.DefaultAuthorizationManagerFactory[], which allows for customizing the `rolePrefix` (defaults to `"ROLE_"`), `RoleHierarchy` and `AuthenticationTrustManager` that are provided to the ``AuthorizationManager``s created by the factory.
|
||||
|
||||
In order to customize the default instance used by Spring Security, simply publish a bean as in the following example:
|
||||
|
||||
include-code::./AuthorizationManagerFactoryConfiguration[tag=config,indent=0]
|
||||
|
||||
[TIP]
|
||||
It is also possible to target a specific usage of this factory within Spring Security by providing a concrete parameterized type instead of a generic type.
|
||||
See examples of each in the xref:servlet/authorization/authorize-http-requests.adoc#customizing-authorization-managers[request-based] and xref:servlet/authorization/method-security.adoc#customizing-authorization-managers[method-based] sections of the documentation.
|
||||
|
||||
In addition to simply customizing the default instance of `AuthorizationManagerFactory`, you can provide your own implementation to fully customize the instances created by the factory and provide your own implementations.
|
||||
|
||||
[NOTE]
|
||||
The {gh-url}/core/src/main/java/org/springframework/security/authorization/AuthorizationManagerFactory.java[actual interface] provides default implementations for all factory methods, which allows custom implementations to only implement the methods that need to be customized.
|
||||
|
||||
[[authz-authorization-managers]]
|
||||
==== AuthorizationManagers
|
||||
There are also helpful static factories in javadoc:org.springframework.security.authorization.AuthorizationManagers[] for composing individual ``AuthorizationManager``s into more sophisticated expressions.
|
||||
|
||||
@@ -57,6 +57,7 @@ In many cases, your authorization rules will be more sophisticated than that, so
|
||||
* I want to <<match-by-custom, match a request programmatically>>
|
||||
* I want to <<authorize-requests, authorize a request programmatically>>
|
||||
* I want to <<remote-authorization-manager, delegate request authorization>> to a policy agent
|
||||
* I want to <<customizing-authorization-managers,customize how authorization managers are created>>
|
||||
|
||||
[[request-authorization-architecture]]
|
||||
== Understanding How Request Authorization Components Work
|
||||
@@ -765,6 +766,24 @@ You will notice that since we are using the `hasRole` expression we do not need
|
||||
<6> Any URL that has not already been matched on is denied access.
|
||||
This is a good strategy if you do not want to accidentally forget to update your authorization rules.
|
||||
|
||||
[[customizing-authorization-managers]]
|
||||
== Customizing Authorization Managers
|
||||
|
||||
When you use the `authorizeHttpRequests` DSL, Spring Security takes care of creating the appropriate `AuthorizationManager` instances for you.
|
||||
In certain cases, you may want to customize what is created in order to have complete control over how authorization decisions are made xref:servlet/authorization/architecture.adoc#authz-delegate-authorization-manager[at the framework level].
|
||||
|
||||
In order to take control of creating instances of `AuthorizationManager` for authorizing HTTP requests, you can create a custom xref:servlet/authorization/architecture.adoc#authz-authorization-manager-factory[`AuthorizationManagerFactory`].
|
||||
For example, let's say you want to create a convention that authenticated users must be authenticated _AND_ have the `USER` role.
|
||||
To do this, you can create a custom implementation for HTTP requests as in the following example:
|
||||
|
||||
include-code::./CustomHttpRequestsAuthorizationManagerFactory[tag=class,indent=0]
|
||||
|
||||
Now, whenever you <<activate-request-security,require authentication>>, Spring Security will automatically invoke your custom factory to create an instance of `AuthorizationManager` that requires authentication _AND_ the `USER` role.
|
||||
|
||||
[TIP]
|
||||
We use this as a simple example of creating a custom `AuthorizationManagerFactory`, though it is also possible (and often simpler) to replace a specific `AuthorizationManager` only for a particular request.
|
||||
See <<remote-authorization-manager>> for an example.
|
||||
|
||||
[[authorization-expressions]]
|
||||
== Expressing Authorization with SpEL
|
||||
|
||||
|
||||
@@ -1995,6 +1995,24 @@ This works on both classes and interfaces.
|
||||
This does not work for interfaces, since they do not have debug information about the parameter names.
|
||||
For interfaces, either annotations or the `-parameters` approach must be used.
|
||||
|
||||
[[customizing-authorization-managers]]
|
||||
== Customizing Authorization Managers
|
||||
|
||||
When you use SpEL expressions with <<use-preauthorize,`@PreAuthorize`>>, <<use-postauthorize,`@PostAuthorize`>>, <<use-prefilter,`@PreFilter`>> and <<use-postfilter,`@PostFilter`>>, Spring Security takes care of creating the appropriate `AuthorizationManager` instances for you.
|
||||
In certain cases, you may want to customize what is created in order to have complete control over how authorization decisions are made xref:servlet/authorization/architecture.adoc#authz-delegate-authorization-manager[at the framework level].
|
||||
|
||||
In order to take control of creating instances of `AuthorizationManager` for pre- and post-annotations, you can create a custom xref:servlet/authorization/architecture.adoc#authz-authorization-manager-factory[`AuthorizationManagerFactory`].
|
||||
For example, let's say you want to allow users with the `ADMIN` role whenever any other role is required.
|
||||
To do this, you can create a custom implementation for method security as in the following example:
|
||||
|
||||
include-code::./CustomMethodInvocationAuthorizationManagerFactory[tag=class,indent=0]
|
||||
|
||||
Now, whenever you <<use-preauthorize,use the `@PreAuthorize` annotation>> with `hasRole` or `hasAnyRole`, Spring Security will automatically invoke your custom factory to create an instance of `AuthorizationManager` that allows access for the given role(s) _OR_ the `ADMIN` role.
|
||||
|
||||
[TIP]
|
||||
We use this as a simple example of creating a custom `AuthorizationManagerFactory`, though the same outcome could be accomplished with <<favor-granting-authorities,a role hierarchy>>.
|
||||
Use whichever approach fits best in your situation.
|
||||
|
||||
[[authorize-object]]
|
||||
== Authorizing Arbitrary Objects
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@ Each section that follows will indicate the more notable removals as well as the
|
||||
== Core
|
||||
|
||||
* Removed `AuthorizationManager#check` in favor of `AuthorizationManager#authorize`
|
||||
* Added xref:servlet/authorization/architecture.adoc#authz-authorization-manager-factory[`AuthorizationManagerFactory`] for creating `AuthorizationManager` instances in xref:servlet/authorization/authorize-http-requests.adoc#customizing-authorization-managers[request-based] and xref:servlet/authorization/method-security.adoc#customizing-authorization-managers[method-based] authorization components
|
||||
|
||||
== Config
|
||||
|
||||
|
||||
+77
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright 2004-present 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 clients 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.docs.servlet.authorization.authzauthorizationmanagerfactory;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.access.hierarchicalroles.RoleHierarchyImpl;
|
||||
import org.springframework.security.authentication.AuthenticationTrustResolverImpl;
|
||||
import org.springframework.security.authentication.TestingAuthenticationToken;
|
||||
import org.springframework.security.authorization.AuthorizationManagerFactory;
|
||||
import org.springframework.security.authorization.DefaultAuthorizationManagerFactory;
|
||||
|
||||
/**
|
||||
* Documentation for {@link AuthorizationManagerFactory}.
|
||||
*
|
||||
* @author Steve Riesenberg
|
||||
*/
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
public class AuthorizationManagerFactoryConfiguration {
|
||||
|
||||
// tag::config[]
|
||||
@Bean
|
||||
<T> AuthorizationManagerFactory<T> authorizationManagerFactory() {
|
||||
DefaultAuthorizationManagerFactory<T> authorizationManagerFactory =
|
||||
new DefaultAuthorizationManagerFactory<>();
|
||||
authorizationManagerFactory.setTrustResolver(getAuthenticationTrustResolver());
|
||||
authorizationManagerFactory.setRoleHierarchy(getRoleHierarchy());
|
||||
authorizationManagerFactory.setRolePrefix("role_");
|
||||
|
||||
return authorizationManagerFactory;
|
||||
}
|
||||
// end::config[]
|
||||
|
||||
private static AuthenticationTrustResolverImpl getAuthenticationTrustResolver() {
|
||||
AuthenticationTrustResolverImpl authenticationTrustResolver =
|
||||
new AuthenticationTrustResolverImpl();
|
||||
authenticationTrustResolver.setAnonymousClass(Anonymous.class);
|
||||
authenticationTrustResolver.setRememberMeClass(RememberMe.class);
|
||||
|
||||
return authenticationTrustResolver;
|
||||
}
|
||||
|
||||
private static RoleHierarchyImpl getRoleHierarchy() {
|
||||
return RoleHierarchyImpl.fromHierarchy("role_admin > role_user");
|
||||
}
|
||||
|
||||
static class Anonymous extends TestingAuthenticationToken {
|
||||
|
||||
Anonymous(String principal) {
|
||||
super(principal, "", "role_anonymous");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static class RememberMe extends TestingAuthenticationToken {
|
||||
|
||||
RememberMe(String principal) {
|
||||
super(principal, "", "role_rememberMe");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
+208
@@ -0,0 +1,208 @@
|
||||
/*
|
||||
* Copyright 2004-present 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 clients 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.docs.servlet.authorization.authzauthorizationmanagerfactory;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.security.authentication.TestingAuthenticationToken;
|
||||
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||
import org.springframework.security.config.test.SpringTestContext;
|
||||
import org.springframework.security.config.test.SpringTestContextExtension;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.docs.servlet.authorization.authzauthorizationmanagerfactory.AuthorizationManagerFactoryConfiguration.Anonymous;
|
||||
import org.springframework.security.docs.servlet.authorization.authzauthorizationmanagerfactory.AuthorizationManagerFactoryConfiguration.RememberMe;
|
||||
import org.springframework.security.web.SecurityFilterChain;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.ResponseStatus;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
|
||||
|
||||
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.authentication;
|
||||
import static org.springframework.security.test.web.servlet.response.SecurityMockMvcResultMatchers.authenticated;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
/**
|
||||
* Tests for {@link AuthorizationManagerFactoryConfiguration}.
|
||||
*
|
||||
* @author Steve Riesenberg
|
||||
*/
|
||||
@ExtendWith(SpringTestContextExtension.class)
|
||||
public class AuthorizationManagerFactoryConfigurationTests {
|
||||
|
||||
public final SpringTestContext spring = new SpringTestContext(this);
|
||||
|
||||
@Autowired
|
||||
MockMvc mockMvc;
|
||||
|
||||
@Test
|
||||
void getAnonymousWhenCustomAnonymousClassThenOk() throws Exception {
|
||||
this.spring.register(AuthorizationManagerFactoryConfiguration.class, SecurityConfiguration.class,
|
||||
TestController.class).autowire();
|
||||
Authentication authentication = new Anonymous("anonymous");
|
||||
// @formatter:off
|
||||
this.mockMvc.perform(get("/anonymous").with(authentication(authentication)))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(authenticated().withAuthentication(authentication));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
void getAnonymousWhenAuthenticatedThenForbidden() throws Exception {
|
||||
this.spring.register(AuthorizationManagerFactoryConfiguration.class, SecurityConfiguration.class,
|
||||
TestController.class).autowire();
|
||||
Authentication authentication = new TestingAuthenticationToken("user", "", "role_user");
|
||||
// @formatter:off
|
||||
this.mockMvc.perform(get("/anonymous").with(authentication(authentication)))
|
||||
.andExpect(status().isForbidden())
|
||||
.andExpect(authenticated().withAuthentication(authentication));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
void getRememberMeWhenCustomRememberMeClassThenOk() throws Exception {
|
||||
this.spring.register(AuthorizationManagerFactoryConfiguration.class, SecurityConfiguration.class,
|
||||
TestController.class).autowire();
|
||||
Authentication authentication = new RememberMe("rememberMe");
|
||||
// @formatter:off
|
||||
this.mockMvc.perform(get("/rememberMe").with(authentication(authentication)))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(authenticated().withAuthentication(authentication));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
void getRememberMeWhenAuthenticatedThenForbidden() throws Exception {
|
||||
this.spring.register(AuthorizationManagerFactoryConfiguration.class, SecurityConfiguration.class,
|
||||
TestController.class).autowire();
|
||||
Authentication authentication = new TestingAuthenticationToken("user", "", "role_user");
|
||||
// @formatter:off
|
||||
this.mockMvc.perform(get("/rememberMe").with(authentication(authentication)))
|
||||
.andExpect(status().isForbidden())
|
||||
.andExpect(authenticated().withAuthentication(authentication));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
void getUserWhenCustomUserRoleThenOk() throws Exception {
|
||||
this.spring.register(AuthorizationManagerFactoryConfiguration.class, SecurityConfiguration.class,
|
||||
TestController.class).autowire();
|
||||
Authentication authentication = new TestingAuthenticationToken("user", "", "role_user");
|
||||
// @formatter:off
|
||||
this.mockMvc.perform(get("/user").with(authentication(authentication)))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(authenticated().withAuthentication(authentication));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
void getUserWhenCustomAdminRoleThenOk() throws Exception {
|
||||
this.spring.register(AuthorizationManagerFactoryConfiguration.class, SecurityConfiguration.class,
|
||||
TestController.class).autowire();
|
||||
Authentication authentication = new TestingAuthenticationToken("admin", "", "role_admin");
|
||||
// @formatter:off
|
||||
this.mockMvc.perform(get("/user").with(authentication(authentication)))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(authenticated().withAuthentication(authentication));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
void getPreAuthorizeWhenCustomUserRoleThenOk() throws Exception {
|
||||
this.spring.register(AuthorizationManagerFactoryConfiguration.class, SecurityConfiguration.class,
|
||||
TestController.class).autowire();
|
||||
Authentication authentication = new TestingAuthenticationToken("user", "", "role_user");
|
||||
// @formatter:off
|
||||
this.mockMvc.perform(get("/preAuthorize").with(authentication(authentication)))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(authenticated().withAuthentication(authentication));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
void getPreAuthorizeWhenCustomAdminRoleThenOk() throws Exception {
|
||||
this.spring.register(AuthorizationManagerFactoryConfiguration.class, SecurityConfiguration.class,
|
||||
TestController.class).autowire();
|
||||
Authentication authentication = new TestingAuthenticationToken("admin", "", "role_admin");
|
||||
// @formatter:off
|
||||
this.mockMvc.perform(get("/preAuthorize").with(authentication(authentication)))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(authenticated().withAuthentication(authentication));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
void getPreAuthorizeWhenOtherRoleThenForbidden() throws Exception {
|
||||
this.spring.register(AuthorizationManagerFactoryConfiguration.class, SecurityConfiguration.class,
|
||||
TestController.class).autowire();
|
||||
Authentication authentication = new TestingAuthenticationToken("other", "", "role_other");
|
||||
// @formatter:off
|
||||
this.mockMvc.perform(get("/preAuthorize").with(authentication(authentication)))
|
||||
.andExpect(status().isForbidden())
|
||||
.andExpect(authenticated().withAuthentication(authentication));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@EnableWebMvc
|
||||
@EnableWebSecurity
|
||||
@EnableMethodSecurity
|
||||
@Configuration
|
||||
static class SecurityConfiguration {
|
||||
|
||||
@Bean
|
||||
SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
|
||||
// @formatter:off
|
||||
http
|
||||
.authorizeHttpRequests((authorize) -> authorize
|
||||
.requestMatchers("/anonymous").anonymous()
|
||||
.requestMatchers("/rememberMe").rememberMe()
|
||||
.requestMatchers("/user").hasRole("user")
|
||||
.requestMatchers("/preAuthorize").permitAll()
|
||||
.anyRequest().denyAll()
|
||||
);
|
||||
// @formatter:on
|
||||
return http.build();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@RestController
|
||||
static class TestController {
|
||||
|
||||
@GetMapping({ "/anonymous", "/rememberMe", "/user" })
|
||||
@ResponseStatus(HttpStatus.OK)
|
||||
void httpRequest() {
|
||||
}
|
||||
|
||||
@GetMapping("/preAuthorize")
|
||||
@ResponseStatus(HttpStatus.OK)
|
||||
@PreAuthorize("hasRole('user')")
|
||||
void preAuthorize() {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright 2004-present 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 clients 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.docs.servlet.authorization.customizingauthorizationmanagers;
|
||||
|
||||
import org.springframework.security.authorization.AuthorizationManager;
|
||||
import org.springframework.security.authorization.AuthorizationManagerFactory;
|
||||
import org.springframework.security.authorization.AuthorizationManagers;
|
||||
import org.springframework.security.authorization.DefaultAuthorizationManagerFactory;
|
||||
import org.springframework.security.web.access.intercept.RequestAuthorizationContext;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* Documentation for {@link AuthorizationManagerFactory}.
|
||||
*
|
||||
* @author Steve Riesenberg
|
||||
*/
|
||||
// tag::class[]
|
||||
@Component
|
||||
public class CustomHttpRequestsAuthorizationManagerFactory
|
||||
implements AuthorizationManagerFactory<RequestAuthorizationContext> {
|
||||
|
||||
private final AuthorizationManagerFactory<RequestAuthorizationContext> delegate =
|
||||
new DefaultAuthorizationManagerFactory<>();
|
||||
|
||||
@Override
|
||||
public AuthorizationManager<RequestAuthorizationContext> authenticated() {
|
||||
return AuthorizationManagers.allOf(
|
||||
this.delegate.authenticated(),
|
||||
this.delegate.hasRole("USER")
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
// end::class[]
|
||||
+137
@@ -0,0 +1,137 @@
|
||||
/*
|
||||
* Copyright 2004-present 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 clients 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.docs.servlet.authorization.customizingauthorizationmanagers;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.security.authentication.TestingAuthenticationToken;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||
import org.springframework.security.config.test.SpringTestContext;
|
||||
import org.springframework.security.config.test.SpringTestContextExtension;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.web.SecurityFilterChain;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.ResponseStatus;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
|
||||
|
||||
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.anonymous;
|
||||
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.authentication;
|
||||
import static org.springframework.security.test.web.servlet.response.SecurityMockMvcResultMatchers.authenticated;
|
||||
import static org.springframework.security.test.web.servlet.response.SecurityMockMvcResultMatchers.unauthenticated;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
/**
|
||||
* Tests for {@link CustomHttpRequestsAuthorizationManagerFactory}.
|
||||
*
|
||||
* @author Steve Riesenberg
|
||||
*/
|
||||
@ExtendWith(SpringTestContextExtension.class)
|
||||
public class CustomHttpRequestsAuthorizationManagerFactoryTests {
|
||||
|
||||
public final SpringTestContext spring = new SpringTestContext(this);
|
||||
|
||||
@Autowired
|
||||
MockMvc mockMvc;
|
||||
|
||||
@Test
|
||||
void getHelloWhenAnonymousThenForbidden() throws Exception {
|
||||
this.spring.register(SecurityConfiguration.class, TestController.class).autowire();
|
||||
// @formatter:off
|
||||
this.mockMvc.perform(get("/hello").with(anonymous()))
|
||||
.andExpect(status().isForbidden())
|
||||
.andExpect(unauthenticated());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
void getHelloWhenAuthenticatedWithNoRolesThenForbidden() throws Exception {
|
||||
this.spring.register(SecurityConfiguration.class, TestController.class).autowire();
|
||||
Authentication authentication = new TestingAuthenticationToken("user", "", Collections.emptyList());
|
||||
// @formatter:off
|
||||
this.mockMvc.perform(get("/hello").with(authentication(authentication)))
|
||||
.andExpect(status().isForbidden())
|
||||
.andExpect(authenticated().withAuthentication(authentication));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
void getHelloWhenAuthenticatedWithUserRoleThenOk() throws Exception {
|
||||
this.spring.register(SecurityConfiguration.class, TestController.class).autowire();
|
||||
Authentication authentication = new TestingAuthenticationToken("user", "", "ROLE_USER");
|
||||
// @formatter:off
|
||||
this.mockMvc.perform(get("/hello").with(authentication(authentication)))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(authenticated().withAuthentication(authentication));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
void getHelloWhenAuthenticatedWithOtherRoleThenForbidden() throws Exception {
|
||||
this.spring.register(SecurityConfiguration.class, TestController.class).autowire();
|
||||
Authentication authentication = new TestingAuthenticationToken("user", "", "ROLE_OTHER");
|
||||
// @formatter:off
|
||||
this.mockMvc.perform(get("/hello").with(authentication(authentication)))
|
||||
.andExpect(status().isForbidden())
|
||||
.andExpect(authenticated().withAuthentication(authentication));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@EnableWebMvc
|
||||
@EnableWebSecurity
|
||||
@Configuration
|
||||
static class SecurityConfiguration {
|
||||
|
||||
@Bean
|
||||
SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
|
||||
// @formatter:off
|
||||
http
|
||||
.authorizeHttpRequests((authorize) -> authorize
|
||||
.anyRequest().authenticated()
|
||||
);
|
||||
// @formatter:on
|
||||
return http.build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
CustomHttpRequestsAuthorizationManagerFactory customHttpRequestsAuthorizationManagerFactory() {
|
||||
return new CustomHttpRequestsAuthorizationManagerFactory();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@RestController
|
||||
static class TestController {
|
||||
|
||||
@GetMapping("/**")
|
||||
@ResponseStatus(HttpStatus.OK)
|
||||
void ok() {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
+57
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright 2004-present 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 clients 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.docs.servlet.authorization.customizingauthorizationmanagers;
|
||||
|
||||
import org.aopalliance.intercept.MethodInvocation;
|
||||
|
||||
import org.springframework.security.authorization.AuthorizationManager;
|
||||
import org.springframework.security.authorization.AuthorizationManagerFactory;
|
||||
import org.springframework.security.authorization.AuthorizationManagers;
|
||||
import org.springframework.security.authorization.DefaultAuthorizationManagerFactory;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* Documentation for {@link AuthorizationManagerFactory}.
|
||||
*
|
||||
* @author Steve Riesenberg
|
||||
*/
|
||||
// tag::class[]
|
||||
@Component
|
||||
public class CustomMethodInvocationAuthorizationManagerFactory
|
||||
implements AuthorizationManagerFactory<MethodInvocation> {
|
||||
|
||||
private final AuthorizationManagerFactory<MethodInvocation> delegate =
|
||||
new DefaultAuthorizationManagerFactory<>();
|
||||
|
||||
@Override
|
||||
public AuthorizationManager<MethodInvocation> hasRole(String role) {
|
||||
return AuthorizationManagers.anyOf(
|
||||
this.delegate.hasRole(role),
|
||||
this.delegate.hasRole("ADMIN")
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AuthorizationManager<MethodInvocation> hasAnyRole(String... roles) {
|
||||
return AuthorizationManagers.anyOf(
|
||||
this.delegate.hasAnyRole(roles),
|
||||
this.delegate.hasRole("ADMIN")
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
// end::class[]
|
||||
+191
@@ -0,0 +1,191 @@
|
||||
/*
|
||||
* Copyright 2004-present 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 clients 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.docs.servlet.authorization.customizingauthorizationmanagers;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.security.authentication.TestingAuthenticationToken;
|
||||
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||
import org.springframework.security.config.test.SpringTestContext;
|
||||
import org.springframework.security.config.test.SpringTestContextExtension;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.web.SecurityFilterChain;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.ResponseStatus;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
|
||||
|
||||
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.anonymous;
|
||||
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.authentication;
|
||||
import static org.springframework.security.test.web.servlet.response.SecurityMockMvcResultMatchers.authenticated;
|
||||
import static org.springframework.security.test.web.servlet.response.SecurityMockMvcResultMatchers.unauthenticated;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
/**
|
||||
* Tests for {@link CustomMethodInvocationAuthorizationManagerFactory}.
|
||||
*
|
||||
* @author Steve Riesenberg
|
||||
*/
|
||||
@ExtendWith(SpringTestContextExtension.class)
|
||||
public class CustomMethodInvocationAuthorizationManagerFactoryTests {
|
||||
|
||||
public final SpringTestContext spring = new SpringTestContext(this);
|
||||
|
||||
@Autowired
|
||||
MockMvc mockMvc;
|
||||
|
||||
@Test
|
||||
void getUserWhenAnonymousThenForbidden() throws Exception {
|
||||
this.spring.register(SecurityConfiguration.class, TestController.class).autowire();
|
||||
// @formatter:off
|
||||
this.mockMvc.perform(get("/user").with(anonymous()))
|
||||
.andExpect(status().isForbidden())
|
||||
.andExpect(unauthenticated());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
void getUserWhenAuthenticatedWithNoRolesThenForbidden() throws Exception {
|
||||
this.spring.register(SecurityConfiguration.class, TestController.class).autowire();
|
||||
Authentication authentication = new TestingAuthenticationToken("user", "", Collections.emptyList());
|
||||
// @formatter:off
|
||||
this.mockMvc.perform(get("/user").with(authentication(authentication)))
|
||||
.andExpect(status().isForbidden())
|
||||
.andExpect(authenticated().withAuthentication(authentication));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
void getUserWhenAuthenticatedWithUserRoleThenOk() throws Exception {
|
||||
this.spring.register(SecurityConfiguration.class, TestController.class).autowire();
|
||||
Authentication authentication = new TestingAuthenticationToken("user", "", "ROLE_USER");
|
||||
// @formatter:off
|
||||
this.mockMvc.perform(get("/user").with(authentication(authentication)))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(authenticated().withAuthentication(authentication));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
void getUserWhenAuthenticatedWithAdminRoleThenOk() throws Exception {
|
||||
this.spring.register(SecurityConfiguration.class, TestController.class).autowire();
|
||||
Authentication authentication = new TestingAuthenticationToken("admin", "", "ROLE_ADMIN");
|
||||
// @formatter:off
|
||||
this.mockMvc.perform(get("/user").with(authentication(authentication)))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(authenticated().withAuthentication(authentication));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
void getUserWhenAuthenticatedWithOtherRoleThenForbidden() throws Exception {
|
||||
this.spring.register(SecurityConfiguration.class, TestController.class).autowire();
|
||||
Authentication authentication = new TestingAuthenticationToken("user", "", "ROLE_OTHER");
|
||||
// @formatter:off
|
||||
this.mockMvc.perform(get("/user").with(authentication(authentication)))
|
||||
.andExpect(status().isForbidden())
|
||||
.andExpect(authenticated().withAuthentication(authentication));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
void getRolesWhenAuthenticatedWithRole1RoleThenOk() throws Exception {
|
||||
this.spring.register(SecurityConfiguration.class, TestController.class).autowire();
|
||||
Authentication authentication = new TestingAuthenticationToken("user", "", "ROLE_ROLE1");
|
||||
// @formatter:off
|
||||
this.mockMvc.perform(get("/roles").with(authentication(authentication)))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(authenticated().withAuthentication(authentication));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
void getRolesWhenAuthenticatedWithAdminRoleThenOk() throws Exception {
|
||||
this.spring.register(SecurityConfiguration.class, TestController.class).autowire();
|
||||
Authentication authentication = new TestingAuthenticationToken("admin", "", "ROLE_ADMIN");
|
||||
// @formatter:off
|
||||
this.mockMvc.perform(get("/roles").with(authentication(authentication)))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(authenticated().withAuthentication(authentication));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
void getRolesWhenAuthenticatedWithOtherRoleThenForbidden() throws Exception {
|
||||
this.spring.register(SecurityConfiguration.class, TestController.class).autowire();
|
||||
Authentication authentication = new TestingAuthenticationToken("user", "", "ROLE_OTHER");
|
||||
// @formatter:off
|
||||
this.mockMvc.perform(get("/roles").with(authentication(authentication)))
|
||||
.andExpect(status().isForbidden())
|
||||
.andExpect(authenticated().withAuthentication(authentication));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@EnableWebMvc
|
||||
@EnableWebSecurity
|
||||
@EnableMethodSecurity
|
||||
@Configuration
|
||||
static class SecurityConfiguration {
|
||||
|
||||
@Bean
|
||||
SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
|
||||
// @formatter:off
|
||||
http
|
||||
.authorizeHttpRequests((authorize) -> authorize
|
||||
.anyRequest().authenticated()
|
||||
);
|
||||
// @formatter:on
|
||||
return http.build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
CustomMethodInvocationAuthorizationManagerFactory customMethodInvocationAuthorizationManagerFactory() {
|
||||
return new CustomMethodInvocationAuthorizationManagerFactory();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@RestController
|
||||
static class TestController {
|
||||
|
||||
@GetMapping("/user")
|
||||
@ResponseStatus(HttpStatus.OK)
|
||||
@PreAuthorize("hasRole('USER')")
|
||||
void user() {
|
||||
}
|
||||
|
||||
@GetMapping("/roles")
|
||||
@ResponseStatus(HttpStatus.OK)
|
||||
@PreAuthorize("hasAnyRole('ROLE1', 'ROLE2')")
|
||||
void roles() {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
+62
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright 2004-present 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.kt.docs.servlet.authorization.authzauthorizationmanagerfactory
|
||||
|
||||
import org.springframework.context.annotation.Bean
|
||||
import org.springframework.context.annotation.Configuration
|
||||
import org.springframework.security.access.hierarchicalroles.RoleHierarchyImpl
|
||||
import org.springframework.security.authentication.AuthenticationTrustResolverImpl
|
||||
import org.springframework.security.authentication.TestingAuthenticationToken
|
||||
import org.springframework.security.authorization.AuthorizationManagerFactory
|
||||
import org.springframework.security.authorization.DefaultAuthorizationManagerFactory
|
||||
|
||||
/**
|
||||
* Documentation for [org.springframework.security.authorization.AuthorizationManagerFactory].
|
||||
*
|
||||
* @author Steve Riesenberg
|
||||
*/
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
class AuthorizationManagerFactoryConfiguration {
|
||||
// tag::config[]
|
||||
@Bean
|
||||
fun <T> authorizationManagerFactory(): AuthorizationManagerFactory<T> {
|
||||
val authorizationManagerFactory = DefaultAuthorizationManagerFactory<T>()
|
||||
authorizationManagerFactory.setTrustResolver(getAuthenticationTrustResolver())
|
||||
authorizationManagerFactory.setRoleHierarchy(getRoleHierarchy())
|
||||
authorizationManagerFactory.setRolePrefix("role_")
|
||||
|
||||
return authorizationManagerFactory
|
||||
}
|
||||
// end::config[]
|
||||
|
||||
private fun getAuthenticationTrustResolver(): AuthenticationTrustResolverImpl {
|
||||
val authenticationTrustResolver = AuthenticationTrustResolverImpl()
|
||||
authenticationTrustResolver.setAnonymousClass(Anonymous::class.java)
|
||||
authenticationTrustResolver.setRememberMeClass(RememberMe::class.java)
|
||||
|
||||
return authenticationTrustResolver
|
||||
}
|
||||
|
||||
private fun getRoleHierarchy(): RoleHierarchyImpl {
|
||||
return RoleHierarchyImpl.fromHierarchy("role_admin > role_user")
|
||||
}
|
||||
|
||||
internal class Anonymous(principal: String) :
|
||||
TestingAuthenticationToken(principal, "", "role_anonymous")
|
||||
|
||||
internal class RememberMe(principal: String) :
|
||||
TestingAuthenticationToken(principal, "", "role_rememberMe")
|
||||
}
|
||||
+229
@@ -0,0 +1,229 @@
|
||||
/*
|
||||
* Copyright 2004-present 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.kt.docs.servlet.authorization.authzauthorizationmanagerfactory
|
||||
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.junit.jupiter.api.extension.ExtendWith
|
||||
import org.springframework.beans.factory.annotation.Autowired
|
||||
import org.springframework.context.annotation.Bean
|
||||
import org.springframework.context.annotation.Configuration
|
||||
import org.springframework.http.HttpStatus
|
||||
import org.springframework.security.access.prepost.PreAuthorize
|
||||
import org.springframework.security.authentication.TestingAuthenticationToken
|
||||
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity
|
||||
import org.springframework.security.config.test.SpringTestContext
|
||||
import org.springframework.security.config.test.SpringTestContextExtension
|
||||
import org.springframework.security.kt.docs.servlet.authorization.authzauthorizationmanagerfactory.AuthorizationManagerFactoryConfiguration.Anonymous
|
||||
import org.springframework.security.kt.docs.servlet.authorization.authzauthorizationmanagerfactory.AuthorizationManagerFactoryConfiguration.RememberMe
|
||||
import org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.authentication
|
||||
import org.springframework.security.test.web.servlet.response.SecurityMockMvcResultMatchers.authenticated
|
||||
import org.springframework.security.web.SecurityFilterChain
|
||||
import org.springframework.test.web.servlet.MockMvc
|
||||
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get
|
||||
import org.springframework.test.web.servlet.result.MockMvcResultMatchers.status
|
||||
import org.springframework.web.bind.annotation.GetMapping
|
||||
import org.springframework.web.bind.annotation.ResponseStatus
|
||||
import org.springframework.web.bind.annotation.RestController
|
||||
import org.springframework.web.servlet.config.annotation.EnableWebMvc
|
||||
|
||||
/**
|
||||
* Tests for [AuthorizationManagerFactoryConfiguration].
|
||||
*
|
||||
* @author Steve Riesenberg
|
||||
*/
|
||||
@ExtendWith(SpringTestContextExtension::class)
|
||||
class AuthorizationManagerFactoryConfigurationTests {
|
||||
@JvmField
|
||||
val spring = SpringTestContext(this)
|
||||
|
||||
@Autowired
|
||||
lateinit var mockMvc: MockMvc
|
||||
|
||||
@Test
|
||||
@Throws(Exception::class)
|
||||
fun getAnonymousWhenCustomAnonymousClassThenOk() {
|
||||
this.spring.register(AuthorizationManagerFactoryConfiguration::class.java, SecurityConfiguration::class.java)
|
||||
.autowire()
|
||||
val authentication = Anonymous("anonymous")
|
||||
// @formatter:off
|
||||
mockMvc.perform(get("/anonymous").with(authentication(authentication)))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(authenticated().withAuthentication(authentication))
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
@Throws(Exception::class)
|
||||
fun getAnonymousWhenAuthenticatedThenForbidden() {
|
||||
this.spring.register(AuthorizationManagerFactoryConfiguration::class.java, SecurityConfiguration::class.java)
|
||||
.autowire()
|
||||
val authentication = TestingAuthenticationToken("user", "", "role_user")
|
||||
// @formatter:off
|
||||
mockMvc.perform(get("/anonymous").with(authentication(authentication)))
|
||||
.andExpect(status().isForbidden())
|
||||
.andExpect(authenticated().withAuthentication(authentication))
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
@Throws(Exception::class)
|
||||
fun getRememberMeWhenCustomRememberMeClassThenOk() {
|
||||
this.spring.register(AuthorizationManagerFactoryConfiguration::class.java, SecurityConfiguration::class.java)
|
||||
.autowire()
|
||||
val authentication = RememberMe("rememberMe")
|
||||
// @formatter:off
|
||||
mockMvc.perform(get("/rememberMe").with(authentication(authentication)))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(authenticated().withAuthentication(authentication))
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
@Throws(Exception::class)
|
||||
fun getRememberMeWhenAuthenticatedThenForbidden() {
|
||||
this.spring.register(AuthorizationManagerFactoryConfiguration::class.java, SecurityConfiguration::class.java)
|
||||
.autowire()
|
||||
val user = TestingAuthenticationToken("user", "", "role_user")
|
||||
// @formatter:off
|
||||
mockMvc.perform(get("/rememberMe").with(authentication(user)))
|
||||
.andExpect(status().isForbidden())
|
||||
.andExpect(authenticated().withAuthentication(user))
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
@Throws(Exception::class)
|
||||
fun getUserWhenCustomUserRoleThenOk() {
|
||||
this.spring.register(AuthorizationManagerFactoryConfiguration::class.java, SecurityConfiguration::class.java)
|
||||
.autowire()
|
||||
val authentication = TestingAuthenticationToken("user", "", "role_user")
|
||||
// @formatter:off
|
||||
mockMvc.perform(get("/user").with(authentication(authentication)))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(authenticated().withAuthentication(authentication))
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
@Throws(Exception::class)
|
||||
fun getUserWhenCustomAdminRoleThenOk() {
|
||||
this.spring.register(AuthorizationManagerFactoryConfiguration::class.java, SecurityConfiguration::class.java)
|
||||
.autowire()
|
||||
val admin = TestingAuthenticationToken("admin", "", "role_admin")
|
||||
// @formatter:off
|
||||
mockMvc.perform(get("/user").with(authentication(admin)))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(authenticated().withAuthentication(admin))
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
@Throws(Exception::class)
|
||||
fun getPreAuthorizeWhenCustomUserRoleThenOk() {
|
||||
this.spring.register(AuthorizationManagerFactoryConfiguration::class.java, SecurityConfiguration::class.java)
|
||||
.autowire()
|
||||
val authentication = TestingAuthenticationToken("user", "", "role_user")
|
||||
// @formatter:off
|
||||
mockMvc.perform(get("/preAuthorize").with(authentication(authentication)))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(authenticated().withAuthentication(authentication))
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
@Throws(Exception::class)
|
||||
fun getPreAuthorizeWhenCustomAdminRoleThenOk() {
|
||||
this.spring.register(AuthorizationManagerFactoryConfiguration::class.java, SecurityConfiguration::class.java)
|
||||
.autowire()
|
||||
val authentication = TestingAuthenticationToken("admin", "", "role_admin")
|
||||
// @formatter:off
|
||||
mockMvc.perform(get("/preAuthorize").with(authentication(authentication)))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(authenticated().withAuthentication(authentication))
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
@Throws(Exception::class)
|
||||
fun getPreAuthorizeWhenOtherRoleThenForbidden() {
|
||||
this.spring.register(AuthorizationManagerFactoryConfiguration::class.java, SecurityConfiguration::class.java)
|
||||
.autowire()
|
||||
val authentication = TestingAuthenticationToken("other", "", "role_other")
|
||||
// @formatter:off
|
||||
mockMvc.perform(get("/preAuthorize").with(authentication(authentication)))
|
||||
.andExpect(status().isForbidden())
|
||||
.andExpect(authenticated().withAuthentication(authentication))
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@EnableWebMvc
|
||||
@EnableWebSecurity
|
||||
@EnableMethodSecurity
|
||||
@Configuration
|
||||
internal open class SecurityConfiguration {
|
||||
@Bean
|
||||
@Throws(Exception::class)
|
||||
open fun securityFilterChain(http: HttpSecurity): SecurityFilterChain {
|
||||
// @formatter:off
|
||||
http.authorizeHttpRequests { authorize ->
|
||||
authorize
|
||||
.requestMatchers("/anonymous").anonymous()
|
||||
.requestMatchers("/rememberMe").rememberMe()
|
||||
.requestMatchers("/user").hasRole("user")
|
||||
.requestMatchers("/preAuthorize").permitAll()
|
||||
.anyRequest().denyAll()
|
||||
}
|
||||
// @formatter:on
|
||||
return http.build()
|
||||
}
|
||||
|
||||
@Bean
|
||||
open fun testController(testService: TestService): TestController {
|
||||
return TestController(testService())
|
||||
}
|
||||
|
||||
@Bean
|
||||
open fun testService(): TestService {
|
||||
return TestServiceImpl()
|
||||
}
|
||||
}
|
||||
|
||||
@RestController
|
||||
internal open class TestController(private val testService: TestService) {
|
||||
@GetMapping(value = ["/anonymous", "/rememberMe", "/user"])
|
||||
@ResponseStatus(HttpStatus.OK)
|
||||
fun httpRequest() {
|
||||
}
|
||||
|
||||
@GetMapping("/preAuthorize")
|
||||
@ResponseStatus(HttpStatus.OK)
|
||||
fun preAuthorize() {
|
||||
testService.preAuthorize()
|
||||
}
|
||||
}
|
||||
|
||||
internal interface TestService {
|
||||
@PreAuthorize("hasRole('user')")
|
||||
fun preAuthorize()
|
||||
}
|
||||
|
||||
internal open class TestServiceImpl : TestService {
|
||||
override fun preAuthorize() {
|
||||
}
|
||||
}
|
||||
}
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright 2004-present 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.kt.docs.servlet.authorization.customizingauthorizationmanagers
|
||||
|
||||
import org.springframework.security.authorization.AuthorizationManager
|
||||
import org.springframework.security.authorization.AuthorizationManagerFactory
|
||||
import org.springframework.security.authorization.AuthorizationManagers
|
||||
import org.springframework.security.authorization.DefaultAuthorizationManagerFactory
|
||||
import org.springframework.security.web.access.intercept.RequestAuthorizationContext
|
||||
import org.springframework.stereotype.Component
|
||||
|
||||
/**
|
||||
* Documentation for {@link AuthorizationManagerFactory}.
|
||||
*
|
||||
* @author Steve Riesenberg
|
||||
*/
|
||||
// tag::class[]
|
||||
@Component
|
||||
class CustomHttpRequestsAuthorizationManagerFactory : AuthorizationManagerFactory<RequestAuthorizationContext> {
|
||||
private val delegate = DefaultAuthorizationManagerFactory<RequestAuthorizationContext>()
|
||||
|
||||
override fun authenticated(): AuthorizationManager<RequestAuthorizationContext> {
|
||||
return AuthorizationManagers.allOf(
|
||||
delegate.authenticated(),
|
||||
delegate.hasRole("USER")
|
||||
)
|
||||
}
|
||||
}
|
||||
// end::class[]
|
||||
|
||||
|
||||
+131
@@ -0,0 +1,131 @@
|
||||
/*
|
||||
* Copyright 2004-present 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.kt.docs.servlet.authorization.customizingauthorizationmanagers
|
||||
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.junit.jupiter.api.extension.ExtendWith
|
||||
import org.springframework.beans.factory.annotation.Autowired
|
||||
import org.springframework.context.annotation.Bean
|
||||
import org.springframework.context.annotation.Configuration
|
||||
import org.springframework.http.HttpStatus
|
||||
import org.springframework.security.authentication.TestingAuthenticationToken
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity
|
||||
import org.springframework.security.config.test.SpringTestContext
|
||||
import org.springframework.security.config.test.SpringTestContextExtension
|
||||
import org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.anonymous
|
||||
import org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.authentication
|
||||
import org.springframework.security.test.web.servlet.response.SecurityMockMvcResultMatchers
|
||||
import org.springframework.security.test.web.servlet.response.SecurityMockMvcResultMatchers.authenticated
|
||||
import org.springframework.security.web.SecurityFilterChain
|
||||
import org.springframework.test.web.servlet.MockMvc
|
||||
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get
|
||||
import org.springframework.test.web.servlet.result.MockMvcResultMatchers.status
|
||||
import org.springframework.web.bind.annotation.GetMapping
|
||||
import org.springframework.web.bind.annotation.ResponseStatus
|
||||
import org.springframework.web.bind.annotation.RestController
|
||||
import org.springframework.web.servlet.config.annotation.EnableWebMvc
|
||||
|
||||
/**
|
||||
* Tests for [CustomHttpRequestsAuthorizationManagerFactory].
|
||||
*
|
||||
* @author Steve Riesenberg
|
||||
*/
|
||||
@ExtendWith(SpringTestContextExtension::class)
|
||||
class CustomHttpRequestsAuthorizationManagerFactoryTests {
|
||||
@JvmField
|
||||
val spring = SpringTestContext(this)
|
||||
|
||||
@Autowired
|
||||
lateinit var mockMvc: MockMvc
|
||||
|
||||
@Test
|
||||
@Throws(Exception::class)
|
||||
fun getHelloWhenAnonymousThenForbidden() {
|
||||
spring.register(SecurityConfiguration::class.java, TestController::class.java).autowire()
|
||||
// @formatter:off
|
||||
mockMvc.perform(get("/hello").with(anonymous()))
|
||||
.andExpect(status().isForbidden())
|
||||
.andExpect(SecurityMockMvcResultMatchers.unauthenticated())
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
@Throws(Exception::class)
|
||||
fun getHelloWhenAuthenticatedWithUserRoleThenOk() {
|
||||
spring.register(SecurityConfiguration::class.java, TestController::class.java).autowire()
|
||||
val authentication = TestingAuthenticationToken("user", "", "ROLE_USER")
|
||||
// @formatter:off
|
||||
mockMvc.perform(get("/hello").with(authentication(authentication)))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(authenticated().withAuthentication(authentication))
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
@Throws(Exception::class)
|
||||
fun getHelloWhenAuthenticatedWithOtherRoleThenForbidden() {
|
||||
spring.register(SecurityConfiguration::class.java, TestController::class.java).autowire()
|
||||
val authentication = TestingAuthenticationToken("user", "", "ROLE_OTHER")
|
||||
// @formatter:off
|
||||
mockMvc.perform(get("/hello").with(authentication(authentication)))
|
||||
.andExpect(status().isForbidden())
|
||||
.andExpect(authenticated().withAuthentication(authentication))
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
@Throws(Exception::class)
|
||||
fun getHelloWhenAuthenticatedWithNoRolesThenForbidden() {
|
||||
spring.register(SecurityConfiguration::class.java, TestController::class.java).autowire()
|
||||
val authentication = TestingAuthenticationToken("user", "", listOf())
|
||||
// @formatter:off
|
||||
mockMvc.perform(get("/hello").with(authentication(authentication)))
|
||||
.andExpect(status().isForbidden())
|
||||
.andExpect(authenticated().withAuthentication(authentication))
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@EnableWebMvc
|
||||
@EnableWebSecurity
|
||||
@Configuration
|
||||
internal open class SecurityConfiguration {
|
||||
@Bean
|
||||
@Throws(Exception::class)
|
||||
open fun securityFilterChain(http: HttpSecurity): SecurityFilterChain {
|
||||
// @formatter:off
|
||||
http
|
||||
.authorizeHttpRequests { authorize ->
|
||||
authorize.anyRequest().authenticated()
|
||||
}
|
||||
// @formatter:on
|
||||
return http.build()
|
||||
}
|
||||
|
||||
@Bean
|
||||
open fun customHttpRequestsAuthorizationManagerFactory(): CustomHttpRequestsAuthorizationManagerFactory {
|
||||
return CustomHttpRequestsAuthorizationManagerFactory()
|
||||
}
|
||||
}
|
||||
|
||||
@RestController
|
||||
internal class TestController {
|
||||
@GetMapping("/**")
|
||||
@ResponseStatus(HttpStatus.OK)
|
||||
fun ok() {
|
||||
}
|
||||
}
|
||||
}
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright 2004-present 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.kt.docs.servlet.authorization.customizingauthorizationmanagers
|
||||
|
||||
import org.aopalliance.intercept.MethodInvocation
|
||||
import org.springframework.security.authorization.AuthorizationManager
|
||||
import org.springframework.security.authorization.AuthorizationManagerFactory
|
||||
import org.springframework.security.authorization.AuthorizationManagers
|
||||
import org.springframework.security.authorization.DefaultAuthorizationManagerFactory
|
||||
import org.springframework.stereotype.Component
|
||||
|
||||
/**
|
||||
* Documentation for [AuthorizationManagerFactory].
|
||||
*
|
||||
* @author Steve Riesenberg
|
||||
*/
|
||||
// tag::class[]
|
||||
@Component
|
||||
class CustomMethodInvocationAuthorizationManagerFactory : AuthorizationManagerFactory<MethodInvocation> {
|
||||
private val delegate = DefaultAuthorizationManagerFactory<MethodInvocation>()
|
||||
|
||||
override fun hasRole(role: String): AuthorizationManager<MethodInvocation> {
|
||||
return AuthorizationManagers.anyOf(
|
||||
delegate.hasRole(role),
|
||||
delegate.hasRole("ADMIN")
|
||||
)
|
||||
}
|
||||
|
||||
override fun hasAnyRole(vararg roles: String): AuthorizationManager<MethodInvocation> {
|
||||
return AuthorizationManagers.anyOf(
|
||||
delegate.hasAnyRole(*roles),
|
||||
delegate.hasRole("ADMIN")
|
||||
)
|
||||
}
|
||||
}
|
||||
// end::class[]
|
||||
|
||||
+215
@@ -0,0 +1,215 @@
|
||||
/*
|
||||
* Copyright 2004-present 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.kt.docs.servlet.authorization.customizingauthorizationmanagers
|
||||
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.junit.jupiter.api.extension.ExtendWith
|
||||
import org.springframework.beans.factory.annotation.Autowired
|
||||
import org.springframework.context.annotation.Bean
|
||||
import org.springframework.context.annotation.Configuration
|
||||
import org.springframework.http.HttpStatus
|
||||
import org.springframework.security.access.prepost.PreAuthorize
|
||||
import org.springframework.security.authentication.TestingAuthenticationToken
|
||||
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity
|
||||
import org.springframework.security.config.test.SpringTestContext
|
||||
import org.springframework.security.config.test.SpringTestContextExtension
|
||||
import org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.anonymous
|
||||
import org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.authentication
|
||||
import org.springframework.security.test.web.servlet.response.SecurityMockMvcResultMatchers.authenticated
|
||||
import org.springframework.security.test.web.servlet.response.SecurityMockMvcResultMatchers.unauthenticated
|
||||
import org.springframework.security.web.SecurityFilterChain
|
||||
import org.springframework.test.web.servlet.MockMvc
|
||||
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get
|
||||
import org.springframework.test.web.servlet.result.MockMvcResultMatchers.status
|
||||
import org.springframework.web.bind.annotation.GetMapping
|
||||
import org.springframework.web.bind.annotation.ResponseStatus
|
||||
import org.springframework.web.bind.annotation.RestController
|
||||
import org.springframework.web.servlet.config.annotation.EnableWebMvc
|
||||
|
||||
/**
|
||||
* Tests for [CustomMethodInvocationAuthorizationManagerFactory].
|
||||
*
|
||||
* @author Steve Riesenberg
|
||||
*/
|
||||
@ExtendWith(SpringTestContextExtension::class)
|
||||
class CustomMethodInvocationAuthorizationManagerFactoryTests {
|
||||
@JvmField
|
||||
val spring = SpringTestContext(this)
|
||||
|
||||
@Autowired
|
||||
lateinit var mockMvc: MockMvc
|
||||
|
||||
@Test
|
||||
@Throws(Exception::class)
|
||||
fun getUserWhenAnonymousThenForbidden() {
|
||||
spring.register(SecurityConfiguration::class.java).autowire()
|
||||
// @formatter:off
|
||||
mockMvc.perform(get("/user").with(anonymous()))
|
||||
.andExpect(status().isForbidden())
|
||||
.andExpect(unauthenticated())
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
@Throws(Exception::class)
|
||||
fun getUserWhenAuthenticatedWithNoRolesThenForbidden() {
|
||||
spring.register(SecurityConfiguration::class.java).autowire()
|
||||
val authentication = TestingAuthenticationToken("user", "", listOf())
|
||||
// @formatter:off
|
||||
mockMvc.perform(get("/user").with(authentication(authentication)))
|
||||
.andExpect(status().isForbidden())
|
||||
.andExpect(authenticated().withAuthentication(authentication))
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
@Throws(Exception::class)
|
||||
fun getUserWhenAuthenticatedWithUserRoleThenOk() {
|
||||
spring.register(SecurityConfiguration::class.java).autowire()
|
||||
val authentication = TestingAuthenticationToken("user", "", "ROLE_USER")
|
||||
// @formatter:off
|
||||
mockMvc.perform(get("/user").with(authentication(authentication)))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(authenticated().withAuthentication(authentication))
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
@Throws(Exception::class)
|
||||
fun getUserWhenAuthenticatedWithAdminRoleThenOk() {
|
||||
spring.register(SecurityConfiguration::class.java).autowire()
|
||||
val authentication = TestingAuthenticationToken("user", "", "ROLE_ADMIN")
|
||||
// @formatter:off
|
||||
mockMvc.perform(get("/user").with(authentication(authentication)))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(authenticated().withAuthentication(authentication))
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
@Throws(Exception::class)
|
||||
fun getUserWhenAuthenticatedWithOtherRoleThenForbidden() {
|
||||
spring.register(SecurityConfiguration::class.java).autowire()
|
||||
val authentication = TestingAuthenticationToken("user", "", "ROLE_OTHER")
|
||||
// @formatter:off
|
||||
mockMvc.perform(get("/user").with(authentication(authentication)))
|
||||
.andExpect(status().isForbidden())
|
||||
.andExpect(authenticated().withAuthentication(authentication))
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
@Throws(Exception::class)
|
||||
fun getRolesWhenAuthenticatedWithRole1RoleThenOk() {
|
||||
spring.register(SecurityConfiguration::class.java).autowire()
|
||||
val authentication = TestingAuthenticationToken("user", "", "ROLE_ROLE1")
|
||||
// @formatter:off
|
||||
mockMvc.perform(get("/roles").with(authentication(authentication)))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(authenticated().withAuthentication(authentication))
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
@Throws(Exception::class)
|
||||
fun getRolesWhenAuthenticatedWithAdminRoleThenOk() {
|
||||
spring.register(SecurityConfiguration::class.java).autowire()
|
||||
val authentication = TestingAuthenticationToken("user", "", "ROLE_ADMIN")
|
||||
// @formatter:off
|
||||
mockMvc.perform(get("/roles").with(authentication(authentication)))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(authenticated().withAuthentication(authentication))
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
@Throws(Exception::class)
|
||||
fun getRolesWhenAuthenticatedWithOtherRoleThenForbidden() {
|
||||
spring.register(SecurityConfiguration::class.java).autowire()
|
||||
val authentication = TestingAuthenticationToken("user", "", "ROLE_OTHER")
|
||||
// @formatter:off
|
||||
mockMvc.perform(get("/roles").with(authentication(authentication)))
|
||||
.andExpect(status().isForbidden())
|
||||
.andExpect(authenticated().withAuthentication(authentication))
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@EnableWebMvc
|
||||
@EnableWebSecurity
|
||||
@EnableMethodSecurity
|
||||
@Configuration
|
||||
internal open class SecurityConfiguration {
|
||||
@Bean
|
||||
@Throws(Exception::class)
|
||||
open fun securityFilterChain(http: HttpSecurity): SecurityFilterChain {
|
||||
// @formatter:off
|
||||
http
|
||||
.authorizeHttpRequests { authorize ->
|
||||
authorize.anyRequest().authenticated()
|
||||
}
|
||||
// @formatter:on
|
||||
return http.build()
|
||||
}
|
||||
|
||||
@Bean
|
||||
open fun customMethodInvocationAuthorizationManagerFactory(): CustomMethodInvocationAuthorizationManagerFactory {
|
||||
return CustomMethodInvocationAuthorizationManagerFactory()
|
||||
}
|
||||
|
||||
@Bean
|
||||
open fun testController(testService: TestService): TestController {
|
||||
return TestController(testService())
|
||||
}
|
||||
|
||||
@Bean
|
||||
open fun testService(): TestService {
|
||||
return TestServiceImpl()
|
||||
}
|
||||
}
|
||||
|
||||
@RestController
|
||||
internal open class TestController(private val testService: TestService) {
|
||||
@GetMapping("/user")
|
||||
@ResponseStatus(HttpStatus.OK)
|
||||
fun user() {
|
||||
testService.user()
|
||||
}
|
||||
|
||||
@GetMapping("/roles")
|
||||
@ResponseStatus(HttpStatus.OK)
|
||||
fun roles() {
|
||||
testService.roles()
|
||||
}
|
||||
}
|
||||
|
||||
internal interface TestService {
|
||||
@PreAuthorize("hasRole('USER')")
|
||||
fun user()
|
||||
|
||||
@PreAuthorize("hasAnyRole('ROLE1', 'ROLE2')")
|
||||
fun roles()
|
||||
}
|
||||
|
||||
internal open class TestServiceImpl : TestService {
|
||||
override fun user() {
|
||||
}
|
||||
|
||||
override fun roles() {
|
||||
}
|
||||
}
|
||||
}
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
~ Copyright 2004-present the original author or authors.
|
||||
~
|
||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
||||
~ you may not use this file except in compliance with the License.
|
||||
~ You may obtain a copy of the License at
|
||||
~
|
||||
~ https://www.apache.org/licenses/LICENSE-2.0
|
||||
~
|
||||
~ Unless required by applicable law or agreed to in writing, software
|
||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
~ See the License for the specific language governing permissions and
|
||||
~ limitations under the License.
|
||||
-->
|
||||
|
||||
<b:beans xmlns:b="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="
|
||||
http://www.springframework.org/schema/beans
|
||||
https://www.springframework.org/schema/beans/spring-beans.xsd">
|
||||
|
||||
<!-- tag::config[] -->
|
||||
<b:bean id="authorizationManagerFactory" class="org.springframework.security.authorization.DefaultAuthorizationManagerFactory">
|
||||
<b:property name="trustResolver" ref="authenticationTrustResolver"/>
|
||||
<b:property name="roleHierarchy" ref="roleHierarchy"/>
|
||||
<b:property name="rolePrefix" value="role_"/>
|
||||
</b:bean>
|
||||
<!-- end::config[] -->
|
||||
|
||||
<b:bean id="authenticationTrustResolver" class="org.springframework.security.authentication.AuthenticationTrustResolverImpl">
|
||||
<b:property name="anonymousClass" value="org.springframework.security.authentication.TestingAuthenticationToken"/>
|
||||
</b:bean>
|
||||
|
||||
<b:bean id="roleHierarchy" class="org.springframework.security.access.hierarchicalroles.RoleHierarchyImpl" factory-method="fromHierarchy">
|
||||
<b:constructor-arg name="hierarchy" value="role_admin > role_user"/>
|
||||
</b:bean>
|
||||
|
||||
</b:beans>
|
||||
Reference in New Issue
Block a user