Spring Security Authorization 官方文档分析

Spring Security Authorization 源码分析

基于官方文档 https://docs.spring.io/spring-security/reference/servlet/authentication/index.html

1.Authorization

The advanced authorization capabilities within Spring Security represent one of the most compelling reasons for its popularity. Irrespective of how you choose to authenticate (whether using a Spring Security-provided mechanism and provider or integrating with a container or other non-Spring Security authentication authority), the authorization services can be used within your application in a consistent and simple way.

In this part, we explore the different AbstractSecurityInterceptor implementations, which were introduced in Part I. We then move on to explore how to fine-tune authorization through the use of domain access control lists.

2.Section Summary

3. Authorization Architecture

This section describes the Spring Security architecture that applies to authorization.

描述 spring security 在授权中的应用

4. Authorities

Authentication discusses how all Authentication implementations store a list of GrantedAuthority objects. These represent the authorities that have been granted to the principal. The GrantedAuthority objects are inserted into the Authentication object by the AuthenticationManager and are later read by AccessDecisionManager instances when making authorization decisions.

Authentication 描述了所有的 Authentication实现如何存储一个 GrantedAuthority 对象列表。GrantedAuthority对象由AuthenticationManager插入到Authentication对象中,然后由AccessDecisionManager实例在做出授权决策时读取

The GrantedAuthority interface has only one method:

	/**
	 * If the <code>GrantedAuthority</code> can be represented as a <code>String</code>
	 * and that <code>String</code> is sufficient in precision to be relied upon for an
	 * access control decision by an {@link AccessDecisionManager} (or delegate), this
	 * method should return such a <code>String</code>.
	 * <p>
	 * If the <code>GrantedAuthority</code> cannot be expressed with sufficient precision
	 * as a <code>String</code>, <code>null</code> should be returned. Returning
	 * <code>null</code> will require an <code>AccessDecisionManager</code> (or delegate)
	 * to specifically support the <code>GrantedAuthority</code> implementation, so
	 * returning <code>null</code> should be avoided unless actually required.
	 * @return a representation of the granted authority (or <code>null</code> if the
	 * granted authority cannot be expressed as a <code>String</code> with sufficient
	 * precision).
	 */
	String getAuthority();

This method lets an AccessDecisionManager instance to obtain a precise String representation of the GrantedAuthority. By returning a representation as a String, a GrantedAuthority can be easily “read” by most AccessDecisionManager implementations. If a GrantedAuthority cannot be precisely represented as a String, the GrantedAuthority is considered “complex” and getAuthority() must return null.

这个方法可以让 AccessDecisionManager实例获取一个准确的字符串,代表授予的权限。

An example of a “complex” GrantedAuthority would be an implementation that stores a list of operations and authority thresholds that apply to different customer account numbers. Representing this complex GrantedAuthority as a String would be quite difficult. As a result, the getAuthority() method should return null. This indicates to any AccessDecisionManager that it needs to support the specific GrantedAuthority implementation to understand its contents.

Spring Security includes one concrete GrantedAuthority implementation: SimpleGrantedAuthority. This implementation lets any user-specified String be converted into a GrantedAuthority. All AuthenticationProvider instances included with the security architecture use SimpleGrantedAuthority to populate the Authentication object.

spring security 包含一个 GrantedAuthority的实现: SimpleGrantedAuthority。 其可以是所有的 权限字符转换位 GrantedAuthority, 所有的 AuthenticationProvider 都会用 SimpleGrantedAuthority 提供一个 Authentication 对象

5. Pre-Invocation Handling

Spring Security provides interceptors that control access to secure objects, such as method invocations or web requests. A pre-invocation decision on whether the invocation is allowed to proceed is made by the AccessDecisionManager.

Spring Security 中,安全拦截器(Security Interceptor)用于控制对受保护对象的访问,例如方法调用或Web请求。这些安全拦截器根据配置,会拦截请求并将其转发到AccessDecisionManager进行授权决策,以确定是否允许请求继续进行。

5. The AuthorizationManager

AuthorizationManager supersedes both AccessDecisionManager and AccessDecisionVoter.

AuthorizationManagers are called by the AuthorizationFilter and are responsible for making final access control decisions. The AuthorizationManager interface contains two methods:

AuthorizationManagers被 AuthorizationFilter 调用, 做出最后的访问控制决策。 只有两个方法。

	/**
	 * Determines if access should be granted for a specific authentication and object.
	 * @param authentication the {@link Supplier} of the {@link Authentication} to check
	 * @param object the {@link T} object to check
	 * @throws AccessDeniedException if access is not granted
	 */
	default void verify(Supplier<Authentication> authentication, T object) {
		AuthorizationDecision decision = check(authentication, object);
		if (decision != null && !decision.isGranted()) {
			throw new AccessDeniedException("Access Denied");
		}
	}

	/**
	 * Determines if access is granted for a specific authentication and object.
	 * @param authentication the {@link Supplier} of the {@link Authentication} to check
	 * @param object the {@link T} object to check
	 * @return an {@link AuthorizationDecision} or null if no decision could be made
	 */
	@Nullable
	AuthorizationDecision check(Supplier<Authentication> authentication, T object);

The AuthorizationManager’s check method is passed all the relevant information it needs in order to make an authorization decision. In particular, passing the secure Object enables those arguments contained in the actual secure object invocation to be inspected. For example, let’s assume the secure object was a MethodInvocation. It would be easy to query the MethodInvocation for any Customer argument, and then implement some sort of security logic in the AuthorizationManager to ensure the principal is permitted to operate on that customer. Implementations are expected to return a positive AuthorizationDecision if access is granted, negative AuthorizationDecision if access is denied, and a null AuthorizationDecision when abstaining from making a decision.

Spring Security 中,AuthorizationManager 是一种授权管理器,它用于在访问受保护资源之前,检查用户是否具有足够的授权信息。AuthorizationManager 接口中定义了一个 check 方法,该方法需要传递所有相关的信息,以便进行授权决策。在特定情况下,将安全对象作为参数传递给 check 方法,可以方便地查询实际的安全对象调用中包含的参数信息,以实现更精细的授权逻辑。

例如,假设我们有一个 MethodInvocation 对象表示一个受保护的方法调用。在 AuthorizationManagercheck 方法中,我们可以查询 MethodInvocation 对象中的参数信息,例如查询其中是否有一个 Customer 参数。如果有 Customer 参数,则可以使用 AuthorizationManager 中的某些逻辑来验证当前用户是否有权限操作该 Customer 对象。如果用户有足够的授权信息,AuthorizationManager 将返回一个 AuthorizationDecision 表示授权通过,否则将返回一个表示拒绝授权的 AuthorizationDecision,或者返回 null 表示弃权决策。

总之,AuthorizationManagercheck 方法允许我们检查用户是否具有足够的授权信息来访问受保护的资源,并且可以根据实际的安全对象调用中包含的参数信息,实现更精细的授权逻辑。

5.1 Delegate-based AuthorizationManager Implementations

Whilst users can implement their own AuthorizationManager to control all aspects of authorization, Spring Security ships with a delegating AuthorizationManager that can collaborate with individual AuthorizationManagers.

Spring Security 中,用户可以实现自己的 AuthorizationManager 来控制所有的授权方面,但是 Spring Security 也提供了一个委托式的 AuthorizationManager,它可以与个别的 AuthorizationManager 协同工作,实现更灵活和可扩展的授权机制。

RequestMatcherDelegatingAuthorizationManager will match the request with the most appropriate delegate AuthorizationManager. For method security, you can use AuthorizationManagerBeforeMethodInterceptor and AuthorizationManagerAfterMethodInterceptor.

Authorization Manager Implementations illustrates the relevant classes.

在这里插入图片描述

Using this approach, a composition of AuthorizationManager implementations can be polled on an authorization decision.

5.2 AuthorityAuthorizationManager

The most common AuthorizationManager provided with Spring Security is AuthorityAuthorizationManager. It is configured with a given set of authorities to look for on the current Authentication. It will return positive AuthorizationDecision should the Authentication contain any of the configured authorities. It will return a negative AuthorizationDecision otherwise.

	private final Set<String> authorities;

	private AuthorityAuthorizationManager(String... authorities) {
		this.authorities = Set.of(authorities);
	}

	/**
	 * Determines if the current user is authorized by evaluating if the
	 * {@link Authentication} contains a specified authority.
	 * @param authentication the {@link Supplier} of the {@link Authentication} to check
	 * @param object the {@link T} object to check
	 * @return an {@link AuthorizationDecision}
	 */
	@Override
	public AuthorizationDecision check(Supplier<Authentication> authentication, T object) {
		return this.delegate.check(authentication, this.authorities);
	}

5.3 AuthenticatedAuthorizationManager

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.

5.4 Custom Authorization Managers

Obviously, you can also implement a custom AuthorizationManager and you can put just about any access-control logic you want in it. It might be specific to your application (business-logic related) or it might implement some security administration logic. For example, you can create an implementation that can query Open Policy Agent or your own authorization database.

6. Adapting AccessDecisionManager and AccessDecisionVoters

适配旧版本

Previous to AuthorizationManager, Spring Security published AccessDecisionManager and AccessDecisionVoter.

In some cases, like migrating an older application, it may be desirable to introduce an AuthorizationManager that invokes an AccessDecisionManager or AccessDecisionVoter.

To call an existing AccessDecisionManager, you can do:

Adapting an AccessDecisionManager

  • Java
@Component
public class AccessDecisionManagerAuthorizationManagerAdapter implements AuthorizationManager {
    private final AccessDecisionManager accessDecisionManager;
    private final SecurityMetadataSource securityMetadataSource;

    @Override
    public AuthorizationDecision check(Supplier<Authentication> authentication, Object object) {
        try {
            Collection<ConfigAttribute> attributes = this.securityMetadataSource.getAttributes(object);
            this.accessDecisionManager.decide(authentication.get(), object, attributes);
            return new AuthorizationDecision(true);
        } catch (AccessDeniedException ex) {
            return new AuthorizationDecision(false);
        }
    }

    @Override
    public void verify(Supplier<Authentication> authentication, Object object) {
        Collection<ConfigAttribute> attributes = this.securityMetadataSource.getAttributes(object);
        this.accessDecisionManager.decide(authentication.get(), object, attributes);
    }
}
Copied!

And then wire it into your SecurityFilterChain.

Or to only call an AccessDecisionVoter, you can do:

Adapting an AccessDecisionVoter

  • Java
@Component
public class AccessDecisionVoterAuthorizationManagerAdapter implements AuthorizationManager {
    private final AccessDecisionVoter accessDecisionVoter;
    private final SecurityMetadataSource securityMetadataSource;

    @Override
    public AuthorizationDecision check(Supplier<Authentication> authentication, Object object) {
        Collection<ConfigAttribute> attributes = this.securityMetadataSource.getAttributes(object);
        int decision = this.accessDecisionVoter.vote(authentication.get(), object, attributes);
        switch (decision) {
        case ACCESS_GRANTED:
            return new AuthorizationDecision(true);
        case ACCESS_DENIED:
            return new AuthorizationDecision(false);
        }
        return null;
    }
}
Copied!

And then wire it into your SecurityFilterChain.

7. Hierarchical Roles

It is a common requirement that a particular role in an application should automatically “include” other roles. For example, in an application which has the concept of an “admin” and a “user” role, you may want an admin to be able to do everything a normal user can. To achieve this, you can either make sure that all admin users are also assigned the “user” role. Alternatively, you can modify every access constraint which requires the “user” role to also include the “admin” role. This can get quite complicated if you have a lot of different roles in your application.

应用程序中的特定角色应该自动“包含”其他角色,这是一个常见的需求。例如,在具有“管理员”和“用户”角色概念的应用程序中,您可能希望管理员能够做普通用户可以做的所有事情。要实现这一点,您可以确保所有管理用户也被分配为“user”角色。或者,您可以修改每个访问约束,要求“用户”角色也包括“管理员”角色。如果您的应用程序中有很多不同的角色,这可能会变得相当复杂

The use of a role-hierarchy allows you to configure which roles (or authorities) should include others. An extended version of Spring Security’s RoleVoter, RoleHierarchyVoter, is configured with a RoleHierarchy, from which it obtains all the “reachable authorities” which the user is assigned. A typical configuration might look like this:

@Bean
AccessDecisionVoter hierarchyVoter() {
    RoleHierarchy hierarchy = new RoleHierarchyImpl();
    hierarchy.setHierarchy("ROLE_ADMIN > ROLE_STAFF\n" +
            "ROLE_STAFF > ROLE_USER\n" +
            "ROLE_USER > ROLE_GUEST");
    return new RoleHierarchyVoter(hierarchy);
}

​ Here we have four roles in a hierarchy ROLE_ADMIN ⇒ ROLE_STAFF ⇒ ROLE_USER ⇒ ROLE_GUEST. A user who is authenticated with ROLE_ADMIN, will behave as if they have all four roles when security constraints are evaluated against an AuthorizationManager adapted to call the above RoleHierarchyVoter. The > symbol can be thought of as meaning “includes”.

这里给出的四个角色 ROLE_ADMIN ⇒ ROLE_STAFF ⇒ ROLE_USER ⇒ ROLE_GUEST 代表了一个层级关系,其中一个角色的权限包含了它下面的所有角色的权限。具体来说,如果一个用户被授权为 ROLE_ADMIN,那么在权限验证时,使用 RoleHierarchyVoterAuthorizationManager 将认为该用户具有所有四个角色的权限。

例如,假设存在一个安全约束,要求用户具有 ROLE_USER 的权限才能访问某个资源。那么,一个被授权为 ROLE_ADMIN 的用户就可以访问该资源,因为 ROLE_ADMIN 包含了 ROLE_USER 的权限。同样地,如果一个用户被授权为 ROLE_STAFF,那么该用户也将被认为具有 ROLE_USERROLE_GUEST 的权限。

因此,这个层级关系可以帮助简化权限管理,让更高级别的角色包含了低级别角色的权限,从而避免了重复授权的工作。

​ Role hierarchies offer a convenient means of simplifying the access-control configuration data for your application and/or reducing the number of authorities which you need to assign to a user. For more complex requirements you may wish to define a logical mapping between the specific access-rights your application requires and the roles that are assigned to users, translating between the two when loading the user information.

角色层级提供了一种简化应用程序访问控制配置数据或减少需要为用户分配的权限数量的便捷方法。但对于更复杂的要求,您可能希望定义特定访问权限与分配给用户的角色之间的逻辑映射,以在加载用户信息时在两者之间进行转换。

这种逻辑映射可以帮助您更好地管理应用程序中的访问权限,使您能够将具体的访问权限映射到与其相关的角色。例如,假设您的应用程序需要授予用户读、写和删除资源的访问权限。您可以将这些访问权限映射到三个角色 ROLE_READ, ROLE_WRITEROLE_DELETE,然后分配这些角色给相应的用户。这样,您就可以更方便地管理用户的访问权限,而不需要对每个用户分配一系列具体的访问权限。

当加载用户信息时,您可以使用该逻辑映射来将这些角色映射回具体的访问权限。例如,如果一个用户被授予了 ROLE_WRITEROLE_DELETE 的角色,那么您可以在加载该用户信息时将这些角色映射回具体的访问权限,即写和删除资源的访问权限。

总之,角色层级和逻辑映射都是访问控制中常用的概念,它们可以帮助简化和管理访问控制配置数据和用户的访问权限。

8. Authorize HttpServletRequests with AuthorizationFilter

This section builds on Servlet Architecture and Implementation by digging deeper into how authorization works within Servlet-based applications.

The AuthorizationFilter provides authorization for HttpServletRequests. It is inserted into the FilterChainProxy as one of the Security Filters.

You can override the default when you declare a SecurityFilterChain. Instead of using authorizeRequests, use authorizeHttpRequests, like so:

Use authorizeHttpRequests

@Bean
SecurityFilterChain web(HttpSecurity http) throws AuthenticationException {
    http
        .authorizeHttpRequests((authorize) -> authorize
            .anyRequest().authenticated();
        )
        // ...

    return http.build();
}

​ This improves on authorizeRequests in a number of ways:

  1. Uses the simplified AuthorizationManager API instead of metadata sources, config attributes, decision managers, and voters. This simplifies reuse and customization.
  2. Delays Authentication lookup. Instead of the authentication needing to be looked up for every request, it will only look it up in requests where an authorization decision requires authentication.
  3. Bean-based configuration support.

​ When authorizeHttpRequests is used instead of authorizeRequests, then AuthorizationFilter is used instead of FilterSecurityInterceptor.

在这里插入图片描述

  • number 1 First, the AuthorizationFilter obtains an Authentication from the SecurityContextHolder. It wraps this in an Supplier in order to delay lookup.
  • number 2 Second, it passes the Supplier<Authentication> and the HttpServletRequest to the AuthorizationManager.
    • number 3 If authorization is denied, an AccessDeniedException is thrown. In this case the ExceptionTranslationFilter handles the AccessDeniedException.
    • number 4 If access is granted, AuthorizationFilter continues with the FilterChain which allows the application to process normally.

We can configure Spring Security to have different rules by adding more rules in order of precedence.

	@Override
	public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain)
			throws ServletException, IOException {

		HttpServletRequest request = (HttpServletRequest) servletRequest;
		HttpServletResponse response = (HttpServletResponse) servletResponse;
		.....
		String alreadyFilteredAttributeName = getAlreadyFilteredAttributeName();
		request.setAttribute(alreadyFilteredAttributeName, Boolean.TRUE);
		try {
      // 取出认证信息,交给 authorizationManager 进行认证
			AuthorizationDecision decision = this.authorizationManager.check(this::getAuthentication, request);
			this.eventPublisher.publishAuthorizationEvent(this::getAuthentication, request, decision);
      // 认证失败,抛出异常
 			if (decision != null && !decision.isGranted()) {
				throw new AccessDeniedException("Access Denied");
			}
			chain.doFilter(request, response);
		}
		finally {
			request.removeAttribute(alreadyFilteredAttributeName);
		}
	}

Authorize Requests

@Bean
SecurityFilterChain web(HttpSecurity http) throws Exception {
	http
		// ...
		.authorizeHttpRequests(authorize -> authorize                                  
			.requestMatchers("/resources/**", "/signup", "/about").permitAll()         
			.requestMatchers("/admin/**").hasRole("ADMIN")                             
			.requestMatchers("/db/**").access(new WebExpressionAuthorizationManager("hasRole('ADMIN') and hasRole('DBA')"))   
			// .requestMatchers("/db/**").access(AuthorizationManagers.allOf(AuthorityAuthorizationManager.hasRole("ADMIN"), AuthorityAuthorizationManager.hasRole("DBA")))   
			.anyRequest().denyAll()                                                
		);

	return http.build();
}
  1. There are multiple authorization rules specified. Each rule is considered in the order they were declared.
  2. We specified multiple URL patterns that any user can access. Specifically, any user can access a request if the URL starts with “/resources/”, equals “/signup”, or equals “/about”.
  3. Any URL that starts with “/admin/” will be restricted to users who have the role “ROLE_ADMIN”. You will notice that since we are invoking the hasRole method we do not need to specify the “ROLE_” prefix.
  4. Any URL that starts with “/db/” requires the user to have both “ROLE_ADMIN” and “ROLE_DBA”. You will notice that since we are using the hasRole expression we do not need to specify the “ROLE_” prefix.
  5. The same rule from 4, could be written by combining multiple AuthorizationManager.
  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.

You can take a bean-based approach by constructing your own RequestMatcherDelegatingAuthorizationManager like so:

Configure RequestMatcherDelegatingAuthorizationManager

@Bean
SecurityFilterChain web(HttpSecurity http, AuthorizationManager<RequestAuthorizationContext> access)
        throws AuthenticationException {
    http
        .authorizeHttpRequests((authorize) -> authorize
            .anyRequest().access(access)
        )
        // ...

    return http.build();
}

@Bean
AuthorizationManager<RequestAuthorizationContext> requestMatcherAuthorizationManager(HandlerMappingIntrospector introspector) {
    MvcRequestMatcher.Builder mvcMatcherBuilder = new MvcRequestMatcher.Builder(introspector);
    RequestMatcher permitAll =
            new AndRequestMatcher(
                    mvcMatcherBuilder.pattern("/resources/**"),
                    mvcMatcherBuilder.pattern("/signup"),
                    mvcMatcherBuilder.pattern("/about"));
    RequestMatcher admin = mvcMatcherBuilder.pattern("/admin/**");
    RequestMatcher db = mvcMatcherBuilder.pattern("/db/**");
    RequestMatcher any = AnyRequestMatcher.INSTANCE;
    AuthorizationManager<HttpServletRequest> manager = RequestMatcherDelegatingAuthorizationManager.builder()
            .add(permitAll, (context) -> new AuthorizationDecision(true))
            .add(admin, AuthorityAuthorizationManager.hasRole("ADMIN"))
            .add(db, AuthorityAuthorizationManager.hasRole("DBA"))
            .add(any, new AuthenticatedAuthorizationManager())
            .build();
    return (context) -> manager.check(context.getRequest());
}

You can also wire your own custom authorization managers for any request matcher.

Here is an example of mapping a custom authorization manager to the my/authorized/endpoint:

Custom Authorization Manager

@Bean
SecurityFilterChain web(HttpSecurity http) throws Exception {
    http
        .authorizeHttpRequests((authorize) -> authorize
            .requestMatchers("/my/authorized/endpoint").access(new CustomAuthorizationManager());
        )
        // ...

    return http.build();
}

Or you can provide it for all requests as seen below:

Custom Authorization Manager for All Requests

@Bean
SecurityFilterChain web(HttpSecurity http) throws Exception {
    http
        .authorizeHttpRequests((authorize) -> authorize
            .anyRequest().access(new CustomAuthorizationManager());
        )
        // ...

    return http.build();
}

By default, the AuthorizationFilter applies to all dispatcher types. We can configure Spring Security to not apply the authorization rules to all dispatcher types by using the shouldFilterAllDispatcherTypes method:

Set shouldFilterAllDispatcherTypes to false

@Bean
SecurityFilterChain web(HttpSecurity http) throws Exception {
    http
        .authorizeHttpRequests((authorize) -> authorize
            .shouldFilterAllDispatcherTypes(false)
            .anyRequest().authenticated()
        )
        // ...

    return http.build();
}

Instead of setting shouldFilterAllDispatcherTypes to false, the recommended approach is to customize authorization on the dispatcher types. For example, you may want to grant all access on requests with dispatcher type ASYNC or FORWARD.

@Bean
SecurityFilterChain web(HttpSecurity http) throws Exception {
    http
        .authorizeHttpRequests((authorize) -> authorize
            .dispatcherTypeMatchers(DispatcherType.ASYNC, DispatcherType.FORWARD).permitAll()
            .anyRequest().authenticated()
        )
        // ...

    return http.build();
}

You can also customize it to require a specific role for a dispatcher type:

@Bean
SecurityFilterChain web(HttpSecurity http) throws Exception {
    http
        .authorizeHttpRequests((authorize) -> authorize
            .dispatcherTypeMatchers(DispatcherType.ERROR).hasRole("ADMIN")
            .anyRequest().authenticated()
        )
        // ...

    return http.build();
}

9. Request Matchers

The RequestMatcher interface is used to determine if a request matches a given rule. We use securityMatchers to determine if a given HttpSecurity should be applied to a given request. The same way, we can use requestMatchers to determine the authorization rules that we should apply to a given request. Look at the following example:

@Configuration
@EnableWebSecurity
public class SecurityConfig {

	@Bean
	public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
		http
			.securityMatcher("/api/**")                            
			.authorizeHttpRequests(authorize -> authorize
				.requestMatchers("/user/**").hasRole("USER")       
				.requestMatchers("/admin/**").hasRole("ADMIN")     
				.anyRequest().authenticated()                      
			)
			.formLogin(withDefaults());
		return http.build();
	}
}
  1. Configure HttpSecurity to only be applied to URLs that start with /api/
  2. Allow access to URLs that start with /user/ to users with the USER role
  3. Allow access to URLs that start with /admin/ to users with the ADMIN role
  4. Any other request that doesn’t match the rules above, will require authentication

The securityMatcher(s) and requestMatcher(s) methods will decide which RequestMatcher implementation fits best for your application: If Spring MVC is in the classpath, then MvcRequestMatcher will be used, otherwise, AntPathRequestMatcher will be used. You can read more about the Spring MVC integration here.

If you want to use a specific RequestMatcher, just pass an implementation to the securityMatcher and/or requestMatcher methods:

@Configuration
@EnableWebSecurity
public class SecurityConfig {

	@Bean
	public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
		http
			.securityMatcher(antMatcher("/api/**"))                              
			.authorizeHttpRequests(authorize -> authorize
				.requestMatchers(antMatcher("/user/**")).hasRole("USER")         
				.requestMatchers(regexMatcher("/admin/.*")).hasRole("ADMIN")     
				.requestMatchers(new MyCustomRequestMatcher()).hasRole("SUPERVISOR")     
				.anyRequest().authenticated()
			)
			.formLogin(withDefaults());
		return http.build();
	}
}

public class MyCustomRequestMatcher implements RequestMatcher {

    @Override
    public boolean matches(HttpServletRequest request) {
        // ...
    }
}
  1. Import the static factory methods from AntPathRequestMatcher and RegexRequestMatcher to create RequestMatcher instance.
  2. Configure HttpSecurity to only be applied to URLs that start with /api/, using AntPathRequestMatcher
  3. Allow access to URLs that start with /user/ to users with the USER role, using AntPathRequestMatcher
  4. Allow access to URLs that start with /admin/ to users with the ADMIN role, using RegexRequestMatcher
  5. Allow access to URLs that match the MyCustomRequestMatcher to users with the SUPERVISOR role, using a custom RequestMatcher
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值