前言
在前面項目的學習中用來練手的都是本地的項目,進行一個用戶名和密碼登錄即可,也做過一些的限制操作等,比如在登錄時候對於用戶名(電話號碼的驗證等等)詳情見秒殺項目登錄設計,但也都是本地的登錄,不需要驗證碼,也不需要授權等,也就沒有上線的可能性。所以就想着來記錄和寫一些關於第三方授權登錄的文章。之前也做過關於短信驗證碼的登錄,但是短信驗證購買的是騰訊一年的短信驗證服務(後續會出一個教程和demo),這裏就不作具體的介紹。今天這裏來介紹一下Github第三方驗證登錄,後續的還有gitee,QQ和郵箱驗證登錄。我也會做成小的demo放在Github
,供大家學習。
首先來看一下自己的社區登錄圖,其中有註冊郵箱登錄,和第三方登錄。
正文
既然學習到如何使用Github來做第三方登錄,就需要我們先去官網查看文檔,一般對於網站可以用來接入第三方的登錄,在網站下方都會有一個API其中有一個具體的授權登錄等,這裏就直接貼出具體的地址Github第三方登錄文檔英文好的小夥伴可以直接觀看原生文檔,就是一個單點登錄,有學習和了解過基礎的原理的看起來應該不算是困難。
在大致完成了文檔的閱讀之後,下面就直接開始介紹具體的流程:
創建App
這裏就不再具體貼圖如何進入到這個頁面(Settings->Developer Settings->Oauth Apps)
進入之後,點擊新建,填寫下面的信息:
解釋:Homepage URl 就是我們網站後續上線之後的上線地址,下面的Authorization callback URL
原本填寫應該是https://community.maycope.cn/callback
,但是現在沒有服務器用來部署項目,我們就可以寫成本地項目地址和端口號,在調用時候,就會調用本地進行驗證登錄。
點擊Register application,上傳自己的app的頭像即可,注意可以先將ID和 Secret複製下來。
若是以上圖片可能講解不是很清楚可以查看如下具體創建app創建app
圖解流程:
- 首先我們用戶訪問網站首頁,點擊登錄時候進行的是
1.1
就是自己邏輯的構造,將那些client ID
和redirect_uri
進行一個處理,然後纔會發送到Github上的https://github.com/login/oauth/authorize
(這些信息文檔裏都有寫到),進行驗證授權,這個時候,Github會回調我們的redirect-uri,攜帶code信息,如1.2.1
- 本地收到地址之後,解析出code,然後再度調用
https://github.com/login/oauth/access_token
攜帶code
和secret
和下面的所有信息,這裏進行了一個封裝的處理。
- 在完成了調用之後,如果攜帶的
access_token
是正確的,Github會返回這個具體的access_token
,網站(我們的)就可以根據這個返回回來的進行調用用戶的具體信息,這裏我們可以進行模擬生成一個access_token
看看網站會給我們返回什麼信息:
1.如下我們生成一個access_token,選擇下方的user,這裏沒有截圖完整。
- 將生成的進行復制。
- 訪問如下網址,並且攜帶上自己的token信息。可以看到返回給我們的信息1,有id,name等。
- 將生成的進行復制。
- 前面返回的access_token,就可以用來調用user信息。
- 就可以將用戶的信息存入到數據庫裏面並且對用戶的狀態進行更新處理。
- 返回給用戶,登錄成功,進入到系統中。
- 以上就是全部的流程處理信息。具體變成如下。
編程實現
以上完成了講解之後,其實發現並不難理解,就是第一次接觸可能會有一些困難,這裏就將這部分代碼集成到miaosha_2
模塊,因爲對於模塊二也是登錄設置,可以進行同時的學習,這部分代碼會放到我的個人倉庫,地址如下【超鏈接】,先暫時完成一個小模塊(對於數據庫模塊,可以保存到數據庫中,表的設計也有實現,但是就是對於用戶信息更改的情況,這裏暫時沒有做一個編寫,大家可以自行對用戶數據更改的情況進行設計)
授權登錄獲取access_token
首先來看具體的登錄按鈕設計,就如我們前面所講,訪問authorize
時候攜帶上code和redirect_uri
<div style="margin-top: 25px">
<h4>第三方賬號登錄</h4>
<a th:href="@{https://github.com/login/oauth/authorize(client_id=${@environment.getProperty('github.client_id')},redirect_uri=${@environment.getProperty('github.redirect_uri')},scope='user',state='githublogin')}"
class="login-style">
<img src="/images/github.svg" style="width: 20px;height: 20px">
Github登錄
</a>
</div>
然後github會回調我們的地址,這裏先行貼出在配置文件中的內容,就可以回調如下地址,我們再來看該接口下是如何對參數進行接收和驗證。
github:
client_id: 63fcee0c9a2ad4f0XXXX
client_secret: XXXXX685e5db5cd0320ad12331e9e1772ceXXXXX
redirect_uri: http://localhost:8887/githubCallback
githubCallback
- 首先對數據進行封裝,因爲需要一些
id
和secret
和redirect_uri
,然後獲取到access_token
@GetMapping("/githubCallback")access_token
public String callback(@RequestParam("code")String code,
@RequestParam("state") String state,
HttpServletResponse response,
Model model) {
setAccessTokenDto(code,state,githubConfig.getClient_id(),githubConfig.getClient_secret(),githubConfig.getRedirect_uri());
String accessToken= githubProvider.getAccessToekn(accessTokenDto);// 獲取access_toke
}
private void setAccessTokenDto(String code, String state, String clientId, String clientSecret, String redirectUri) {
accessTokenDto.setClient_id(clientId);
accessTokenDto.setClient_secret(clientSecret);
accessTokenDto.setCode(code);
accessTokenDto.setRedirect_uri(redirectUri);
accessTokenDto.setState(state);
}
getAccessToken對於如何發送請求這裏使用到了Okhttp,具體學習見okhttp官網文檔對請求的參數和需要什麼配置講解都很清楚了。
可以看到發送到https://github.com/login/oauth/access_token
獲取token信息。
public String getAccessToekn(AccessTokenDto accessTokenDto){
MediaType mediaType = MediaType.parse("application/json; charset=utf-8");
OkHttpClient client = new OkHttpClient();
//將accessTokenDto轉爲json字符串傳入參數
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();
//得到的是類似這樣的字符串,我們需要將它分割,只要access_token部分
//access_token=9566ba3483a556c610be42d44338f3fd16a3b8d1&scope=&token_type=bearer
return string.split("&")[0].split("=")[1];
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
根據獲取到的token信息請求用戶信息
在上面獲取到token以後,再度請求https://api.github.com/user獲取用戶信息。
@GetMapping("/githubCallback")
public String callback(@RequestParam("code")String code,
@RequestParam("state") String state,
HttpServletResponse response,
Model model)
{
setAccessTokenDto(code,state,githubConfig.getClient_id(),githubConfig.getClient_secret(),githubConfig.getRedirect_uri());
String accessToken= githubProvider.getAccessToekn(accessTokenDto);
// 獲取用戶信息。
GithubUser githubUser=githubProvider.getGithubUser(accessToken);
}
void setUserInfo(String token, String name, String avatarUrl, String accountId, String bio) {
GithubUsers user = new GithubUsers();
user.setToken(token);
user.setName(name);
user.setAvatarUrl(avatarUrl);
user.setAccountId(accountId);
user.setBio(bio);
githubUserService.createOrUpdateUser(user);
}
githubProvider
/**
* 根據access_token獲取用戶信息
*
* @param access_token
* @return
*/
public GithubUser getGithubUser(String access_token) {
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url("https://api.github.com/user")
.header("Authorization", "token " + access_token)
.build();
try (Response response = client.newCall(request).execute()){
//得到的是json字符串,因此需要轉爲GithubUser對象
String str = response.body().string();
return JSON.parseObject(str, GithubUser.class);
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
將用戶信息存儲到cookie中:
@GetMapping("/githubCallback")
public String callback(@RequestParam("code")String code,
@RequestParam("state") String state,
HttpServletResponse response,
Model model)
{
setAccessTokenDto(code,state,githubConfig.getClient_id(),githubConfig.getClient_secret(),githubConfig.getRedirect_uri());
String accessToken= githubProvider.getAccessToekn(accessTokenDto);
GithubUser githubUser=githubProvider.getGithubUser(accessToken);
//用戶信息不爲空 存儲起來
if(githubUser!=null && githubUser.getId()!=null)
{
String token= UUID.randomUUID().toString();
setUserInfo(token, githubUser.getName(), githubUser.getAvatarUrl(), "Github-" + githubUser.getId(), githubUser.getBio());
// 存儲。
CookieUtils.setCookie(response, "token", token, COOKIE_EXPIRY);
model.addAttribute("name",githubUser.getName());
return "goods_list";
} else {
throw new GlobalException(CodeMsg.LOGIN_ERROR);
}
}
setCookie
以下代碼的講解可以見獲取cookie信息
public static void setCookie(HttpServletResponse response, String name, String value, int expiry){
Cookie cookie=new Cookie(name,value);
cookie.setMaxAge(expiry);
response.addCookie(cookie);
}
以上就是對主題部分的學習與講解,這裏有想要進行深入視頻學習的可以參見B站8-14p裏有具體的講解。
測試
完成之後我們來看對於我的示例,我們不僅可以使用到我們原來的手機號碼登錄的方式,還可以使用到github第三方登錄。
登錄成功之後頁面,可以看到顯示出我的GitHub名稱。
後記
以上就是關於github授權登錄的學習與講解,也算是我第二次學習的記錄。有什麼具體的問題歡迎私信。文章看起來雖然不是很長,但是要自己全部明白其中的意思,我還是寫了很久的。
下面貼出Github地址源碼地址,若是大家覺得還行,歡迎大家給一個小小star和關注(雖然很菜),後續也會推出更多有價值的實例。