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:
<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 上完成授权操作,注意授权的链接如下:
- https://github.com/login/oauth/authorize
这个授权需要携带一个 client_id 参数,这个 client_id 就是准备工作中获取到的 client_id,另外一个 state 则是用来防止跨站脚本攻击的,state 参数的值可以自己随意填写。
我们来看下页面的效果图:
当我们点击 GitHub 图标,完成授权操作之后,会自动跳转到我们在准备工作填的回调地址中,并且携带一个 code 参数,拿着这个 code 参数我们就可以去获取 access_token 了,有了 access_token 我们就可以获取到用户信息了。
因此,我们再来添加一个 /authorization_code 接口,如下:
@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 的数据格式如下:
{access_token=9f33730ef09b74943a1cf7d8f9c0e567b9286829, token_type=bearer, scope=}
可以看到,有 access_token,有 token_type,也有 scope。
接下来,拿着 access_token ,将 access_token 放在请求头里边,我们就可以去调用 https://api.github.com/user 接口获取用户信息了,获取到的用户信息格式如下:
{
"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
好了,本文就先说这么多,有问题欢迎留言讨论。
← 单点登录 自定义返回的 Token 信息 →