SpringSecurity系列——授权Http请求day4-2(源于官网5.7.2版本)

181 篇文章 3 订阅
24 篇文章 31 订阅

前言

源于官方最新5.7.2文档,若你觉得官方文档阅读起来很枯燥,内容复杂,我提供了解析概括在每个部分的结尾,我对官方文档的内容做了一些改变,实例代码我会在后续进行更新,请查看如:SpringSecurity系列——认证架构实例代码的文章

但是如果你有能力,还是推荐直接阅读官方文档

Authorize HttpServletRequests with AuthorizationFilter(使用 AuthorizationFilter 授权 HttpServletRequests)

AuthorizationFilter取代 FilterSecurityInterceptor. 为了保持向后兼容, FilterSecurityInterceptor保持默认。 本节讨论如何 AuthorizationFilter工作原理以及如何覆盖默认配置。

AuthorizationFilter 为 HttpServletRequests 提供授权。 它作为安全过滤器之一插入到 FilterChainProxy 中。

您可以在声明 SecurityFilterChain 时覆盖默认值。 不要使用 authorizeRequests,而是使用 authorizeHttpRequests,如下所示:

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

    return http.build();
}

这以多种方式改进了 authorizeRequests:

  1. 使用简化的 AuthorizationManager API,而不是元数据源、配置属性、决策管理器和选民。 这简化了重用和定制。
  2. 延迟身份验证查找。 而不是需要为每个请求查找身份验证,它只会在授权决策需要身份验证的请求中查找它。
  3. 基于 Bean 的配置支持。

当使用 authorizeHttpRequests 代替 authorizeRequests 时,则使用 AuthorizationFilter 代替 FilterSecurityInterceptor。
在这里插入图片描述

  1. 首先,AuthorizationFilter 从 SecurityContextHolder 获得一个 Authentication。 它将其包装在供应商中以延迟查找。
  2. 其次,AuthorizationFilter 从 HttpServletRequest、HttpServletResponse 和 FilterChain 创建一个 FilterInvocation。
  3. 接下来,它将 Supplier<Authentication> 和 FilterInvocation 传递给 AuthorizationManager。
    4. 如果授权被拒绝,则抛出 AccessDeniedException。 在这种情况下,ExceptionTranslationFilter 处理 AccessDeniedException。
    5. 如果授予访问权限,AuthorizationFilter 继续使用允许应用程序正常处理的 FilterChain。

我们可以通过按优先顺序添加更多规则来配置 Spring Security 以具有不同的规则。

//授权请求
@Bean
SecurityFilterChain web(HttpSecurity http) throws Exception {
	http
		// ...
		//指定了多个授权规则。  每个规则都按照它们被声明的顺序来考虑。
		.authorizeHttpRequests(authorize -> authorize
		// 我们指定了任何用户都可以访问的多个 URL 模式。  具体来说,如果 URL 以“/resources/”开头、等于“/signup”或等于“/about”,则任何用户都可以访问请求。
			.mvcMatchers("/resources/**", "/signup", "/about").permitAll()
			//任何以“/admin/”开头的 URL 都将被限制为具有“ROLE_ADMIN”角色的用户。  您会注意到,由于我们正在调用 hasRole 方法,因此我们不需要指定“ROLE_”前缀。
			.mvcMatchers("/admin/**").hasRole("ADMIN")
			// 任何以“/db/”开头的 URL 都要求用户同时拥有“ROLE_ADMIN”和“ROLE_DBA”。  您会注意到,由于我们使用了 hasRole 表达式,我们不需要指定“ROLE_”前缀。
			.mvcMatchers("/db/**").access((authentication, request) ->
			    Optional.of(hasRole("ADMIN").check(authentication, request))
			        .filter((decision) -> !decision.isGranted())
			        .orElseGet(() -> hasRole("DBA").check(authentication, request));
			)
			// 任何尚未匹配的 URL 都将被拒绝访问。  如果您不想意外忘记更新授权规则,这是一个很好的策略。
			.anyRequest().denyAll()
		);

	return http.build();
}

您可以通过构建自己的 RequestMatcherDelegatingAuthorizationManager 来采用基于 bean 的方法,如下所示:

@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 的示例:

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

    return http.build();
}

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

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

    return http.build();
}

默认情况下,AuthorizationFilter 不适用于 DispatcherType.ERROR 和 DispatcherType.ASYNC。 我们可以使用 shouldFilterAllDispatcherTypes 方法配置 Spring Security 以将授权规则应用于所有调度程序类型:

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

    return http.build();
}

解释概括

  1. AuthorizationFilter取代 FilterSecurityInterceptor
  2. AuthorizationFilter 为 HttpServletRequests 提供授权
  3. 我们需要在使用SecurityFilterChain 时覆盖默认值。 使用 authorizeHttpRequests
  4. 我们可以自定义多种策略对授权自定义
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值