本次整理的博客內容是關於在項目中整合用 github 用戶角色登錄的小demo!說到調取github的用戶登錄api , 聽起來好像沒什么難度,但是仔細看來還是有很多細節需要注意的!下面就將整理我成功拉取github用戶登錄的詳細過程:
Step
進入GitHub官網,在官網的最下面會有一個api字樣,就是接入github登錄api使用的詳細介紹文檔,下圖所示,點擊進入
進入之后我們在頁面查找 OAuth,眾所周知這是開放授權的意思,那么這一定是介紹關於github登錄授權的文檔內容了,我們點擊進入,下圖所示
快速點擊截圖中的地方根據詳細文檔一步一步的進行
具體的步驟我在以下截圖中一一展示,真正演示保姆級教程
根據上面一步我們就可以在前端進行登錄的跳轉,來獲取github的授權
主要代碼
<li><a href="https://github.com/login/oauth/authorize?client_id=dfb81c6bd4e3a33beac6&redirect_uri=http://localhost:8080/callback&scope=user&state=1">登錄</a></li>
詳細的前端代碼
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>牛柳社區</title>
<!-- 最新版本的 Bootstrap 核心 CSS 文件 -->
<link rel="stylesheet" href="css/bootstrap.min.css">
<!-- jquery組件 -->
<script src="js/jquery-3.3.1.min.js" type="application/javascript"></script>
<!-- 最新的 Bootstrap 核心 JavaScript 文件 -->
<script src="js/bootstrap.min.js" type="application/javascript"></script>
</head>
<body>
<nav class="navbar navbar-default">
<div class="container-fluid">
<!-- Brand and toggle get grouped for better mobile display -->
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="#">牛柳社區</a>
</div>
<!-- Collect the nav links, forms, and other content for toggling -->
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
<form class="navbar-form navbar-left">
<div class="form-group">
<input type="text" class="form-control" placeholder="Search">
</div>
<button type="submit" class="btn btn-default">Submit</button>
</form>
<ul class="nav navbar-nav navbar-right">
<li><a href="https://github.com/login/oauth/authorize?client_id=dfb81c6bd4e3a33beac6&redirect_uri=http://localhost:8080/callback&scope=user&state=1">登錄</a></li>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Dropdown <span class="caret"></span></a>
<ul class="dropdown-menu">
<li><a href="#">消息中心</a></li>
<li><a href="#">個人資料</a></li>
<li><a href="#">退出登錄</a></li>
</ul>
</li>
</ul>
</div>
</div>
</nav>
</body>
</html>
根據步驟我們可以看到,當點擊前端頁面的登錄按鈕,頁面會跳轉到http:localhost:8080/callback的地址,通過這個回調地址github會給我們返回一個code和state參數,我們要接受它
根據說明文檔我們得到這個code和state參數后,再加上client_id,client_secret,redirect_uri,加在一起我們需要在把這5和數據封裝成一個對象,傳到github去,請求能夠返回一個access_token給我們
所以我們封裝這5個數據為一個對象,方便操作
import lombok.NoArgsConstructor;
/**
* @author yuqiliu
* @create 2020-03-20 11:07
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class AccessTokenDTO {
private String client_id;
private String client_secret;
private String code;
private String redirect_uri;
private String state;
}
此時我們就要把這個數據傳到github上面的POST https://github.com/login/oauth/access_token
接口來獲得github給我們返回的access_token
這里我們要注意了,我們要實現這種接口的跳轉並返回數據,必須要借助一個工具就是OkHttp輔助工具,它能夠很好的解決問題
OkHtto官方網站:https://square.github.io/okhttp/
在使用前先導入maven依賴和fastjson方便后面json對象,json字符串的轉換等操作
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>3.14.2</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.60</version>
</dependency>
通過OkHttp官方給的演示案例,我們直接copy下來,改一改成為這種方式
public String getAccessToken(AccessTokenDTO accessTokenDTO) {
MediaType mediaType = MediaType.get("application/json; charset=utf-8");
OkHttpClient client = new OkHttpClient();
RequestBody body = RequestBody.create(mediaType, JSON.toJSONString(accessTokenDTO));
Request request = new Request.Builder()
.url("https://github.com/login/oauth/access_token")
.post(body)
.build();
try (Response response = client.newCall(request).execute()) {
String string=response.body().string();
System.out.println(string);
String token=string.split("&")[0].split("=")[1];
System.out.println(token);
return token;
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
結果會返回一個access_token字符串根據文檔的說明如下
我在程序代碼運行下獲得的就是這個access_token數據,並且我發現即使同一個用戶不同時間的登錄它的值也是會實時動態的變化的,如下
access_token=d708852fa200b5aa2889e503415c7dd14366da03&scope=user&token_type=bearer
下面是最重要的一步了,也就是說我們完全得到了github端給我們返回的access_token了,登錄用戶再把這個access_token傳輸到github提供的一個接口我們就大功告成了,就能得到這個github登錄用戶的所有用戶信息了
這里我們可以先進行測試一下看能不能成功。
我們可以先自己去創建一個personal access_token的數據來用get方式請求這個接口,來訪問看看是不是真正的能夠得到這個返回的用戶數據,如果能就成功了!
點擊提交之后,我們就會得到一個個人的access_token數據,把這個數據用get方式傳到git提供的接口里面來測試,看返回數據是不是用戶信息就行了
直接可以訪問url:https://api.github.com/user?access_token=42469a388ea96cb4dcac479a01560c6987f63d63
正常情況下會很好的返回用戶的信息的:如下圖所示,json格式的用戶信息
驗證過關后,我們就可以把我們自己剛剛臨時創建的Personal access tokens給刪除了,以免安全問題,下面真正的來實現一波了!
同樣我們可以封裝一個返回的用戶對象,對象的屬性為我們僅僅想需要的屬性就行了,如我封裝了一個GitUser用戶
package com.yuqiliu.community.niuliucommunity.dto;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @author yuqiliu
* @create 2020-03-20 12:00
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class GithubUser {
private String name;
private Long id;
private String bio;
}
后面仍然要使用OkHttp的接口跳轉功能,並且把返回的json字符串通過fastjson工具轉化為我們所想要的json對象即可
public GithubUser getUser(String accessToken)
{
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url("https://api.github.com/user?access_token="+accessToken)
.build();
try (Response response = client.newCall(request).execute()) {
String string= response.body().string();
System.out.println(string);
GithubUser githubUser = JSON.parseObject(string, GithubUser.class);
return githubUser;
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
把返回的access_token傳參進入這個方法就能得到我們期盼已久的github登錄用戶的全部數據了,哈哈哈,完結撒花!!!
下面貼上controller層的業務代碼:
IndexController:
package com.yuqiliu.community.niuliucommunity.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
/**
* @author yuqiliu
* @create 2020-03-19 11:58
*/
@Controller
public class IndexController {
@RequestMapping("/")
public String index(){
return "index";
}
}
AuthorizeController:
package com.yuqiliu.community.niuliucommunity.controller;
import com.yuqiliu.community.niuliucommunity.dto.AccessTokenDTO;
import com.yuqiliu.community.niuliucommunity.dto.GithubUser;
import com.yuqiliu.community.niuliucommunity.provider.GithubProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
/**
* @author yuqiliu
* @create 2020-03-20 10:51
*/
@Controller
public class AuthorizeController {
@Autowired
private GithubProvider githubProvider;
@Value("${github.client.id}")
private String clientId;
@Value("${github.client.secret}")
private String clientSecret;
@Value("${github.redirect.uri}")
private String redirectUri;
@GetMapping("/callback")
public String callback(@RequestParam(name = "code") String code,
@RequestParam(name = "state") String state)
{
AccessTokenDTO accessTokenDTO=new AccessTokenDTO();
accessTokenDTO.setClient_id(clientId);
accessTokenDTO.setClient_secret(clientSecret);
accessTokenDTO.setRedirect_uri(redirectUri);
accessTokenDTO.setCode(code);
accessTokenDTO.setState(state);
String accessToken = githubProvider.getAccessToken(accessTokenDTO);
GithubUser user = githubProvider.getUser(accessToken);
// System.out.println(user.getName());
System.out.println(user);
return "index";
}
}
application.properties:
github.client.id=dfb81c6bd4e3a33beac6
github.client.secret=3caa91f547b8b15c2ed90df267cb23efcc8a25e7
github.redirect.uri=http://localhost:8080/callback
下面是GithubProvider.java,這個類是完全用來處理github提供的接口的處理方法的:
package com.yuqiliu.community.niuliucommunity.provider;
import com.alibaba.fastjson.JSON;
import com.yuqiliu.community.niuliucommunity.dto.AccessTokenDTO;
import com.yuqiliu.community.niuliucommunity.dto.GithubUser;
import okhttp3.*;
import org.springframework.stereotype.Component;
import java.io.IOException;
/**
* @author yuqiliu
* @create 2020-03-20 11:23
*/
@Component
public class GithubProvider {
public String getAccessToken(AccessTokenDTO accessTokenDTO) {
MediaType mediaType = MediaType.get("application/json; charset=utf-8");
OkHttpClient client = new OkHttpClient();
RequestBody body = RequestBody.create(mediaType, JSON.toJSONString(accessTokenDTO));
Request request = new Request.Builder()
.url("https://github.com/login/oauth/access_token")
.post(body)
.build();
try (Response response = client.newCall(request).execute()) {
String string=response.body().string();
System.out.println(string);
String token=string.split("&")[0].split("=")[1];
System.out.println(token);
return token;
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
public GithubUser getUser(String accessToken)
{
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url("https://api.github.com/user?access_token="+accessToken)
.build();
try (Response response = client.newCall(request).execute()) {
String string= response.body().string();
System.out.println(string);
GithubUser githubUser = JSON.parseObject(string, GithubUser.class);
return githubUser;
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
寫在最后
我運行代碼成功后,得到的用戶返回信息為: