记录一次对接Github授权登陆遇到的问题及经验分享!
前两天对接了Gitee,可以说,很快啊!非常快!就对接好了,半个小时都没要到!大大鼓舞了我的自信心!结果今晚对接Github授权登陆,MD,从完善8点吃完饭,一直对接到现在!主要是耽误时间的是卡到了 curl
设置 headers
和 github 对接接口除了基本的常见鉴权 Authorization
字段,还需要一个额外的 User-Agent
,我滴妈,就这一个 User-Agent
字段,加上本身对 curl
的 headers
写法不熟,足足卡了一晚上!
申请步骤
- 首先你肯定得有Github账号
- 其次你自己得登录这个账号
- 打开 https://github.com/settings/developers 这个链接,创建应用
- 填写对应信息
- 开始开发!
成品分享
因为昨天已经分享了对接gitee的经验,对接github其实也大同小异,因此我直接就先直接上成品代码供大家参考了!
目录结构
网络请求工具类封装
这个工具类我在昨天的基础上进一步优化了一下,支持设置头了!因为我项目是使用的 ThinkPHP 5.1
,避免跟框架的 Request
类冲突,因此我给改名成 HttpReuqest
了!
<?php
namespace app\common\util;
/**
* 发送网络请求工具类
* @author huangjunjie
* @version 1.0.1
*/
class HttpRequest
{
/**
* 发送 post 请求
* @param $url
* @param array $data
* @param array $header
* @param bool $json
* @return mixed
*/
public function post($url, $data = array(), $header = array(), $json = false)
{
// 初始化
$curl = curl_init();
// 设置抓取的url
curl_setopt($curl, CURLOPT_URL, $url);
// 设置请求头
curl_setopt($curl, CURLOPT_HTTPHEADER, $header);
// 设置头文件的信息作为数据流输出
curl_setopt($curl, CURLOPT_HEADER, 0);
// 设置获取的信息以文件流的形式返回,而不是直接输出。
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
// 设置post方式提交
curl_setopt($curl, CURLOPT_POST, 1);
// 设置post数据
curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
// 关闭证书校验
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
// 执行命令
$output = curl_exec($curl);
// 关闭URL请求
curl_close($curl);
return $json ? json_decode($output, true) : $output;
}
/**
* 发送 GET 请求
* @param $url
* @param array $data
* @param array $header
* @param bool $json
* @return mixed
*/
public function get($url, $data = array(), $header = array(), $json = false)
{
// 初始化
$curl = curl_init();
// 设置选项,包括URL
$query = http_build_query($data);
// 拼接url
$url = $url . '?' . $query;
// 设置抓取的url
curl_setopt($curl, CURLOPT_URL, $url);
// 设置头文件的信息作为数据流输出
curl_setopt($curl, CURLOPT_HEADER, 0);
// 设置请求头
curl_setopt($curl, CURLOPT_HTTPHEADER, $header);
// 设置获取的信息以文件流的形式返回,而不是直接输出。
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
// 关闭证书校验
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
// 执行并获取HTML文档内容
$output = curl_exec($curl);
// 释放curl句柄
curl_close($curl);
return $json ? json_decode($output, true) : $output;
}
/**
* 发送 POST 请求,且确认返回值为json
* @param $url
* @param array $data
* @param array $header
* @return mixed
*/
public function postJson($url, $data = array(), $header = array())
{
return $this->post($url, $data, $header, true);
}
/**
* 发送 GET 请求,且确认返回值为json
* @param $url
* @param array $data
* @param array $header
* @return mixed
*/
public function getJson($url, $data = array(), $header = array())
{
return $this->get($url, $data, $header, true);
}
}
配置文件分享
我比较喜欢把配置写在 common.php 里,这个因人而异,这里我直接把我完整的佩服发上来,也包含了 Gitee
的配置!
<?php
// 码云授权登陆配置,相关页面:https://gitee.com/oauth/applications
const AUTH_LOGIN_GITEE_CLIENT_ID = "换成你自己的 CLIENT_ID";
const AUTH_LOGIN_GITEE_CLIENT_SECRET = "换成你自己的!CLIENT_SECRET";
const AUTH_LOGIN_GITEE_REDIRECT_URI = "换成你自己的回调地址!";
const AUTH_LOGIN_GITEE_GET_TOKEN = "https://gitee.com/oauth/token";
const AUTH_LOGIN_GITEE_GET_USERINFO = "https://gitee.com/api/v5/user";
const AUTH_LOGIN_GITEE_AUTH_URI = "https://gitee.com/oauth/authorize";
// Github授权登陆配置,相关页面:https://github.com/settings/developers
const AUTH_LOGIN_GITHUB_CLIENT_ID = "换成你自己的 CLIENT_ID";
const AUTH_LOGIN_GITHUB_CLIENT_SECRET = "换成你自己的!CLIENT_SECRET";
const AUTH_LOGIN_GITHUB_REDIRECT_URI = "换成你自己的回调地址!";
const AUTH_LOGIN_GITHUB_GET_TOKEN = "https://github.com/login/oauth/access_token";
const AUTH_LOGIN_GITHUB_GET_USERINFO = "https://api.github.com/user";
const AUTH_LOGIN_GITHUB_AUTH_URI = "https://github.com/login/oauth/authorize";
业务代码分享
<?php
namespace app\oauth\controller;
use app\common\util\HttpRequest;
use think\facade\Request;
use think\response\Redirect;
/**
* 这个控制器修改了下,不继承 Controller了,方便你们复制直接用
* @author huangjunjie
* @version 1.0.0
*/
class Platform
{
/**
* 码云授权登陆,也负责承担回调页面的责任
* @return array|Redirect
*/
public function gitee()
{
// 通过回调函数获取code
$code = Request::get("code");
// 如果没有code则自动重定向到授权页面
if (is_null($code)) {
$url = AUTH_LOGIN_GITEE_AUTH_URI;
$query = http_build_query([
"client_id" => AUTH_LOGIN_GITEE_CLIENT_ID,
"redirect_uri" => AUTH_LOGIN_GITEE_REDIRECT_URI,
"response_type" => "code"
]);
return redirect($url . "?" . $query);
} else {
// 获取access_token
$request = new HttpRequest();
$login = $request->postJson(AUTH_LOGIN_GITEE_GET_TOKEN, [
"grant_type" => "authorization_code",
"code" => $code,
"client_id" => AUTH_LOGIN_GITEE_CLIENT_ID,
"redirect_uri" => AUTH_LOGIN_GITEE_REDIRECT_URI,
"client_secret" => AUTH_LOGIN_GITEE_CLIENT_SECRET,
]);
// 如果报错提示,没报错则请求获取用户信息接口
if (isset($login["error"])) {
return ["code" => 401, "msg" => $login["error_description"]];
} else {
// Gitee 这里是直接通过 GET 参数传递 Token
$userinfo = $request->getJson(AUTH_LOGIN_GITEE_GET_USERINFO, ["access_token" => $login["access_token"]]);
// 这里返回获得的用户信息,具体可自己根据实际业务继续走
return ["code" => 200, "data" => $userinfo];
}
}
}
/**
* Github授权登陆,也负责承担回调页面的责任
* @return array|Redirect
*/
public function github()
{
// 通过回调函数获取code
$code = Request::get("code");
// 如果没有code则自动重定向到授权页面
if (is_null($code)) {
$url = AUTH_LOGIN_GITHUB_AUTH_URI;
$query = http_build_query([
"client_id" => AUTH_LOGIN_GITHUB_CLIENT_ID,
"redirect_uri" => AUTH_LOGIN_GITHUB_REDIRECT_URI
]);
return redirect($url . "?" . $query);
} else {
// 获取access_token
$request = new HttpRequest();
$login = $request->post(AUTH_LOGIN_GITHUB_GET_TOKEN, [
"code" => $code,
"client_id" => AUTH_LOGIN_GITHUB_CLIENT_ID,
"redirect_uri" => AUTH_LOGIN_GITHUB_REDIRECT_URI,
"client_secret" => AUTH_LOGIN_GITHUB_CLIENT_SECRET,
]);
// 这是里Github需要注意的,Github默认返回不是json,而是一个普通的query字符串
// 因此这里我们使用PHP内置的 parse_str 将 query 字符串专为 json 数据
parse_str($login, $json);
// 如果报错提示,没报错则请求获取用户信息接口
if (isset($json["error"])) {
return ["code" => 401, "msg" => $json["error_description"]];
} else {
// 注意!这里Github需要在常规鉴权 Authorization 字段的基础上
// 还需要额外包含一个 User-Agent 字段,这里为了方便,就直接把默认的头部对应字段转发过去了
// 按照 Github 官方要求, 这里的 User-Agent 字段应该是联系方式或者应用地址
// Github 官方的意思就是:如果你敢捣乱,就方便我找到你!嗯!
$userinfo = $request->getJson(AUTH_LOGIN_GITHUB_GET_USERINFO, [], [
"Authorization: Bearer " . $json["access_token"],
"User-Agent: " . Request::header("user-agent")
]);
// 这里返回获得的用户信息,具体可自己根据实际业务继续走
return ["code" => 200, "data" => $userinfo];
}
}
}
}