# 授权 HttpServletRequestwithAuthorizationFilter

本节通过深入研究授权在基于 Servlet 的应用程序中的工作方式,构建了Servlet Architecture and Implementation

AuthorizationFilter取代[FilterSecurityInterceptor](authorize-requests.html# Servlet-authorization-filtersecurityinterceptor)。
要保持向后兼容,FilterSecurityInterceptor仍然是默认值。
本节讨论AuthorizationFilter如何工作以及如何覆盖默认配置。

[AuthorizationFilter](https://DOCS. Spring.io/ Spring-security/site/DOCS/5.6.2/api/org/springframework/security/web/access/intercept/intercept/authorizationfilter.html)为HttpServletRequests 提供授权。它作为安全过滤器中的一个插入到FilterchainProxy中。

声明SecurityFilterChain时,可以重写默认值。不要使用[authorizeRequests](# Servlet-authorize-requests-defaults),而是使用authorizeHttpRequests,就像这样:

例 1。使用 AuthorizeHttpRequests

爪哇

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

    return http.build();
}

这在以下几个方面改进了authorizeRequests:

  1. 使用简化的AuthorizationManagerAPI,而不是元数据源、配置属性、决策管理器和投票者。这简化了重用和定制。

  2. 延迟Authentication查找。而不是需要为每个请求查找身份验证,它只会在授权决策需要身份验证的请求中查找。

  3. Bean-基于配置支持。

当使用authorizeHttpRequests而不是authorizeRequests时,则使用[AuthorizationFilter](https://DOCS. Spring.io/ Spring-security/site/DOCS/5.6.2/api/org/springframework/security/web/access/intercept/Authorizationfilter.html)代替[<<<requests.html>](authority-requests.html# Servlet-authority-filtersecurityptor)。

授权过滤器

图 1。授权 HttpServletRequest

  • number 1首先,AuthorizationFilterSecurityContextholder得到认证。它将此包在Supplier中,以延迟查找。

  • number 2秒,AuthorizationFilterHttpServletRequestFilterInvocation、<DOCS. Spring.io/ Spring-security/site/DOCS/5.6.2/api/org/springframework/security/web/filterinvocation.html)中创建一个[HttpServletRequestHttpServletResponseFilterChain

  • number 3接下来,它将Supplier<Authentication>FilterInvocation传递给[AuthorizationManager]。

    • number 4如果拒绝授权,将抛出AccessDeniedException。在这种情况下,[ExceptionTranslationFilter](../architecture.html# Servlet-ExceptionTranslationFilter)处理AccessDeniedException

    • number 5如果访问被授予,AuthorizationFilter继续使用滤清链,这允许应用程序正常处理。

通过按优先级顺序添加更多规则,我们可以将安全性配置为具有不同的规则。

例 2。授权请求

爪哇

@Bean
SecurityFilterChain web(HttpSecurity http) throws Exception {
	http
		// ...
		.authorizeHttpRequests(authorize -> authorize                                  (1)
			.mvcMatchers("/resources/**", "/signup", "/about").permitAll()         (2)
			.mvcMatchers("/admin/**").hasRole("ADMIN")                             (3)
			.mvcMatchers("/db/**").access("hasRole('ADMIN') and hasRole('DBA')")   (4)
			.anyRequest().denyAll()                                                (5)
		);

	return http.build();
}
1 指定了多个授权规则。
每个规则都按照它们被声明的顺序被考虑。
2 我们指定了任何用户都可以访问的多个 URL 模式。
具体来说,如果 URL 以“/resources/”开头,等于“/signup”或等于“/about”,则任何用户都可以访问请求。
3 任何以“/admin/”开头的 URL 都将被限制为具有角色“role_admin”的用户。
你将注意到,由于我们正在调用hasRole方法,因此我们不需要指定“role_”前缀。
4 任何以“/db/”开头的 URL 都要求用户同时具有“role_admin”和“role_DBA”。
你将注意到,由于我们使用的是hasRole表达式,因此我们不需要指定“role_”前缀。
5 任何尚未匹配的 URL 都将被拒绝访问。
如果你不想意外地忘记更新授权规则,这是一个很好的策略。

你可以通过构建自己的[RequestMatcherDelegatingAuthorizationManager](architecture.html#authz-delegate-authorization-manager)来采用基于 Bean 的方法,如下所示:

例 3。配置 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) {
    RequestMatcher permitAll =
            new AndRequestMatcher(
                    new MvcRequestMatcher(introspector, "/resources/**"),
                    new MvcRequestMatcher(introspector, "/signup"),
                    new MvcRequestMatcher(introspector, "/about"));
    RequestMatcher admin = new MvcRequestMatcher(introspector, "/admin/**");
    RequestMatcher db = new MvcRequestMatcher(introspector, "/db/**");
    RequestMatcher any = AnyRequestMatcher.INSTANCE;
    AuthorizationManager<HttpRequestServlet> 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());
}

你还可以为任何请求匹配器连接你自己的自定义授权管理器

下面是将自定义授权管理器映射到my/authorized/endpoint的示例:

例 4。自定义授权管理器

爪哇

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

    return http.build();
}

或者,你可以为所有请求提供它,如下所示:

例 5。所有请求的自定义授权管理器

爪哇

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

    return http.build();
}

授权体系结构使用 FilterSecurityInterceptor 授权 HTTP 请求