OAuth2 和小伙伴们已经聊了很多了,咱们来一个实际点的案例练练手。
这里我才用 GitHub 来做第三方登录。
为什么是 GitHub 呢?有两方面考虑:
- 程序员基本上都有 GitHub 账号,测试方便。
- 国内的无论 QQ、微信、微博等,都需要注册审核,很费时间。
- 流程都是一样的,会做 GitHub 第三方登录,就会做 QQ 第三方登录。
当然,本系列前面几篇文章还是建议小伙伴们先看一下,这样可以更好的理解本文。
- 做微服务绕不过的 OAuth2,松哥也来和大家扯一扯
- 这个案例写出来,还怕跟面试官扯不明白 OAuth2 登录流程?
- 死磕 OAuth2,教练我要学全套的!
- OAuth2 令牌还能存入 Redis ?越玩越溜!
- 想让 OAuth2 和 JWT 在一起愉快玩耍?请看松哥的表演
- 最近在做 Spring Cloud 项目,松哥和大家分享一点微服务架构中的安全管理思路
- Spring Boot+OAuth2,一个注解搞定单点登录!
好了,不废话,我们开始今天的案例。
1.准备工作
首先登录自己的 GitHub 账户,右上角点击个人面板,选择 Settings:
然后点击左边菜单底部的 Developer settings:
然后选择 OAuth Apps,点击 Register a new application 按钮:
接下来注册你的应用信息
从上往下,依次是你的项目名称、首页地址、项目描述、授权成功回调地址。信息填完之后,点击下方的 Register application 按钮完成注册。
注册完成之后,我们就可以获取到一个 Client ID 和一个 Client Secret,这就是我们登录时客户端的凭据。
这两个信息保存好,不要外泄。
写到这里,松哥不由得感叹一句,还是国外的应用香啊,用 GitHub 做第三方登录,一分钟不到,准备工作就完成了,用 QQ 做,我的资料已经提交两天了,目前的状态还是审核中。。。不过我也理解腾讯所面临的监管问题。
2.创建应用
接下来我们来简单创建一个自己的网站,我们依然使用 Spring Boot 项目,添加如下依赖:
然后我们在 resources/templates 目录下创建一个简单的 index.html:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| <body> <p>hello 欢迎来到江南一点雨的小站!</p> <div> 社交账号登录:<a href="https://github.com/login/oauth/authorize?client_id=xxxxxx&state=javaboy"> <svg t="1587352912571" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2196" width="32" height="32"> <path d="M512 42.666667A464.64 464.64 0 0 0 42.666667 502.186667 460.373333 460.373333 0 0 0 363.52 938.666667c23.466667 4.266667 32-9.813333 32-22.186667v-78.08c-130.56 27.733333-158.293333-61.44-158.293333-61.44a122.026667 122.026667 0 0 0-52.053334-67.413333c-42.666667-28.16 3.413333-27.733333 3.413334-27.733334a98.56 98.56 0 0 1 71.68 47.36 101.12 101.12 0 0 0 136.533333 37.973334 99.413333 99.413333 0 0 1 29.866667-61.44c-104.106667-11.52-213.333333-50.773333-213.333334-226.986667a177.066667 177.066667 0 0 1 47.36-124.16 161.28 161.28 0 0 1 4.693334-121.173333s39.68-12.373333 128 46.933333a455.68 455.68 0 0 1 234.666666 0c89.6-59.306667 128-46.933333 128-46.933333a161.28 161.28 0 0 1 4.693334 121.173333A177.066667 177.066667 0 0 1 810.666667 477.866667c0 176.64-110.08 215.466667-213.333334 226.986666a106.666667 106.666667 0 0 1 32 85.333334v125.866666c0 14.933333 8.533333 26.88 32 22.186667A460.8 460.8 0 0 0 981.333333 502.186667 464.64 464.64 0 0 0 512 42.666667" fill="#2c2c2c" p-id="2197"></path> </svg> </a> </div> <div>国际站:<a href="http://www.javaboy.org">javaboy.org</a></div> <div>国内站:<a href="http://www.itboyhub.com">itboyhub.com</a></div> </body>
|
这就是一个简单的 HTML 页面,页面上有一个 GitHub 的图标,点击这个图标,就可以去 GitHub 上完成授权操作,注意授权的链接如下:
这个授权需要携带一个 client_id 参数,这个 client_id 就是准备工作中获取到的 client_id,另外一个 state 则是用来防止跨站脚本攻击的,state 参数的值可以自己随意填写。
我们来看下页面的效果图:
当我们点击 GitHub 图标,完成授权操作之后,会自动跳转到我们在准备工作填的回调地址中,并且携带一个 code 参数,拿着这个 code 参数我们就可以去获取 access_token 了,有了 access_token 我们就可以获取到用户信息了。
因此,我们再来添加一个 /authorization_code 接口,如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| @GetMapping("/authorization_code") public String authorization_code(String code) { Map<String, String> map = new HashMap<>(); map.put("client_id", "xxx"); map.put("client_secret", "xxxx"); map.put("state", "javaboy"); map.put("code", code); map.put("redirect_uri", "http://localhost:8080/authorization_code"); Map<String,String> resp = restTemplate.postForObject("https://github.com/login/oauth/access_token", map, Map.class); System.out.println(resp); HttpHeaders httpheaders = new HttpHeaders(); httpheaders.add("Authorization", "token " + resp.get("access_token")); HttpEntity<?> httpEntity = new HttpEntity<>(httpheaders); ResponseEntity<Map> exchange = restTemplate.exchange("https://api.github.com/user", HttpMethod.GET, httpEntity, Map.class); System.out.println("exchange.getBody() = " + exchange.getBody()); return "forward:/index.html"; }
|
在 authorization_code 接口中,我们首先向 http://localhost:8080/authorization_code 发起请求去获取 access_token,注意我们需要的参数,client_id 和 client_secret 使我们第一步准备工作申请到的。获取到 access_token 的数据格式如下:
1
| {access_token=9f33730ef09b74943a1cf7d8f9c0e567b9286829, token_type=bearer, scope=}
|
可以看到,有 access_token,有 token_type,也有 scope。
接下来,拿着 access_token ,将 access_token 放在请求头里边,我们就可以去调用 https://api.github.com/user 接口获取用户信息了,获取到的用户信息格式如下:
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
| { "login":"lenve", "id":35444368, "node_id":"MDQ6VXNlcjM1NDQ0MzY4", "avatar_url":"https://avatars3.githubusercontent.com/u/35444368?v=4", "gravatar_id":"", "url":"https://api.github.com/users/lenve", "html_url":"https://github.com/lenve", "followers_url":"https://api.github.com/users/lenve/followers", "following_url":"https://api.github.com/users/lenve/following{/other_user}", "gists_url":"https://api.github.com/users/lenve/gists{/gist_id}", "starred_url":"https://api.github.com/users/lenve/starred{/owner}{/repo}", "subscriptions_url":"https://api.github.com/users/lenve/subscriptions", "organizations_url":"https://api.github.com/users/lenve/orgs", "repos_url":"https://api.github.com/users/lenve/repos", "events_url":"https://api.github.com/users/lenve/events{/privacy}", "received_events_url":"https://api.github.com/users/lenve/received_events", "type":"User", "site_admin":false, "name":null, "company":null, "blog":"", "location":null, "email":null, "hireable":null, "bio":null, "public_repos":2, "public_gists":0, "followers":1, "following":1, "created_at":"2018-01-15T06:05:04Z", "updated_at":"2020-04-20T03:00:49Z" }
|
好了,用户的 GitHub 信息现在已经获取到了,接下来该存数据库就存数据库,该接入自己的登录流程就接入。
如此之后,我们就完成了第三方登录功能,其实还是非常 Easy 的,只要大家把这个流程走通,以后想接入微信登录、QQ 登录,都将是非常容易的事情。
本文案例下载地址:https://github.com/lenve/oauth2-samples
好了,本文就先说这么多,有问题欢迎留言讨论。