Spring Boot 快速集成第三方登錄功能
前言
此 demo 主要演示 Spring Boot 項目如何使用 史上最全的第三方登錄工具 - JustAuth 實現第三方登錄,包括 QQ 登錄、GitHub 登錄、微信登錄、谷歌登錄、微軟登錄、小米登錄、企業微信登錄。
通過 justauth-spring-boot-starter 快速集成,好嗨喲~
JustAuth,如你所見,它僅僅是一個第三方授權登錄的工具類庫,它可以讓我們脫離繁瑣的第三方登錄 SDK,讓登錄變得So easy!
- 全:已集成十多家第三方平臺(國內外常用的基本都已包含),後續依然還有擴展計劃!
- 簡:API 就是奔着最簡單去設計的(見後面
快速開始
),儘量讓您用起來沒有障礙感!PS: 本人十分幸運的參與到了這個 SDK 的開發,主要開發了 QQ 登錄、微信登錄、小米登錄、微軟登錄、谷歌登錄這
5
個第三方登錄,以及一些 BUG 的修復工作。再次感謝 @母狼 開源這個又好用又全面的第三方登錄 SDK。
如果技術選型是 JFinal
的,請查看此 demo
https://github.com/xkcoding/jfinal-justauth-demo
如果技術選型是 ActFramework
的,請查看此 demo
https://github.com/xkcoding/act-justauth-demo
1. 環境準備
1.1. 公網服務器準備
首先準備一臺有公網 IP 的服務器,可以選用阿里雲或者騰訊雲,如果選用的是阿里雲的,可以使用我的優惠鏈接購買。
1.2. 內網穿透 frp 搭建
frp 安裝程序:https://github.com/fatedier/frp/releases
1.2.1. frp 服務端搭建
服務端搭建在上一步準備的公網服務器上,因爲服務器是 centos7 x64 的系統,因此,這裏下載安裝包版本爲 linux_amd64 的 frp_0.27.0_linux_amd64.tar.gz 。
-
下載安裝包
複製1
$ wget https://github.com/fatedier/frp/releases/download/v0.27.0/frp_0.27.0_linux_amd64.tar.gz
-
解壓安裝包
複製1
$ tar -zxvf frp_0.27.0_linux_amd64.tar.gz
-
修改配置文件
複製1 2 3 4 5 6
$ cd frp_0.27.0_linux_amd64 $ vim frps.ini [common] bind_port = 7100 vhost_http_port = 7200
-
啓動 frp 服務端
複製1 2 3 4
$ ./frps -c frps.ini 2019/06/15 16:42:02 [I] [service.go:139] frps tcp listen on 0.0.0.0:7100 2019/06/15 16:42:02 [I] [service.go:181] http service listen on 0.0.0.0:7200 2019/06/15 16:42:02 [I] [root.go:204] Start frps success
1.2.2. frp 客戶端搭建
客戶端搭建在本地的 Mac 上,因此下載安裝包版本爲 darwin_amd64 的 frp_0.27.0_darwin_amd64.tar.gz 。
-
下載安裝包
複製1
$ wget https://github.com/fatedier/frp/releases/download/v0.27.0/frp_0.27.0_darwin_amd64.tar.gz
-
解壓安裝包
複製1
$ tar -zxvf frp_0.27.0_darwin_amd64.tar.gz
-
修改配置文件,配置服務端 ip 端口及監聽的域名信息
複製1 2 3 4 5 6 7 8 9 10 11
$ cd frp_0.27.0_darwin_amd64 $ vim frpc.ini [common] server_addr = 120.92.169.103 server_port = 7100 [web] type = http local_port = 8080 custom_domains = oauth.xkcoding.com
-
啓動 frp 客戶端
複製1 2 3 4
$ ./frpc -c frpc.ini 2019/06/15 16:48:52 [I] [service.go:221] login to server success, get run id [8bb83bae5c58afe6], server udp port [0] 2019/06/15 16:48:52 [I] [proxy_manager.go:137] [8bb83bae5c58afe6] proxy added: [web] 2019/06/15 16:48:52 [I] [control.go:144] [web] start proxy success
1.3. 配置域名解析
前往阿里雲 DNS 解析,將域名解析到我們的公網服務器上,比如我的就是將 oauth.xkcoding.com -> 120.92.169.103
1.4. nginx 代理
nginx 的搭建就不在此贅述了,只說配置
複製
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
server { listen 80; server_name oauth.xkcoding.com; location / { proxy_pass http://127.0.0.1:7200; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $http_host; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Real-IP $remote_addr; proxy_buffering off; sendfile off; proxy_max_temp_file_size 0; client_max_body_size 10m; client_body_buffer_size 128k; proxy_connect_timeout 90; proxy_send_timeout 90; proxy_read_timeout 90; proxy_temp_file_write_size 64k; proxy_http_version 1.1; proxy_request_buffering off; } } |
測試配置文件是否有問題
複製
1 2 3 |
$ nginx -t nginx: the configuration file /etc/nginx/nginx.conf syntax is ok nginx: configuration file /etc/nginx/nginx.conf test is successful |
重新加載配置文件,使其生效
複製
1 |
$ nginx -s reload |
現在當我們在瀏覽器輸入
oauth.xkcoding.com
的時候,網絡流量其實會經歷以下幾個步驟:
- 通過之前配的 DNS 域名解析會訪問到我們的公網服務器
120.92.169.103
的 80 端口- 再經過 nginx,代理到本地的 7200 端口
- 再經過 frp 穿透到我們的 Mac 電腦的 8080 端口
- 此時 8080 就是我們的應用程序端口
1.5. 第三方平臺申請
1.5.1. QQ 互聯平臺申請
1.5.2. GitHub 平臺申請
1.5.3 微信開放平臺申請
這裏微信開放平臺需要用企業的,個人沒有資質,所以我在某寶租了一個月的資質,需要的可以 戳我租賃
聲明:本人與該店鋪無利益相關,純屬個人覺得好用做分享
該店鋪有兩種方式:
- 店鋪支持幫你過企業資質,這裏就用你自己的開放平臺號就好了
- 臨時使用可以問店家租一個月進行開發,這裏租了之後,店家會把 AppID 和 AppSecret 的信息發給你,你提供回調域就好了
因此這裏我就貼出一張授權回調的地址作參考。
1.5.4. 谷歌開放平臺申請
-
前往 https://console.developers.google.com/projectcreate 創建項目
-
前往 https://console.developers.google.com/apis/credentials ,在第一步創建的項目下,添加應用
1.5.5. 微軟開放平臺申請
-
前往 https://portal.azure.com/#blade/Microsoft_AAD_RegisteredApps/ApplicationsListBlade 註冊應用
-
在註冊應用的時候就需要填寫回調地址,當然後期也可以重新修改
-
client id 在這裏
-
client secret 需要自己在這裏生成
1.5.6. 小米開放平臺申請
-
申請小米開發者,審覈通過
-
前往 https://dev.mi.com/passport/oauth2/applist 添加 oauth 應用,選擇
創建網頁應用
-
填寫基本信息之後,進入應用信息頁面填寫
回調地址
-
應用審覈通過之後,可以在應用信息頁面的
應用詳情
查看到 AppKey 和 AppSecret,吐槽下,小米應用的審覈速度特別慢,需要耐心等待。。。。
1.5.7. 企業微信平臺申請
參考:https://xkcoding.com/2019/08/06/use-justauth-integration-wechat-enterprise.html
2. 主要代碼
代碼地址:https://github.com/xkcoding/spring-boot-demo/tree/master/spring-boot-demo-social
2.1. pom.xml
複製
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 |
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <artifactId>spring-boot-demo-social</artifactId> <version>1.0.0-SNAPSHOT</version> <packaging>jar</packaging> <name>spring-boot-demo-social</name> <description>Demo project for Spring Boot</description> <parent> <groupId>com.xkcoding</groupId> <artifactId>spring-boot-demo</artifactId> <version>1.0.0-SNAPSHOT</version> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> <justauth-spring-boot.version>1.0.0</justauth-spring-boot.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <!-- 對象池,使用redis時必須引入 --> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-pool2</artifactId> </dependency> <!-- oauth工具類 --> <dependency> <groupId>com.xkcoding</groupId> <artifactId>justauth-spring-boot-starter</artifactId> <version>${justauth-spring-boot.version}</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> </dependency> <dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> </dependency> </dependencies> <build> <finalName>spring-boot-demo-social</finalName> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project> |
2.2. application.yml
複製
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
server: port: 8080 servlet: context-path: /demo spring: redis: host: localhost # 連接超時時間(記得添加單位,Duration) timeout: 10000ms # Redis默認情況下有16個分片,這裏配置具體使用的分片 # database: 0 lettuce: pool: # 連接池最大連接數(使用負值表示沒有限制) 默認 8 max-active: 8 # 連接池最大阻塞等待時間(使用負值表示沒有限制) 默認 -1 max-wait: -1ms # 連接池中的最大空閒連接 默認 8 max-idle: 8 # 連接池中的最小空閒連接 默認 0 min-idle: 0 cache: # 一般來說是不用配置的,Spring Cache 會根據依賴的包自行裝配 type: redis justauth: enabled: true type: qq: client-id: 10******85 client-secret: 1f7d************************d629e redirect-uri: http://oauth.xkcoding.com/demo/oauth/qq/callback github: client-id: 2d25******d5f01086 client-secret: 5a2919b************************d7871306d1 redirect-uri: http://oauth.xkcoding.com/demo/oauth/github/callback wechat: client-id: wxdcb******4ff4 client-secret: b4e9dc************************a08ed6d redirect-uri: http://oauth.xkcoding.com/demo/oauth/wechat/callback google: client-id: 716******17-6db******vh******ttj320i******userco******t.com client-secret: 9IBorn************7-E redirect-uri: http://oauth.xkcoding.com/demo/oauth/google/callback microsoft: client-id: 7bdce8******************e194ad76c1b client-secret: Iu0zZ4************************tl9PWan_. redirect-uri: https://oauth.xkcoding.com/demo/oauth/microsoft/callback mi: client-id: 288************2994 client-secret: nFeTt89************************== redirect-uri: http://oauth.xkcoding.com/demo/oauth/mi/callback wechat_enterprise: client-id: ww58******f3************fbc client-secret: 8G6PCr00j************************rgk************AyzaPc78 redirect-uri: http://oauth.xkcoding.com/demo/oauth/wechat_enterprise/callback agent-id: 1******2 |
2.3. OauthController.java
複製
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 |
/** * <p> * 第三方登錄 Controller * </p> * * @package: com.xkcoding.oauth.controller * @description: 第三方登錄 Controller * @author: yangkai.shen * @date: Created in 2019-05-17 10:07 * @copyright: Copyright (c) 2019 * @version: V1.0 * @modified: yangkai.shen */ @Slf4j @RestController @RequestMapping("/oauth") @RequiredArgsConstructor(onConstructor_ = @Autowired) public class OauthController { private final AuthRequestFactory factory; /** * 登錄類型 */ @GetMapping public Map<String, String> loginType() { List<String> oauthList = factory.oauthList(); return oauthList.stream().collect(Collectors.toMap(oauth -> oauth.toLowerCase() + "登錄", oauth -> "http://oauth.xkcoding.com/demo/oauth/login/" + oauth.toLowerCase())); } /** * 登錄 * * @param oauthType 第三方登錄類型 * @param response response * @throws IOException */ @RequestMapping("/login/{oauthType}") public void renderAuth(@PathVariable String oauthType, HttpServletResponse response) throws IOException { AuthRequest authRequest = factory.get(getAuthSource(oauthType)); response.sendRedirect(authRequest.authorize(oauthType + "::" + AuthStateUtils.createState())); } /** * 登錄成功後的回調 * * @param oauthType 第三方登錄類型 * @param callback 攜帶返回的信息 * @return 登錄成功後的信息 */ @RequestMapping("/{oauthType}/callback") public AuthResponse login(@PathVariable String oauthType, AuthCallback callback) { AuthRequest authRequest = factory.get(getAuthSource(oauthType)); AuthResponse response = authRequest.login(callback); log.info("【response】= {}", JSONUtil.toJsonStr(response)); return response; } private AuthSource getAuthSource(String type) { if (StrUtil.isNotBlank(type)) { return AuthSource.valueOf(type.toUpperCase()); } else { throw new RuntimeException("不支持的類型"); } } } |
2.4. 如果想要自定義 state 緩存
請看👉這裏
3. 運行方式
打開瀏覽器,輸入 http://oauth.xkcoding.com/demo/oauth ,點擊各個登錄方式自行測試。
Google 登錄,有可能因爲祖國的強大導致測試失敗,自行解決~
:kissing_smiling_eyes:
參考
- JustAuth 項目地址:https://github.com/justauth/JustAuth
- justauth-spring-boot-starter 地址:https://github.com/justauth/justauth-spring-boot-starter
- frp 內網穿透項目地址:https://github.com/fatedier/frp
- frp 內網穿透官方中文文檔:https://github.com/fatedier/frp/blob/master/README_zh.md
- Frp 實現內網穿透:https://zhuanlan.zhihu.com/p/45445979
- QQ 互聯文檔:http://wiki.connect.qq.com/%E5%87%86%E5%A4%87%E5%B7%A5%E4%BD%9C_oauth2-0
- 微信開放平臺文檔:https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&verify=1&id=open1419316505&token=&lang=zh_CN
- GitHub 第三方登錄文檔:https://developer.github.com/apps/building-oauth-apps/
- 谷歌 Oauth2 文檔:https://developers.google.com/identity/protocols/OpenIDConnect
- 微軟 Oauth2 文檔:https://docs.microsoft.com/zh-cn/graph/auth-v2-user
- 小米開放平臺賬號服務文檔:https://dev.mi.com/console/doc/detail?pId=707
------------- 本文結束 感謝您的閱讀 -------------