参考文章:
http://www.ruanyifeng.com/blog/2019/04/oauth_design.html
http://www.ruanyifeng.com/blog/2019/04/oauth-grant-types.html
http://www.ruanyifeng.com/blog/2019/04/github-oauth.html
什么是OAuth2.0
OAuth 2.0 是目前最流行的授权机制,用来授权第三方应用,获取用户数据。
有以下例子:
我们日常使用的微博,其登录页面如下:
可以看到,这里有其他的登录方式,用其他应用的账号去登录微博,这就是OAuth2.0的实际使用例子。
这些其他应用就是第三方应用,授权这些应用来返回用户相应的数据。
OAuth2.0的种类
OAuth2.0共有四种方式,分别是授权码式、 隐藏式、密码式、凭证式。
使用场景分别是:授权码:适合有后端的。隐藏式:适合无后端的。密码式:直接告诉账号密码。凭证式:适合命令行应用。更多详细的信息请看上面三篇文章,写的非常详细,本文只重点讲解授权码式,因为其是目前使用最多的方式。
授权码方法的工作流程
授权码式的工作过程如下:
步骤:
- 用户进入前端页面,点击使用第三方登陆(Gitee)方式
- 页面转跳到 Gitee 登陆页面,并让用户登陆,登陆成功后,询问用户是否允许原网页获取 XX 权限
- 同意后 Gitee 会重定向一个 url 网址,这网址里面包含授权码(code)
- 后端解析这个 url ,并拿到这个授权码,然后将这个授权码发送给 Gitee
- Gitee 收到后,会返回一个 json 数据,这个 json 数据就是令牌(token),其中 access_token 就在里面
- 后端解析 token 拿到 access_token 就可以获取用户登陆 Gitee 内的数据了
实战过程:
- 进入gitee,创建自己的第三方应用 https://gitee.com/oauth/applications/new
创建完成后,会生成Client ID和Client Secret,Client Secret一定要保密!!
- 前端标签填写码云三方认证地址:
https://gitee.com/oauth/authorize?client_id={client_id}&redirect_uri={redirect_uri}&response_type=code(Get请求)
<body>
<h2>
<a id="login">Login By Gitee</a>
</h2>
<script>
//fill in your client_id & redirect_uri
const client_id = '0cacf35545c6723f98d887432c469431032b2140ad142fd7e8bb4cc9c54dc35c';
const redirect_uri = 'http://localhost:8088/oauth/redirect';
const authorize_uri = 'https://gitee.com/oauth/authorize';
const link = document.getElementById('login');
link.href = `${authorize_uri}?client_id=${client_id}&redirect_uri=${redirect_uri}&response_type=code&scope=user_info%20emails`;
</script>
</body>
其中的scope参数的值需要和用户上次授权的勾选的一致。如用户在上次授权了user_info、emails,那么url就如上面所示
- 这时,Gitee会通过回调地址{redirect_uri}将 用户授权码 传递给服务器,即发送({redirect_uri}?code=abc&state=xyz)的请求给我们的服务器,我们直接获取参数即可
user_code = request.queryParams("code"); //获取参数code的值
- 拿到user_code后发送如下请求给Gitee,以获取token。(java发送请求可导入httpcomponents依赖实现)
https://gitee.com/oauth/token?grant_type=authorization_code&code={code}&client_id={client_id}&redirect_uri={redirect_uri}&client_secret={client_secret}
(发POST请求,且建议将 client_secret 放在 Body 中传值,以保证数据安全。)
public static token tokenResponse(String code) throws IOException {
String content = Request.post(OAuthGiteeConst.GiteeURL(code))
.execute().returnContent().toString();
System.out.println(content);
token token = new Gson().fromJson(content, token.class);
System.out.println(token);
return token;
}
content内容如下:
{
"access_token":"0321262ads24aa21c895a7be1b5dc655",
"token_type":"bearer",
"expires_in":86400,
"refresh_token":"2aefd773609d9ed7d2r5hae289ea36f2beebb7bb78e3352d8e9ca4efad41dec9",
"scope":"user_info emails",
"created_at":1615882982
}
可以看到,这个access_token就在token里面
因此,我们可以构造这样的token,以获取content的内的信息
public class token {
private String access_token;
private String token_type;
private Integer expires_in;
private String refresh_token;
private String scope;
private String created_at;
}
- 使用access_token向Gitee发送请求获取用户的相关信息
Gitee的API方法文档:https://gitee.com/api/v5/swagger#/getV5ReposOwnerRepoStargazers?ex=no
获取授权用户的资料:
获取授权用户的全部邮箱:
我使用的是SparkJava来写的web项目,这个有点类似与node.js,用SpringMVC也是一样的,重点是理解整个过过程!