社交媒體登錄Spring Social的源碼解析

2021-01-12 字母哥博客

在上一篇文章中我們給大家介紹了OAuth2授權標準,並且著重介紹了OAuth2的授權碼認證模式。目前絕大多數的社交媒體平臺,都是通過OAuth2授權碼認證模式對外開放接口(登錄認證及用戶信息接口等)。但是,我們也看到OAuth2有一定的複雜性,如果所有的代碼都由我們自己開發,還是有一定的工作量的。因此,我們完全可以使用Spring Social幫助我們,Spring Social對OAuth2標準進行了完整友好的封裝。本文就通過對Spring Social源碼進行一下解析,從而在我們後續開發第三方媒體平臺的登錄認證功能時,能更加的清晰。

一、Spring Social結構化角度解析源碼

Spring Social是一個幫助我們連接社交媒體平臺,方便在我們自己的應用上開發第三方登錄認證等功能的Spring 類庫。其中比較核心的類和接口,如下圖所示,我們來一一解析。

首先我們簡單回顧一下OAuth2,OAuth2主要包含兩部分內容:認證和鑑權。

認證過程就是通過用戶授權,獲取授權碼,最終換取AccessToken的過程。這個過程是標準的OAuth2認證流程,所有平臺都遵循,可以認為是一致的。

鑑權過程就是攜帶AccessToken訪問社交媒體平臺API接口。當然各平臺的用戶不同、業務不同,所以提供的的接口不一樣。

如果你對這部分內容,還不是很熟悉,先回看我的上一篇文章。請結合下面的這張圖理解後面的文字。

Spring Social結構化角度解析源碼總圖

1.1.OAuth2認證源碼

首先在實現OAuth2登錄認證的過程中,有多次我們自己開發的應用和社交媒體平臺之間的的請求和響應。所以我們需要封裝一個類用來處理標準的OAuth2認證專用的HTTP工具類,這個可以說是最重要的工作,Spring Security已經幫我們提供了OAuth2Operations接口,其默認的實現類是OAuth2Template,根據不同的平臺的實現差異我們可能會需要自己來實現(微調)。認證過程中所有與OAuth2認證伺服器交互的工作就全交給OAuth2Operations,最後返回給我們一個AccessToken。

圖片:OAuth2Template

對於開發者來說,只要將以上四個屬性的值告訴OAuth2Operations。只要服務提供商是嚴格按照OAuth2標準開發的認證服務,剩下的與認證伺服器交互的過程,我們就不需要處理了。

1.2.接口資源鑑權

當我們獲得了AccessToken之後,就有權限請求OAuth2資源伺服器裡面的資源了。各個社交媒體平臺根據用戶及業務不同提供的接口完全不同,這時我們需要用到RestTemplate,通用的HTTP工具類處理請求與響應。從圖中可以看到,處理各種數據格式JSON、XML的類庫,RestTemplate會自行根據環境判斷使用哪一個。

圖片:接口資源鑑權

那既然各個平臺的業務接口各不相同,我們當然要自定義開發不同的接口實現APIImpl。此時我們應該需要一個統一的父類,包含accessToken和RestTemplate,這樣我們的自定義接口實現就可以通過繼承這個類獲得並使用accessToken和RestTemplate。這個統一的父類叫做AbstractOAuth2Binding。它還幫助我們實現HTTP請求的參數攜帶,以及請求結果到對象的反序列化工作等。

圖片:AbstractOAuth2Binding

至此,OAuth2Operations 和 自定義接口實現APIImpl,一個負責認證流程請求響應,一個負責資源請求響應。二者統一被封裝為ServiceProvider-服務提供商。

圖片:ServiceProvider

1.3.確定用戶關係

通過實現上面的代碼中的接口,我們自己的應用與社交媒體平臺(服務提供商)的HTTP交互過程就已經可以被全部支持了。但是開發社交媒體登陸還有一個很重要的步驟就是:判定社交媒體平臺響應的用戶信息與我們自己的應用用戶之間的關係。我們用一張資料庫表來表示這個關係,而且必須是這張表(Spring Social專用,在spring-social-core包裡面可以找到):

create table UserConnection ( userId varchar(255) not null, providerId varchar(255) not null, providerUserId varchar(255), rank int not null, displayName varchar(255), profileUrl varchar(512), imageUrl varchar(512), accessToken varchar(512) not null, secret varchar(512), refreshToken varchar(512), expireTime bigint, primary key (userId, providerId, providerUserId));create unique index UserConnectionRank on UserConnection(userId, providerId, rank);

這張表中,最重要的三個欄位就是userId(自開發應用的用戶唯一標識),provider(服務提供商,社交媒體平臺唯一標識),providerUserId (服務提供商用戶的唯一標識)。通過這三個欄位體現自開發應用的用戶與服務提供商用戶之間的關係,從而判定服務提供商的用戶是否可以通過OAuth2認證登錄我們的應用。(這張表裡面的數據,是通過註冊或者綁定操作加入進去的,與認證、鑑權過程無關)

通過1.2小節中的接口,我們可以獲得社交媒體的用戶的數據User,但是我們說過了這個User在不同的服務提供商平臺上,其結構是完全不同的。而spring Social只認識一種用戶的數據結構,那就是Connection(OAuth2Connection)。所以我們需要一個ApiAdapter幫我們將二者進行適配。ApiAdapter是一個接口,內容需要我們自行實現。

現在我們拿到了Spring Social認可的服務提供商用戶信息Connection,然後使用Connection加載UserId(我們自己開發的平臺的userid)。如果能夠加載到userId(不為空),表示登錄驗證成功。

圖片:UserRepository

1.4.本地應用授權

通過實現上面代碼中的接口,我們就可以拿到userId,我們自己開發的應用的用戶的唯一標識。也表示利用社交媒體用戶登錄我們自己開發的應用成功了。但是,還有一個問題沒有解決,你是登陸成功了,但是不意味著你可以訪問本地應用中的所有資源。所以,我們根據userId查找當前用戶,並為他賦權。

在我們之前的使用用戶名密碼登陸的案例中,是通過實現UserDetailsService和UserDetails接口來實現的。在社交媒體登錄過程中,我們需要實現的接口是SocialUserDetailsService和SocialUserDetails。其實實現原理是一樣的,就是用用戶的唯一標識userId,加載該用戶角色的權限信息。至此,Spring Security就知道了該用戶的權限信息,可以有效的控制其訪問權限。

圖片:SocialUserDetailsService

二、Spring Social流程角度解析源碼

Spring Social自動配置會在過濾器鏈中加入一個SocialAuthenticationFilter過濾器,該過濾器攔截社交媒體登錄請求。

Spring Social流程角度解析源碼

SocialAuthenticationFilter過濾器攔截的社交媒體登錄請求的地址是{filterProcessesUrl}/{providerId}。filterProcessesUrl的默認值是「/auth」,如果你的服務提供商providerId(自定義)是github,那麼你的社交媒體登錄按鈕請求的地址就應該是「/auth/github」,當然這兩個值我們都可以修改。

圖片:SocialAuthenticationFilter

要說明的是{filterProcessesUrl}/{providerId}在Spring Social既是認證請求的地址,也是服務提供商回調的地址。當用戶點擊"github登錄"按鈕,此時訪問/{filterProcessesUrl}/{providerId}被攔截,此時用戶沒有被認證通過,所以跳轉到GitHub授權頁面(authorizeUrl)上,用戶輸入用戶密碼授權,在瀏覽器跳回到本地應用,仍然回到/{filterProcessesUrl}/{providerId}再次被攔截。

圖片:attemptAuthentication

首先要檢測用戶是否授權使用第三方平臺用戶信息,如果沒授權就直接拋出異常。如果用戶授權了,就去執行OAuth2一系列的請求響應,獲取授權碼、AccessToken、Connection用戶信息。這個過程代碼在OAuth2AuthenticationService中被定義。

圖片:getAuthToken

doAuthentication中授權過程,參考1.3、1.4小節內容。如果授權失敗(該社交平臺用戶在本地應用中沒有對應的用戶),則跳轉到signUpUrl。執行註冊即用戶關係綁定業務邏輯。

圖片:doAuthentication中授權過程

注意:Spring Social實現的OAuth2認證鑑權流程中,使用到了session(如上圖中的sessionStrategy代碼)。所以當你的應用是一個無狀態應用時,需要對Spring Social進行一定程度的改造。但是筆者從來沒這麼做過。簡單的做法就是:使用session開發有狀態應用,並且session保存的狀態信息交給redis集中管理;或者開發無狀態應用之前,確定該應用不需要社交媒體登錄功能,比如某企業內網應用。

通過zimug點靠m,更多精品合集知識等待你! 本號只做持續的知識輸出,希望您能關注、評論、轉發!您的支持是我不竭的創作動力!讓知識產生價值、讓程式設計師改變世界!

相關焦點

  • Spring-Task源碼解析
    this.registerBeanDefinitionParser("scheduler",newSchedulerBeanDefinitionParser());}schedulerSchedulerBeanDefinitionParser源碼
  • SpringSecurity 默認表單登錄頁展示流程源碼
    1.4 登錄在啟動項目的時候 控制臺會列印一個 seuciryt password : xxxUsing generated security password: f520875f-ea2b-4b5d-9b0c-f30c0c17b90b直接登錄用戶名:user 密碼 :f520875f-ea2b-4b5d-9b0c-f30c0c17b90b
  • 雙語——社交媒體之「齋戒」(A Social Media Fast)
    * 解析中英語單詞的音標使用Dictcom和IPA雙音標標註,如果需要了解Dictcom音標,請參看我們的《dictionary.com所用的音標體系》一文。齋戒;禁食Many people are social media fanatics.【譯】很多人都是社交媒體狂熱分子。【單詞】fanatics 原型:fanatic 名詞複數形式 [fuh-'nat-ik][f'ntk] n.
  • 上盤硬菜,@Transaction源碼深度解析 | Spring系列第48篇
    大家好,今天咱們通過源碼來了解一下spring中@Transaction事務的原理。開始本文之前,下面這些知識需提前了解下1、吃透Spring AOP2、Spring編程式事務源碼解析在這裡插播兩句,整個系列前後知識是有依賴的
  • Spring Core Container 源碼分析三:Spring Beans 初始化流程分析
    http://www.springframework.org/schema/beans/spring-beans.xsd"> <!解析並註冊 bean definitions 流程該部分參考新的博文 Spring Core Container 源碼分析七:註冊 Bean DefinitionsDo Get Bean 流程Do Get Bean 流程的入口是 AbstractBeanFactory#doGetBean 方法,主流程圖如下,
  • 深入理解-Spring-之源碼剖析IOC(一)
    spirng的 release  版本至今已經到了 5.0.3,和最初的 interface21 已經有了翻天復地的變化,現在也有了springboot, springcloud,儼然一個龐大的spring家族,想分析源碼的我們該從哪裡下手呢?萬劍歸宗,始於一處。
  • 雅思口語|Part3:Social media 社交媒體
    addictiveness 致癮性 The point about social media is the addictiveness.社交媒體的關鍵在於其致癮性 spend hours and hours
  • 你知道Spring是怎麼解析配置類的嗎?
    而我們在配置類上明明是可以對掃描的規則進行配置的,例如:@ComponentScan(value = "com.spring.study.springfx.aop.service", useDefaultFilters = true, excludeFilters = @ComponentScan.Filter(type
  • Spring Security 5.1.0.M2 發布,Spring 安全框架
    支持 WebClient 和 OAuth2現在內置了對 OAuth2 和 WebClient 的支持,該支持將允許:將訪問令牌添加到請求中訪問令牌過期時自動刷新解析要使用的訪問令牌例如,在 servlet 環境中,你可以配置一個如下所示的 Bean:
  • springboot+springsecurity實現前後端分離簡單實現!
    我這一次選擇比較反人性的方式去學習,就是手撕源碼和看官方文檔。老實講,剛開始看源碼和官方文檔特別難受,並且看不進去,那些springsecurity的類還有接口名字又臭又長,這時我就下載源碼,源碼的注釋多的就像一本書,非常詳細且權威。當然別指望看幾遍就能看懂,我看這些注釋、源碼、博客看了10幾遍甚至20幾遍才看懂,每次去看都有不同的收穫!!!
  • 海外社交媒體聆聽(social listening),我要聽什麼?
    很多中國企業開通海外社交媒體平臺渠道的最初動機,是為了「賣貨」,將之當作一個觸及海外消費者的渠道——這當然是海外社交媒體平臺對於企業很重要的一個作用,但如果只把它作為「賣貨」的渠道,就有點可惜了。怎麼去理解海外社交媒體平臺對於企業「賣貨」以外的作用呢?我們可以從社交媒體聆聽(social listening)說起。
  • 自定義標籤與解析 - Spring解密
    在 上一節 Spring解密 - 默認標籤的解析 中,重點分析了 Spring 對 默認標籤是如何解析的,那麼本章繼續講解標籤解析,著重講述如何對 自定義標籤進行解析。ApplicationBeanDefinitionParser),負責將組件註冊到 Spring 容器3.編寫 spring.handlers 和 spring.schemas 文件文件存放的目錄位於 resources/META-INF/文件名spring.handlers
  • 抖音解析網站源碼 抖音解析保存在哪裡
    抖音解析網站源碼有沒有呢,這是很多有這方面需求的小夥伴們都關心的問題。就讓小編帶大家了解抖音解析保存在哪裡吧~
  • 超全的springboot+springsecurity實現前後端分離簡單實現!
    我這一次選擇比較反人性的方式去學習,就是手撕源碼和看官方文檔。老實講,剛開始看源碼和官方文檔特別難受,並且看不進去,那些springsecurity的類還有接口名字又臭又長,這時我就下載源碼,源碼的注釋多的就像一本書,非常詳細且權威。  當然別指望看幾遍就能看懂,我看這些注釋、源碼、博客看了10幾遍甚至20幾遍才看懂,每次去看都有不同的收穫!!!
  • 流行語:社交變色龍 Social chameleon
    >   Social chameleon 社交變色龍   社交變色龍(Social chameleon)是指在社交場合慣於偽裝自己,將不良習慣隱藏而總是展示出風度翩翩的一面,而在交往中總是展示良好的習慣。
  • 開課吧雙十二教育節:助力學員輕鬆掌握Spring AOP源碼
    訓練營第一天以源碼解析為主,解析AOP底層實現的動態代理技術。畫圖加講解形式可以形象具體的解析AOP的核心概念及作用。在老師幫助學員掌握JDK和CGLib動態代理技術的使用後,當場進行源碼解析,為學員理清脈絡,剖析JDK及CGLib動態代理技術產生代理對象的過程。課程最後,老師對JDK和CGLib動態代理執行邏輯進行解析,以圖示形象地為學員理清本節課程的邏輯脈絡,做課程總結。第二天開始掌握實用設計開發的應用方法。
  • [Spring-Analysis] v0.0.8 BeanWrapper,Spring 源碼分析
    [Spring-Analysis] v0.0.8 BeanWrapperSpring-Analysis 是一個圍繞 springframework
  • Social media words 社交媒體用語 | 地道英語
    楊莉很生氣因為有些人在她的社交網頁上一味地發表負面評論。
  • Spring5.0源碼學習系列之Spring AOP簡述
    在學習Spring AOP源碼之前,您是否對AOP有足夠熟悉的理解?
  • 乾貨|新手也能看懂的源碼閱讀技巧
    >【原創】004 | 搭上 SpringBoot 事務詭異事件分析專車【原創】005 | 搭上 SpringBoot 請求處理源碼分析專車【原創】00 6| 搭上 SpringBoot 參數解析返回值處理源碼分析專車【原創】007 |