背景:最近一直在做第三方平台登录的相关工作,由于要接入这些平台需要涉及到各个平台的开发者账号的申请工作,而企业级的开发者账号申请就更麻烦了,但是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用户的用户信息了,到这里就大功告成了 。
相关资料