# spring-boot-demo-social > 此 demo 主要演示 Spring Boot 项目如何使用 **[史上最全的第三方登录工具 - JustAuth](https://github.com/zhangyd-c/JustAuth)** 实现第三方登录,包括QQ登录、GitHub登录、微信登录、谷歌登录、微软登录、小米登录、企业微信登录。 > > 通过 [justauth-spring-boot-starter](https://search.maven.org/artifact/com.xkcoding/justauth-spring-boot-starter) 快速集成,好嗨哟~ > > JustAuth,如你所见,它仅仅是一个**第三方授权登录**的**工具类库**,它可以让我们脱离繁琐的第三方登录SDK,让登录变得**So easy!** > > 1. **全**:已集成十多家第三方平台(国内外常用的基本都已包含),后续依然还有扩展计划! >2. **简**:API就是奔着最简单去设计的(见后面[`快速开始`](https://github.com/zhangyd-c/JustAuth#%E5%BF%AB%E9%80%9F%E5%BC%80%E5%A7%8B)),尽量让您用起来没有障碍感! > >PS: 本人十分幸运的参与到了这个SDK的开发,主要开发了**QQ登录、微信登录、小米登录、微软登录、谷歌登录**这 **`5`** 个第三方登录,以及一些BUG的修复工作。再次感谢 [@母狼](https://github.com/zhangyd-c) 开源这个又好用又全面的第三方登录SDK。 如果技术选型是 `JFinal` 的,请查看此 [**`demo`**](https://github.com/xkcoding/jfinal-justauth-demo) https://github.com/xkcoding/jfinal-justauth-demo 如果技术选型是 `ActFramework` 的,请查看此 [**`demo`**](https://github.com/xkcoding/act-justauth-demo) https://github.com/xkcoding/act-justauth-demo ## 1. 环境准备 ### 1.1. 公网服务器准备 首先准备一台有公网IP的服务器,可以选用阿里云或者腾讯云,如果选用的是阿里云的,可以使用我的[优惠链接](https://chuangke.aliyun.com/invite?userCode=r8z5amhr)购买。 ### 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](https://github.com/fatedier/frp/releases/download/v0.27.0/frp_0.27.0_linux_amd64.tar.gz) 。 1. 下载安装包 ```shell $ wget https://github.com/fatedier/frp/releases/download/v0.27.0/frp_0.27.0_linux_amd64.tar.gz ``` 2. 解压安装包 ```shell $ tar -zxvf frp_0.27.0_linux_amd64.tar.gz ``` 3. 修改配置文件 ```shell $ cd frp_0.27.0_linux_amd64 $ vim frps.ini [common] bind_port = 7100 vhost_http_port = 7200 ``` 4. 启动frp服务端 ```shell $ ./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](https://github.com/fatedier/frp/releases/download/v0.27.0/frp_0.27.0_darwin_amd64.tar.gz) 。 1. 下载安装包 ```shell $ wget https://github.com/fatedier/frp/releases/download/v0.27.0/frp_0.27.0_darwin_amd64.tar.gz ``` 2. 解压安装包 ```shell $ tar -zxvf frp_0.27.0_darwin_amd64.tar.gz ``` 3. 修改配置文件,配置服务端ip端口及监听的域名信息 ```shell $ 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 ``` 4. 启动frp客户端 ```shell $ ./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` ![image-20190615165843639](http://static.xkcoding.com/spring-boot-demo/social/063923.jpg) ### 1.4. nginx代理 nginx 的搭建就不在此赘述了,只说配置 ```nginx 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; } } ``` 测试配置文件是否有问题 ```shell $ nginx -t nginx: the configuration file /etc/nginx/nginx.conf syntax is ok nginx: configuration file /etc/nginx/nginx.conf test is successful ``` 重新加载配置文件,使其生效 ```shell $ nginx -s reload ``` > 现在当我们在浏览器输入 `oauth.xkcoding.com` 的时候,网络流量其实会经历以下几个步骤: > > 1. 通过之前配的DNS域名解析会访问到我们的公网服务器 `120.92.169.103` 的 80 端口 > 2. 再经过 nginx,代理到本地的 7200 端口 > 3. 再经过 frp 穿透到我们的 Mac 电脑的 8080 端口 > 4. 此时 8080 就是我们的应用程序端口 ### 1.5. 第三方平台申请 #### 1.5.1. QQ互联平台申请 1. 前往 https://connect.qq.com/ 2. 申请开发者 3. 应用管理 -> 添加网站应用,等待审核通过即可 ![image-20190617144655429](http://static.xkcoding.com/spring-boot-demo/social/063921-1.jpg) #### 1.5.2. GitHub平台申请 1. 前往 https://github.com/settings/developers 2. 点击 `New OAuth App` 按钮创建应用 ![image-20190617145839851](http://static.xkcoding.com/spring-boot-demo/social/063919.jpg) #### 1.5.3 微信开放平台申请 这里微信开放平台需要用企业的,个人没有资质,所以我在某宝租了一个月的资质,需要的可以 [戳我租赁](https://item.taobao.com/item.htm?spm=2013.1.w4023-5034755838.13.747a61a7ccfHwS&id=554942413474) > 声明:本人与该店铺无利益相关,纯属个人觉得好用做分享 > > 该店铺有两种方式: > > 1. 店铺支持帮你过企业资质,这里就用你自己的开放平台号就好了 > 2. 临时使用可以问店家租一个月进行开发,这里租了之后,店家会把 AppID 和 AppSecret 的信息发给你,你提供回调域就好了 因此这里我就贴出一张授权回调的地址作参考。 ![image-20190617153552218](http://static.xkcoding.com/spring-boot-demo/social/063927-1.jpg) #### 1.5.4. 谷歌开放平台申请 1. 前往 https://console.developers.google.com/projectcreate 创建项目 2. 前往 https://console.developers.google.com/apis/credentials ,在第一步创建的项目下,添加应用 ![image-20190617151119584](http://static.xkcoding.com/spring-boot-demo/social/063920.jpg) ![image-20190617150903039](http://static.xkcoding.com/spring-boot-demo/social/063922.jpg) #### 1.5.5. 微软开放平台申请 1. 前往 https://portal.azure.com/#blade/Microsoft_AAD_RegisteredApps/ApplicationsListBlade 注册应用 2. 在注册应用的时候就需要填写回调地址,当然后期也可以重新修改 ![image-20190617152529449](http://static.xkcoding.com/spring-boot-demo/social/063921.jpg) 3. client id 在这里 ![image-20190617152805581](http://static.xkcoding.com/spring-boot-demo/social/063927.jpg) 4. client secret 需要自己在这里生成 ![image-20190617152711938](http://static.xkcoding.com/spring-boot-demo/social/063924.jpg) #### 1.5.6. 小米开放平台申请 1. 申请小米开发者,审核通过 2. 前往 https://dev.mi.com/passport/oauth2/applist 添加oauth应用,选择 `创建网页应用` 3. 填写基本信息之后,进入应用信息页面填写 `回调地址` ![image-20190617151502414](http://static.xkcoding.com/spring-boot-demo/social/063924-1.jpg) 4. 应用审核通过之后,可以在应用信息页面的 `应用详情` 查看到 AppKey 和 AppSecret,吐槽下,小米应用的审核速度特别慢,需要耐心等待。。。。 ![image-20190617151624603](http://static.xkcoding.com/spring-boot-demo/social/063926.jpg) #### 1.5.7. 企业微信平台申请 > 参考:https://xkcoding.com/2019/08/06/use-justauth-integration-wechat-enterprise.html ## 2. 主要代码 > 本 demo 采用 Redis 缓存 state,所以请准备 Redis 环境,如果没有 Redis 环境,可以将配置文件的缓存配置为 > > ```yaml > justauth: > cache: > type: default > ``` ### 2.1. pom.xml ```xml 4.0.0 spring-boot-demo-social 1.0.0-SNAPSHOT jar spring-boot-demo-social Demo project for Spring Boot com.xkcoding spring-boot-demo 1.0.0-SNAPSHOT UTF-8 UTF-8 1.8 1.1.0 org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-starter-test test org.springframework.boot spring-boot-starter-data-redis org.apache.commons commons-pool2 com.xkcoding justauth-spring-boot-starter ${justauth-spring-boot.version} org.projectlombok lombok true com.google.guava guava cn.hutool hutool-all spring-boot-demo-social org.springframework.boot spring-boot-maven-plugin ``` ### 2.2. application.yml ```yaml 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 cache: type: redis prefix: 'SOCIAL::STATE::' timeout: 1h ``` ### 2.3. OauthController.java ```java /** *

* 第三方登录 Controller *

* * @author yangkai.shen * @date Created in 2019-05-17 10:07 */ @Slf4j @RestController @RequestMapping("/oauth") @RequiredArgsConstructor(onConstructor_ = @Autowired) public class OauthController { private final AuthRequestFactory factory; /** * 登录类型 */ @GetMapping public Map loginType() { List 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 缓存 请看👉[这里](https://github.com/justauth/justauth-spring-boot-starter#2-%E7%BC%93%E5%AD%98%E9%85%8D%E7%BD%AE) ## 3. 运行方式 打开浏览器,输入 http://oauth.xkcoding.com/demo/oauth ,点击各个登录方式自行测试。 > `Google 登录,有可能因为祖国的强大导致测试失败,自行解决~` :kissing_smiling_eyes: ![image-20190809161032422](https://static.xkcoding.com/blog/2019-08-09-081033.png) ## 参考 1. JustAuth 项目地址:https://github.com/justauth/JustAuth 2. justauth-spring-boot-starter 地址:https://github.com/justauth/justauth-spring-boot-starter 3. frp内网穿透项目地址:https://github.com/fatedier/frp 4. frp内网穿透官方中文文档:https://github.com/fatedier/frp/blob/master/README_zh.md 5. Frp实现内网穿透:https://zhuanlan.zhihu.com/p/45445979 6. QQ互联文档:http://wiki.connect.qq.com/%E5%87%86%E5%A4%87%E5%B7%A5%E4%BD%9C_oauth2-0 7. 微信开放平台文档:https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&verify=1&id=open1419316505&token=&lang=zh_CN 8. GitHub第三方登录文档:https://developer.github.com/apps/building-oauth-apps/ 9. 谷歌Oauth2文档:https://developers.google.com/identity/protocols/OpenIDConnect 10. 微软Oauth2文档:https://docs.microsoft.com/zh-cn/graph/auth-v2-user 11. 小米开放平台账号服务文档:https://dev.mi.com/console/doc/detail?pId=707