第三方登錄 ---Github

背景:最近一直在做第三方平臺登錄的相關工作,由於要接入這些平臺需要涉及到各個平臺的開發者賬號的申請工作,而企業級的開發者賬號申請就更麻煩了,但是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用戶的用戶信息了,到這裏就大功告成了 。


相關資料

QQ開發文檔

微博開發文檔

微信開發文檔

企業微信

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章