今天我们继续学习:Github授权第三方登录,前面我们已经学习了 码云(Gitee)授权第三方登录,Github授权第三方登录的实现过程其实和 码云(Gitee)授权第三方登录的实现过程类似,只是有一些细节需要注意,下面我们就一起来学习吧
- 一、准备工作
- 1、登录 Github 官网
首先我们得有自己的一个 githu 账号,我们到 github 的官网进行注册或者登录
官网地址:https://github.com/
登录成功后:
- 2、创建应用
在下拉菜单中找到 “Settings”,设置
然后找到 “Developer settings”,开发人员设置
找到“OAuth Apps”,我们就可以开始创建我们的授权应用了,在右上角点击“New OAuth APP”
我们填好应用基本信息,点击“Register application”,我们便创建好了应用,点击应用,我们便可以拿到应用的 appid 和 appkey
- 3、将应用信息保存到项目中
由于我使用的是 SpringBoot 项目,我放在了 application.yml 文件中
-
二、开始开发
-
1、引入 Maven 依赖
<!-- 网络请求 -->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.6</version>
</dependency>
<!-- alibaba的fastjson -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.51</version>
</dependency>
其余的依赖请自行加入
- 2、在页面放置 “Github” 授权登录的 DOM 元素
<a th:href="@{github/auth}" class="link" title="Github登录"><i class="iconfont icon-github"></i></a>
这里使用的是阿里的 iconfont 图标
- 三、创建 “Github” 授权登录的 Controller,GithubController.java
- 1、从配置文件中获取 “Github” 配置信息
/**
* github授权中提供的 appid 和 appkey
*/
@Value("${github.oauth.clientid}")
public String CLIENTID;
@Value("${github.oauth.clientsecret}")
public String CLIENTSECRET;
@Value("${github.oauth.callback}")
public String URL;
- 2、页面登录按钮点击后的接口
/**
* 请求授权页面
*/
@GetMapping(value = "/auth")
public String qqAuth(HttpSession session) {
// 用于第三方应用防止CSRF攻击
String uuid = UUID.randomUUID().toString().replaceAll("-", "");
session.setAttribute("state", uuid);
// Step1:获取Authorization Code
String url = "https://github.com/login/oauth/authorize?scope=user" +
"&client_id=" + CLIENTID +
"&redirect_uri=" + URLEncoder.encode(URL) +
"&state=" + uuid;
return PasswordUtils.redirectTo(url);
}
接口文档中建议我们在授权登录时传入一个加密的数据防止被攻击,我们传入了UUID,最后重定向到授权页面
- 3、当该用户点击“授权”按钮,同意授权后,就会回调到我们在应用中填写的回调地址里去
/**
* 授权回调
*/
@GetMapping(value = "/callback")
public String qqCallback(HttpServletRequest request) throws Exception {
HttpSession session = request.getSession();
// 得到Authorization Code
String code = request.getParameter("code");
// 我们放在地址中的状态码
String state = request.getParameter("state");
String uuid = (String) session.getAttribute("state");
// 验证信息我们发送的状态码
if (null != uuid) {
// 状态码不正确,直接返回登录页面
if (!uuid.equals(state)) {
return PasswordUtils.redirectTo("/login");
}
}
// Step2:通过Authorization Code获取Access Token
String url = "https://github.com/login/oauth/access_token?" +
"client_id=" + CLIENTID +
"&client_secret=" + CLIENTSECRET +
"&redirect_uri=" + URL +
"&code=" + code +
"&state=" + state;
JSONObject accessTokenJson = GithubHttpClient.getAccessToken(url);
// Step3: 获取用户信息
/*url = "https://api.github.com/user?access_token=" + accessTokenJson.getString("access_token");*/
url = "https://api.github.com/user";
JSONObject jsonObject = GithubHttpClient.getUserInfo(url, accessTokenJson.getString("access_token"));
/**
* TODO 获取到用户信息之后,你自己的业务逻辑
* 判断数据库是否有次用户,有---登录成功,无---保存用户至数据库,登录成功
*/
return PasswordUtils.redirectTo("/success");
}
-
四、上面回调方法中所用到的网络接口方法,我放在了 GithubHttpClient.java 文件中,主要有两个方法
-
1、使用 code 获取Access Token
/**
* 获取Access Token
* post
*/
public static JSONObject getAccessToken(String url) throws IOException {
HttpClient client = HttpClients.createDefault();
HttpPost httpPost = new HttpPost(url);
httpPost.setHeader("Accept", "application/json");
HttpResponse response = client.execute(httpPost);
HttpEntity entity = response.getEntity();
if (null != entity) {
String result = EntityUtils.toString(entity, "UTF-8");
return JSONObject.parseObject(result);
}
httpPost.releaseConnection();
return null;
}
我们在请求头中传入了
httpPost.setHeader("Accept", "application/json");
是希望返回 JSON 格式的数据,code 直接拼接在了 url 上
- 2、使用 Access Token 获取用户信息
/**
* 获取用户信息
* get
*/
public static JSONObject getUserInfo(String url, String token) throws IOException {
CloseableHttpClient client = HttpClients.createDefault();
HttpGet httpGet = new HttpGet(url);
httpGet.setHeader("Accept", "application/json");
httpGet.setHeader("Authorization", "token " + token);
HttpResponse response = client.execute(httpGet);
HttpEntity entity = response.getEntity();
if (entity != null) {
String result = EntityUtils.toString(entity, "UTF-8");
return JSONObject.parseObject(result);
}
httpGet.releaseConnection();
return null;
}
获取用户信息这一步,官方给的文档是:
注意:这里我们在请求头中传入 token,API 文档中描述不够清楚,这里看了好几遍才明白,掉坑儿里了
httpGet.setHeader("Authorization", "token " + token);
最终我们获取到一个 JSON 对象,该对象包含了用户的信息,例如:id,name,email,phone 等等。
- 3、官网 OAuth API 文档
https://developer.github.com/apps/building-oauth-apps/authorizing-oauth-apps/#web-application-flow
- 五、总结
该授权认证过程符合 OAuth2 认证基本流程,流程如下:
1、用户点击页面登录按钮,请求授权页面,用户在此页面登录账号并同意授权
2、用户同意授权后,回调至我们项目中,首先验证 state 是否一致
3、使用上一步拿到的 code 请求 access_token
4、使用 access_token 请求 用户信息,完成授权登录过程
如您在阅读中发现不足,欢迎留言!!!
下一篇:
如您在阅读中发现不足,欢迎留言!!!