以GitHub用户权限登录项目

本次整理的博客内容是关于在项目中整合用 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;
    }
}

写在最后

我运行代码成功后,得到的用户返回信息为:

再贴上最后一张通过github拉取用户登录信息的逻辑通信图,原理是这样的,数据是这样传输的,结果是这样得来的:

猜你喜欢

转载自www.cnblogs.com/yuqiliu/p/12531300.html