OAuth2 集成社交網(wǎng)站登錄
1. 前言
上一節(jié)我們介紹了「密碼認(rèn)證」的實(shí)現(xiàn)方法,本節(jié)我們討論如何通過(guò) OAuth2.0 方式直接從第三方機(jī)構(gòu)獲取用戶身份信息的方法。
OAuth(開(kāi)放授權(quán))是一個(gè)開(kāi)放標(biāo)準(zhǔn),允許用戶授權(quán)第三方移動(dòng)應(yīng)用訪問(wèn)他們存儲(chǔ)在另外的服務(wù)提供者上的信息,而不需要將用戶名和密碼提供給第三方移動(dòng)應(yīng)用或分享他們數(shù)據(jù)的所有內(nèi)容,OAuth2.0 是 OAuth 協(xié)議的延續(xù)版本,但不向后兼容 OAuth1.0 即完全廢止了 OAuth1.0。
除了自建認(rèn)證中心外,常用的互聯(lián)網(wǎng) OAuth2.0 認(rèn)證中心還包括:QQ、微信、微博、Github 等,例如 imooc.com 的登錄選項(xiàng)里,我們能看到「微博登錄」、「微信登錄」和「QQ 登錄」,這些其實(shí)就是對(duì) OAuth2.0 認(rèn)證的應(yīng)用。
本節(jié)將以 Github 作為第三方認(rèn)證中心為例,討論如何使用 Spring security 實(shí)現(xiàn) OAuth2 登錄的功能。
本節(jié)開(kāi)發(fā)環(huán)境
- JDK 1.8
- Maven 3.5.3
- 依賴項(xiàng):
- spring-security-config:5.3.2.RELEASE
- spring-security-oauth2-client:5.3.2.RELEASE
- spring-security-oauth2-jose:5.3.2.RELEASE
- spring-boot-starter-thymeleaf:2.3.0.RELEASE
- spring-boot-starter-web:2.3.0.RELEASE
- thymeleaf-extras-springsecurity5:3.0.4.RELEASE
2. 過(guò)程概述
3. 過(guò)程實(shí)現(xiàn)
3.1 在 Github 上注冊(cè)應(yīng)用
要實(shí)現(xiàn) OAuth2.0 認(rèn)證,第一步要將自己的應(yīng)用注冊(cè)到 Github 管理中心。這里需要提前準(zhǔn)備以下信
- 一個(gè)可用的 Github 賬號(hào);
- 應(yīng)用名稱,本例中將使用:spring-security-demo-1-oauth2-client ;
- 應(yīng)用的主頁(yè),本例中將使用:http://localhost:8080/ ;
- 應(yīng)用描述信息(非必填);
- 認(rèn)證回調(diào)地址,本例中將使用:http://localhost:8080/login/oauth2/code/github 。
準(zhǔn)備好信息后,訪問(wèn) Github 的 Register a new OAuth application,填寫(xiě)好信息后提交,在提交成功后將得到如下反饋?lái)?yè)面,記錄下「Client ID」和「Client Secret」兩個(gè)值。如下圖:
3.2 構(gòu)建 OAuth2.0 客戶端
3.2.1 創(chuàng)建 Maven 項(xiàng)目
創(chuàng)建 Maven 項(xiàng)目,本例中 Group ID 為 imooc.tonglei0429.springsecurity
,Artifact ID 為 login.oauth2.github
在控制臺(tái)輸入以下命令:
mvn archetype:generate \
-DgroupId=imooc.tonglei0429.springsecurity \
-DartifactId=login.oauth2.github \
-DarchetypeArtifactId=maven-archetype-quickstart \
-DinteractiveMode=false
等待執(zhí)行完畢后,執(zhí)行目錄下會(huì)自動(dòng)生成名為 login.oauth2.github
的目錄,包含完整的 Maven 項(xiàng)目結(jié)構(gòu)。
3.2.2 添加相關(guān)依賴
打開(kāi) login.oauth2.github/pom.xml 文件,在其中添加以下依賴項(xiàng):
<!-- Spring Security 框架的配置模塊 -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>5.3.2.RELEASE</version>
</dependency>
<!-- Spring Security OAuth2 認(rèn)證客戶端模塊 -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-oauth2-client</artifactId>
<version>5.3.2.RELEASE</version>
</dependency>
<!-- Spring Security OAuth2 授權(quán)信息加密模塊 -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-oauth2-jose</artifactId>
<version>5.3.2.RELEASE</version>
</dependency>
<!-- Spring Boot thymeleaf 啟動(dòng)模塊,用于 Web 服務(wù)中的頁(yè)面模板 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
<version>2.3.0.RELEASE</version>
</dependency>
<!-- Spring Boot thymeleaf 啟動(dòng)模塊,用于啟動(dòng) Web 服務(wù) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.3.0.RELEASE</version>
</dependency>
<!-- Spring Boot thymeleaf 啟動(dòng)模塊,包含適用于 Thymeleaf 的 Spring Security 擴(kuò)展 -->
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity5</artifactId>
<version>3.0.4.RELEASE</version>
</dependency>
添加完以上內(nèi)容后,保持文件。
在命令行中輸入 mvn compile
測(cè)試依賴是否添加成功。
3.2.3 創(chuàng)建 Web 項(xiàng)目
創(chuàng)建 src/main/resources
目錄,增加配置文件 application.yml
,并添加如下配置:
server:
port: 8080
spring:
thymeleaf:
cache: false
修改 src/main/java/imooc/tonglei0429/springsecurity/App.java
,使其作為 Spring Boot 項(xiàng)目啟動(dòng)。
@SpringBootApplication
public class App
{
public static void main( String[] args )
{
SpringApplication.run(App.class, args);
}
}
創(chuàng)建 src/main/resources/templates/index.html
頁(yè),用于展示測(cè)試結(jié)果,index.html 文件內(nèi)容如下:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="https://www.thymeleaf.org" xmlns:sec="https://www.thymeleaf.org/thymeleaf-extras-springsecurity5">
<head>
<title>OAuth2 登錄測(cè)試</title>
<meta charset="utf-8" />
</head>
<body>
<div style="float: right" th:fragment="logout" sec:authorize="isAuthenticated()">
<div style="float:left">
<span style="font-weight:bold">User: </span><span sec:authentication="name"></span>
</div>
<div style="float:none"> </div>
<div style="float:right">
<form action="#" th:action="@{/logout}" method="post">
<input type="submit" value="Logout" />
</form>
</div>
</div>
<h1>Spring Security 示例:使用 OAuth2.0 + Github 實(shí)現(xiàn)用戶認(rèn)證</h1>
<div>
您已成功登錄,當(dāng)前用戶 ID 為: <span style="font-weight:bold" th:text="${userName}"></span>
所屬的客戶端名稱為: <span style="font-weight:bold" th:text="${clientName}"></span>
</div>
<div> </div>
<div>
<span style="font-weight:bold">返回的用戶屬性:</span>
<ul>
<li th:each="userAttribute : ${userAttributes}">
<span style="font-weight:bold" th:text="${userAttribute.key}"></span>: <span th:text="${userAttribute.value}"></span>
</li>
</ul>
</div>
</body>
</html>
為了使 http://localhost:8080/springsecurity/
可以訪問(wèn),還需要配置該路徑的控制器,src/main/java/imooc/tonglei0429/springsecurity/web/OAuth2LoginController.java
,其代碼如下:
@Controller
public class OAuth2LoginController {
@GetMapping("/")
public String index(Model model,
@RegisteredOAuth2AuthorizedClient OAuth2AuthorizedClient authorizedClient,
@AuthenticationPrincipal OAuth2User oauth2User) {
model.addAttribute("userName", oauth2User.getName());
model.addAttribute("clientName", authorizedClient.getClientRegistration().getClientName());
model.addAttribute("userAttributes", oauth2User.getAttributes());
return "index";
}
}
此時(shí)如果運(yùn)行項(xiàng)目,訪問(wèn) localhost:8080/springsecurity
,系統(tǒng)會(huì)默認(rèn)跳轉(zhuǎn)到 localhost:8080/login
要求登錄,我們需要繼續(xù)將認(rèn)證源指向 Github。
3.2.4 配置 OAuth2 認(rèn)證服務(wù)器
繼續(xù)配置 application.yml
文件,添加配置項(xiàng) security.oauth2.client.registration.github.client-id
和 security.oauth2.client.registration.github.client-secret
兩項(xiàng),其值來(lái)自于 Github 上注冊(cè)應(yīng)用后的返回頁(yè)面。具體代碼如下:
spring:
thymeleaf:
cache: false
security:
oauth2:
client:
registration:
github:
client-id: 300c4622cd932acad32a
client-secret: 71cb7971c2260f84c7b59693fbcf97b9c118c638
3.3 啟動(dòng)及測(cè)試
在命令行輸入啟動(dòng)命令 mvn spring-boot:run
。待程序啟動(dòng)完畢后,打開(kāi)瀏覽器訪問(wèn) http://localhost:8080
,將看到以下頁(yè)面:
點(diǎn)擊「Authorize tonglei0429」按鈕,瀏覽器將跳轉(zhuǎn)到過(guò)渡頁(yè)面,如下所示:
最后顯示登錄結(jié)果頁(yè),頁(yè)面內(nèi)容也就是我們?cè)?src/main/resources/templates/index.html
中所編輯的模板一樣,可以看到從 Github 網(wǎng)站返回的一系列用戶信息。效果如下:
4. 小結(jié)
本節(jié)我們討論了如何利用第三方平臺(tái)做我們系統(tǒng)的 OAuth2.0 認(rèn)證中心,主要的知識(shí)點(diǎn)如下:
- Spring Security 實(shí)現(xiàn)了 OAuth2.0 客戶端的常用功能,開(kāi)發(fā)者可以輕松的將 Spring Boot 應(yīng)用作為 OAuth2.0 客戶端集成到安全體系中;
- 在使用第三方作為 OAuth2.0 認(rèn)證服務(wù)器時(shí),首先要在第三方平臺(tái)上完成應(yīng)用注冊(cè),并獲取到 Client ID 和 Client Secret 兩個(gè)重要參數(shù);
- 使用第三方 OAuth2.0 認(rèn)證源,可以簡(jiǎn)化系統(tǒng)開(kāi)發(fā)中的關(guān)于認(rèn)證的操作,并且可以更輕易的實(shí)現(xiàn)單點(diǎn)登錄;
- 使用第三方 OAuth2.0 認(rèn)證源的時(shí)候,用戶在本系統(tǒng)內(nèi)的權(quán)限、詳細(xì)用戶信息等,仍需要在本地系統(tǒng)內(nèi)維護(hù);
- 目前在國(guó)內(nèi)支持度比較好的第三方認(rèn)證源有:QQ、微信、微博、Github 等。
下一節(jié)中,我們繼續(xù)在 OAuth2.0 協(xié)議的基礎(chǔ)上,構(gòu)造出屬于自己的認(rèn)證中心。