背景:最近一直在做第三方平臺登錄的相關工作,由於要接入這些平臺需要涉及到各個平臺的開發者賬號的申請工作,而企業級的開發者賬號申請就更麻煩了,但是github的開發者賬號就很簡單,所以當時就以Github作爲示例了。
整個第三方平臺的開發流程圖如下
名詞解釋
APP_ID | 在第三方平臺申請的APP標識 |
APP_SECRETE | 在第三方平臺申請的APP祕鑰(注意保密) |
CODE | 預授權碼 |
ACCESS_TOKEN | 授權碼 |
OPEN_ID | 第三方平臺的用戶ID |
流程圖文字描述:
首先用戶在頁面選擇觸發具體的第三方平臺登錄,此時我們的應用系統要攜帶我們的APP_ID+回調地址訪問第三方平臺的授權頁面,當用戶在第三方平臺成功的登錄後,第三方平臺會自動攜帶CODE調用回調地址將用戶重定向到我們的應該系統中,此時我們在使用CODE+APP_SECRETE調用第三方平臺提供的接口,就可以得到ACCESS_TOKEN了,最後再通過這ACCESS_TOKEN調用第三方平臺提供的接口即可得到用戶的OPEN_ID(還可以取到其他的用戶信息,比如:用戶名、圖像等).
注意:
1.在跳轉到第三方的授權登錄頁面時,有的第三方平臺會檢查APP_ID和回調地址是否與開發者賬號中配置的應用信息是否一致,所以請認真配置
2.第三方平臺的處理流程在細節上差異很大,但是總體流程都是大同小異的,文末將附上相關平臺的接口鏈接
下面開始正式搭建系統
1.首先在Github上配置相關應用信息
登錄Github --> settings --> Applications --> Developer settings
然按照表單內容填寫即可
註冊完成後就可以看到應用的相關信息了
到這裏我們的準備工作就完成了,下面開始寫代碼,首先配置pom.xml引入相關的依賴包
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.8.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>auth.demo</groupId>
<artifactId>demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>demo</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.scribe</groupId>
<artifactId>scribe</artifactId>
<version>1.3.7</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.41</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
代碼結構如下,主要的文件已經用紅圈圈出了
具體步驟:
1.新建index.html文件,主要負責點擊後,將請求定位到我們的登錄頁面
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1><a href="http:/127.0.0.1:12345/login/github">Github登錄</a></h1>
</body>
</html>
2.增加GithubAuthController.java
package qn.auth.demo.demo.github.controller;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import qn.auth.demo.demo.github.service.GithubAuthService;
import javax.servlet.http.HttpServletResponse;
/**
* @author callmevvv
* @date 2019/9/21
* @description
*/
@Slf4j
@Controller
@RequestMapping("/github")
@AllArgsConstructor
public class GithubAuthController {
/**
* github認證的業務處理類
*/
private GithubAuthService githubAuthService;
/**
* 跳轉到github的授權登錄頁面
* @param response
* @throws Exception
*/
@GetMapping("/login")
public void showLoginPage(HttpServletResponse response) throws Exception {
String path = githubAuthService.getGithubAuthPath();
response.sendRedirect(path);
}
/**
* 在github頁面登錄成功後,github會回調這個
* @param code
* @return
*/
@GetMapping(value = "/callback")
@ResponseBody
public String callback(@RequestParam(value = "code") String code) {
return githubAuthService.callback(code);
}
}
3.新建GithubAuthService.java接口
package qn.auth.demo.demo.github.service;
/**
* @author callmevvv
* @date 2019/9/21
* @description
*/
public interface GithubAuthService {
/**
* 獲取github的授權地址
* @return
*/
String getGithubAuthPath();
/**
* 在github頁面登錄成功後,回調的處理方法
* @param code
* @return
*/
String callback(String code);
}
4.增加GithubAuthServiceImpl.java接口實現類
package qn.auth.demo.demo.github.service.impl;
import com.sun.deploy.net.HttpUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.http.converter.ByteArrayHttpMessageConverter;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.ResourceHttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.http.converter.support.AllEncompassingFormHttpMessageConverter;
import org.springframework.http.converter.xml.SourceHttpMessageConverter;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriComponentsBuilder;
import qn.auth.demo.demo.github.service.GithubAuthService;
import javax.xml.transform.Source;
import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
/**
* @author callmevvv
* @date 2019/9/21
* @description
*/
@Slf4j
@Service
public class GithubAuthServiceImpl implements GithubAuthService {
/**
* github的授權地址
*/
private final static String GITHUB_CODE_URL = "https://github.com/login/oauth/authorize?client_id=%s&redirect_uri=%s&state=%s";
/**
* 獲取github用戶ACCESS_TOKEN地址
*/
private final static String GITHUB_TOKEN_URL = "https://github.com/login/oauth/access_token?client_id=%s&client_secret=%s&code=%s";
/**
* 獲取github用戶信息
*/
private final static String GITHUB_USER_URL = "https://api.github.com/user?access_token=%s";
/**
* 服務器github的客戶端ID
*/
private final static String CLIENT_ID = "Iv1.xxxxxxxx";
/**
* 應用祕鑰
*/
private final static String CLIENT_SECRETE = "c26xxxxxxxxxxxxxxxxxxxxx4e5";
/**
* github的回調地址
*/
private final static String REDIRECT_URL = "http://127.0.0.1:12345/github/callback";
/**
*
*/
private final static String ACCESS_TOKEN_NAME = "access_token";
/**
* 該字段的值會回傳回來
*/
private final static String STATE = "true";
/**
* 本系統訪問github登錄頁面的URL地址
*/
static String APP_GITHUB_CODE_URL = String.format(GITHUB_CODE_URL,CLIENT_ID,REDIRECT_URL,STATE);
@Override
public String getGithubAuthPath() {
return APP_GITHUB_CODE_URL;
}
@Override
public String callback(String code) {
String accessToken = getAccessToken(code);
return getOpenId(accessToken);
}
public String getAccessToken(String code) {
String url = String.format(GITHUB_TOKEN_URL,CLIENT_ID,CLIENT_SECRETE,code);
UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(url);
URI uri = builder.build().encode().toUri();
String resp = getRestTemplate().getForObject(uri, String.class);
if (resp.contains(ACCESS_TOKEN_NAME)) {
Map<String, String> map = getParam(resp);
String access_token = map.get(ACCESS_TOKEN_NAME);
return access_token;
} else {
throw new RuntimeException(resp);
}
}
public String getOpenId(String accessToken) {
String url = String.format(GITHUB_USER_URL,accessToken);
UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(url);
URI uri = builder.build().encode().toUri();
String resp = getRestTemplate().getForObject(uri, String.class);
log.error("getAccessToken resp = "+resp);
return resp;
}
public RestTemplate getRestTemplate() {// 手動添加
SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
requestFactory.setReadTimeout(120000);
List<HttpMessageConverter<?>> messageConverters = new LinkedList<>();
messageConverters.add(new ByteArrayHttpMessageConverter());
messageConverters.add(new StringHttpMessageConverter(StandardCharsets.UTF_8));
messageConverters.add(new ResourceHttpMessageConverter());
messageConverters.add(new SourceHttpMessageConverter<Source>());
messageConverters.add(new AllEncompassingFormHttpMessageConverter());
messageConverters.add(new MappingJackson2HttpMessageConverter());
RestTemplate restTemplate = new RestTemplate(messageConverters);
restTemplate.setRequestFactory(requestFactory);
return restTemplate;
}
private Map<String, String> getParam(String string) {
Map<String, String> map = new HashMap();
String[] kvArray = string.split("&");
for (int i = 0; i < kvArray.length; i++) {
String[] kv = kvArray[i].split("=");
if(kv != null){
if(kv.length == 1){
map.put(kv[0], null);
}else if(kv.length == 2){
map.put(kv[0], kv[1]);
}
}
}
return map;
}
}
到這裏代碼就已經寫完了,下面只需要啓動程序,然後訪問index.html文件即可
點擊後將會跳轉到github的登錄頁面,注意看上面的地址
最後在github登錄成功後,將會得到下面的類似結果
這樣我們就得到了當前登錄github用戶的用戶信息了,到這裏就大功告成了 。
相關資料