Spring Security OAuth Client配置加载源码分析

这篇具有很好参考价值的文章主要介绍了Spring Security OAuth Client配置加载源码分析。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

相关文章:

  1. OAuth2的定义和运行流程
  2. Spring Security OAuth实现Gitee快捷登录
  3. Spring Security OAuth实现GitHub快捷登录
  4. Spring Security的过滤器链机制

前言

这一节我们以前面默认的OAuth2 客户端集成为例,来了解下配置文件的加载,示例见第二、第三节。

源码分析

InMemoryClientRegistrationRepository

假如你没有看过相关视频,或者书,但想要自己分析源码,应该怎么分析?
在分析原理之前,我们一定要找到突破口,否则就会无从下手,突破口就是之前集成Gitee OAuth的配置文件,我们分析任何框架的源码都是如此,从表象到骨髓,一层层深入。

spring:
  security:
    oauth2:
      client:
        registration:
          gitee:
            client-id: gitee-client-id
            client-secret: gitee-client-secret
            authorization-grant-type: authorization_code
            redirect-uri: '{baseUrl}/login/oauth2/code/{registrationId}'
            client-name: Gitee
          github:
            client-id: b4713d47174917b34c28
            client-secret: 898389369c2e9f3d1d0ff4543ba1d9b45adfd093
        provider:
          gitee:
            authorization-uri: https://gitee.com/oauth/authorize
            token-uri: https://gitee.com/oauth/token
            user-info-uri: https://gitee.com/api/v5/user
            user-name-attribute: name

我们点进去,内部就是一个OAuth2ClientProperties类,这个类配置了@ConfigurationProperties 注解用来加载配置文件,用IDE查找一下该类用在了哪些地方,出来很多类,在这种没法一下判断的情况下,我的办法就是一个个进去看,判断哪个类最有可能,Reactive开头的类都是在响应式环境下使用的,都可以忽略。

Spring Security OAuth Client配置加载源码分析

这里OAuth2ClientRegistrationRepositoryConfiguration就是我们要找的类,在该类中会加载一个InMemoryClientRegistrationRepositoryBean,该Bean用于本地存储客户端注册信息的。

@Configuration(proxyBeanMethods = false)
@EnableConfigurationProperties(OAuth2ClientProperties.class)
@Conditional(ClientsConfiguredCondition.class)
class OAuth2ClientRegistrationRepositoryConfiguration {

	@Bean
	@ConditionalOnMissingBean(ClientRegistrationRepository.class)
	InMemoryClientRegistrationRepository clientRegistrationRepository(OAuth2ClientProperties properties) {
		List<ClientRegistration> registrations = new ArrayList<>(
				OAuth2ClientPropertiesRegistrationAdapter.getClientRegistrations(properties).values());
		return new InMemoryClientRegistrationRepository(registrations);
	}

}

这里有如下几个配置:

  • @Configuration(proxyBeanMethods = false):使用@Bean时候的配置,proxyBeanMethods表示是否使用代理来获取bean,这里表示不使用代理获取,这样配置能够提高Spring 的加载速度。

  • @EnableConfigurationProperties:开启OAuth2ClientPropertiesSpring Bean

  • @Conditional(ClientsConfiguredCondition.class): 只有在存在ClientsConfiguredConditionBean的时候,才注册该类

InMemoryClientRegistrationRepositoryBean只有在ClientRegistrationRepository不存在的时候才会加载。
该Bean的流程是从OAuth2ClientProperties配置中获取OAuth客户端信息,构建ClientRegistration对象,并存储在InMemoryClientRegistrationRepository中。
这个类看似好像到这里就完了,线索断了吗,其实没有,OAuth客户端配置的加载确实是完成了,那后面其他类肯定会使用到该配置类,这个后面在看,别忘记我们的问题。

回到OAuth2ClientRegistrationRepositoryConfiguration所在的目录,你会发现该目录下还有两个文件OAuth2ClientAutoConfigurationOAuth2WebSecurityConfiguration,
看下OAuth2ClientAutoConfiguration类,原来OAuth2ClientRegistrationRepositoryConfiguration也是由它引导加载的,那么我们看下另外一个类。

OAuth2WebSecurityConfiguration

OAuth2WebSecurityConfiguration类中,注册了InMemoryOAuth2AuthorizedClientServiceOAuth2AuthorizedClientRepositorySecurityFilterChain

(1)InMemoryOAuth2AuthorizedClientService是OAuth2AuthorizedClientService的实现,用于本地保存OAuth2授权客户端,具有保存已认证的授权客户端(saveAuthorizedClient)、移除已认证的授权客户端(removeAuthorizedClient)和获取已认证的授权客户端(loadAuthorizedClient)3个功能。

在该类中,你会发现保存了ClientRegistrationRepository对象,并且loadAuthorizedClient 和 removeAuthorizedClient 的时候,都会调用ClientRegistrationRepository中的findByRegistrationId方法,至此又跟前面加载的InMemoryClientRegistrationRepository联系在了一起。

(2)AuthenticatedPrincipalOAuth2AuthorizedClientRepository是OAuth2AuthorizedClientRepository的实现,用于维护principal主体(理解为已认证的用户)与授权客户端OAuth2AuthorizedClient的关系,并且提供了一个匿名的处理,如果是匿名使用HttpSessionOAuth2AuthorizedClientRepository处理(也可覆盖提供)。

该类提供了loadAuthorizedClient、saveAuthorizedClient、removeAuthorizedClient、setAnonymousAuthorizedClientRepository 几个公开方法

(3)SecurityFilterChain:一个过滤器链,用来匹配请求,匹配的请求将执行一系列过滤器。

@Bean
SecurityFilterChain oauth2SecurityFilterChain(HttpSecurity http) throws Exception {
    http.authorizeRequests((requests) -> requests.anyRequest().authenticated());
    http.oauth2Login(Customizer.withDefaults());
    http.oauth2Client();
    return http.build();
}

代码可见,内部使用HttpSecurity构建了一个默认的SecurityFilterChain,表明任何请求都可以使用该过滤器链,使用oauth2提供的默认登录方式(提供一个/login的默认登录页面),再最后http.build()用于构建一个SecurityFilterChain,看看此处代码。
http.build(),build()位于HttpSecurity的父类AbstractSecurityBuilder

public final O build() throws Exception {
    if (this.building.compareAndSet(false, true)) {
        this.object = doBuild();
        return this.object;
    }
    throw new AlreadyBuiltException("This object has already been built");
}

build()使用了CAS来保证构建的对象只会构建一次,我们主要看doBuild(),其是一个抽象方法,用于子类去实现具体的构建逻辑,该子类是AbstractConfiguredSecurityBuilder。

protected final O doBuild() throws Exception {
    synchronized (this.configurers) {
        //标记构建状态
        this.buildState = BuildState.INITIALIZING;
        //加载配置前的处理,默认空实现,子类可以覆盖实现
        beforeInit();
        //加载配置
        init();
        //修改构建状态
        this.buildState = BuildState.CONFIGURING;
        //在开始配置之前的处理
        beforeConfigure();
        //开始配置,调用实现了SecurityConfigurer的configure()
        //在这里会将各种内置的过滤器添加到HttpSecurity中
        configure();
        this.buildState = BuildState.BUILDING;
        //开始构建要返回的对象,抽象返回,子类实现构建逻辑
        O result = performBuild();
        this.buildState = BuildState.BUILT;
        return result;
    }
}

HttpSecurity的构建逻辑如下:

protected DefaultSecurityFilterChain performBuild() {
    ExpressionUrlAuthorizationConfigurer<?> expressionConfigurer = getConfigurer(
        ExpressionUrlAuthorizationConfigurer.class);
    AuthorizeHttpRequestsConfigurer<?> httpConfigurer = getConfigurer(AuthorizeHttpRequestsConfigurer.class);
    boolean oneConfigurerPresent = expressionConfigurer == null ^ httpConfigurer == null;
    Assert.state((expressionConfigurer == null && httpConfigurer == null) || oneConfigurerPresent,
                 "authorizeHttpRequests cannot be used in conjunction with authorizeRequests. Please select just one.");
    this.filters.sort(OrderComparator.INSTANCE);
    List<Filter> sortedFilters = new ArrayList<>(this.filters.size());
    for (Filter filter : this.filters) {
        sortedFilters.add(((OrderedFilter) filter).filter);
    }
    return new DefaultSecurityFilterChain(this.requestMatcher, sortedFilters);
}

此处先判断是否同时加载了ExpressionUrlAuthorizationConfigurer(基于SpEL的URL授权)和AuthorizeHttpRequestsConfigurer(使用AuthorizationManager添加基于 URL 的授权,该类是5.5新增),这两个不能同时使用。
然后再对加载的过滤器进行Order排序,最后生成DefaultSecurityFilterChain对象返回。
我们可以看下此处filters的值,发现已经加载了18个filter,如下,其中OAuth2开头的几个过滤器特别显眼。

DisableEncodeUrlFilter
WebAsyncManagerIntegrationFilter
SecurityContextPersistenceFilter
HeaderWriterFilter
CsrfFilter
LogoutFilter
OAuth2AuthorizationRequestRedirectFilter
OAuth2AuthorizationRequestRedirectFilter
OAuth2LoginAuthenticationFilter
DefaultLoginPageGeneratingFilter
DefaultLogoutPageGeneratingFilter
RequestCacheAwareFilter
SecurityContextHolderAwareRequestFilter
AnonymousAuthenticationFilter
OAuth2AuthorizationCodeGrantFilter
SessionManagementFilter
ExceptionTranslationFilter
FilterSecurityInterceptor

到这里,Spring Security OAuth2 的默认配置已经加载完了,这里描述内容只是我们表象能看到的,其实还有其他的内容,比如HttpSecurity等还有很多。

后面我们将深入分析这18个过滤器都干了哪些事。

总结

要学习一个新框架,我一般会按照如下步骤来实施:
(1)根据官方文档搭建Demo,先跑起来,有一个整体观
(2)分析源码,从Demo的功能配置入手,找到突破口
(3)每次分析源码,要带着问题看
(4)根据源码分析出来的思路,画架构图、流程图
(5)学习框架的实现思路,取其精华去其糟粕

参考博主:码农小胖哥的2022版PDF文章来源地址https://www.toymoban.com/news/detail-479327.html

到了这里,关于Spring Security OAuth Client配置加载源码分析的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Spring Security OAuth2.0(3):Spring Security简单入门

    Spring Security 快速入门。 本章代码已分享至Gitee:https://gitee.com/lengcz/security-spring-security qquad Spring Secutiry 是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架。由于它是Spring生态系统的一员,因此它伴随着整个Spring生态系统不断修正、升级,

    2024年02月13日
    浏览(48)
  • Spring Security OAuth 2.0

    1 概念 OAuth 2.0 到底是什么呢?我们先从字面上来分析下。OAuth 2.0 一词中的字母 “O” 是 Open 的简称,表示 “开放” , “Auth” 表示 “授权”,连在一起就表示 “开放授权”。 OAuth 2.0是一种授权框架,提供了一套规范和协议,用于实现授权流程和访问令牌的管理,而非单个

    2024年02月16日
    浏览(48)
  • Spring Security OAuth2详解

    spring security oauth2框架即spring security + OAuth2,spring security上一篇文章已经讲过,接下来讲讲OAuth2,它是行业标准的授权协议,旨在为开发人员提供简单易用的授权流程;OAuth 定义了四种角色: 资源所有者:能够授予对受保护资源的访问权限的实体,当资源所有者是一个人时,

    2024年02月03日
    浏览(36)
  • Spring Security OAuth2.0 - 学习笔记

    OAuth2.0是一个开放标准,允许用户授权第三方应用程序访问他们存储在另外的服务提供者上的信息,而不需要将用户和密码提供给第三方应用或分享数据的所有内容。 1)授权码模式 2)简化模式 3)密码模式 4)客户端模式 普通令牌只是一个随机的字符串,没有特殊的意义,

    2024年02月16日
    浏览(46)
  • Spring Security OAuth2 远程命令执行漏洞

    cd vulhub/spring/CVE-2016-4977/ docker-compose up -d 访问 http://192.168.10.171:8080/oauth/authorize?response_type=${233*233}client_id=acmescope=openidredirect_uri=http://test 用admin:admin登陆 出现以下报错,表示漏洞存在(response_type里面的命令执行了) poc.py #!/usr/bin/env python message = input(‘Enter message to encode:’) p

    2024年02月09日
    浏览(37)
  • 微服务安全Spring Security Oauth2实战

    Spring Authorization Server 是一个框架,它提供了 OAuth 2.1 和 OpenID Connect 1.0 规范以及其他相关规范的实现。它建立在 Spring Security 之上,为构建 OpenID Connect 1.0 身份提供者和 OAuth2 授权服务器产品提供了一个安全、轻量级和可定制的基础。说白了,Spring Authorization Server 就是一个**认

    2024年02月03日
    浏览(36)
  • Spring Security与OAuth2的完美结合

    OAuth2是一种流行的授权框架,它允许用户授权第三方应用程序访问他们的资源。Spring Security是一个强大的安全框架,它提供了一系列的安全功能。本文将介绍如何将Spring Security与OAuth2整合,以实现更加安全和可靠的应用程序。 OAuth2的基本概念 OAuth2是一个授权框架,它允许用

    2024年02月05日
    浏览(40)
  • Spring Security实现OAuth2协议及实战

    文章篇幅较长,愿读者耐心看完。如有不足之处,请指正。 一.OAuth2介绍 1.1 OAuth2是什么 怎么用 OAuth2是目前最流行的授权协议,用来授权第三方应用,获取用户数据。 举个例子:快递员想要进入小区,有3种方式。1是业主远程开门,2是业主告诉门禁密码,3是使用令牌(Oaut

    2024年02月08日
    浏览(39)
  • Spring Security对接OIDC(OAuth2)外部认证

    前后端分离项目对接OIDC(OAuth2)外部认证,认证服务器可以使用Keycloak。 后端已有用户管理和权限管理,需要外部认证服务器的用户名和业务系统的用户名一致才可以登录。 后台基于Spring Boot 2.7 + Spring Security 流程: 前台浏览器跳转到  后台地址 + /login/oauth2/authorization/my-oid

    2024年02月21日
    浏览(41)
  • SpringCloud微服务整合Spring Security OAuth2

    首先得了解什么是OAuth2,这个的话可以参见博客: https://blog.csdn.net/weixin_42272869/article/details/112260123 https://www.bilibili.com/video/BV1D94y1Z7t1?p=33vd_source=bf9d70f3d2a451db07f40b6407c95a77 本文采用的是使用最广泛的、安全性最高的 授权码模式 进行讲解。 单独创建一个鉴权微服务auth,负责整个

    2024年02月09日
    浏览(50)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包