-
Notifications
You must be signed in to change notification settings - Fork 109
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
096a740
commit 0f5fe7b
Showing
7 changed files
with
320 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,187 @@ | ||
<?php | ||
|
||
namespace Yurun\OAuthLogin\GitLab; | ||
|
||
use Yurun\OAuthLogin\ApiException; | ||
use Yurun\OAuthLogin\Base; | ||
|
||
class OAuth2 extends Base | ||
{ | ||
/** | ||
* 授权接口域名. | ||
*/ | ||
public $authDomain = 'https://gitlab.com/'; | ||
|
||
/** | ||
* api域名. | ||
*/ | ||
public $apiDomain = 'https://gitlab.com/api/v4/'; | ||
|
||
/** | ||
* 设置授权接口域名. | ||
* | ||
* @param string $domain | ||
* @return $this | ||
*/ | ||
public function setAuthDomain(string $domain) | ||
{ | ||
$this->authDomain = $domain; | ||
|
||
return $this; | ||
} | ||
|
||
/** | ||
* 设置api域名. | ||
* | ||
* @param string $domain | ||
* @return $this | ||
*/ | ||
public function setApiDomain(string $domain) | ||
{ | ||
$this->apiDomain = $domain; | ||
|
||
return $this; | ||
} | ||
|
||
/** | ||
* 获取登录授权url地址 | ||
* | ||
* @param string $name 跟在域名后的文本 | ||
* @param array $params GET参数 | ||
* | ||
* @return string | ||
*/ | ||
public function getAuthLoginUrl($name, $params = []) | ||
{ | ||
return $this->authDomain . $name . (empty($params) ? '' : ('?' . $this->http_build_query($params))); | ||
} | ||
|
||
/** | ||
* 获取url地址 | ||
* | ||
* @param string $name 跟在域名后的文本 | ||
* @param array $params GET参数 | ||
* | ||
* @return string | ||
*/ | ||
public function getUrl($name, $params = []) | ||
{ | ||
return $this->apiDomain . $name . (empty($params) ? '' : ('?' . $this->http_build_query($params))); | ||
} | ||
|
||
/** | ||
* 第一步:获取登录页面跳转url. | ||
* | ||
* @param string $callbackUrl 登录回调地址 | ||
* @param string $state 状态值,不传则自动生成,随后可以通过->state获取。用于第三方应用防止CSRF攻击,成功授权后回调时会原样带回。一般为每个用户登录时随机生成state存在session中,登录回调中判断state是否和session中相同 | ||
* @param array $scope 请求用户授权时向用户显示的可进行授权的列表。可空 | ||
* | ||
* @return string | ||
*/ | ||
public function getAuthUrl($callbackUrl = null, $state = null, $scope = null) | ||
{ | ||
$option = [ | ||
'client_id' => $this->appid, | ||
'redirect_uri' => null === $callbackUrl ? $this->callbackUrl : $callbackUrl, | ||
'response_type' => 'code', | ||
'state' => $this->getState($state), | ||
'scope' => null === $scope ? $this->scope : $scope, | ||
]; | ||
if (null === $this->loginAgentUrl) { | ||
return $this->getAuthLoginUrl('oauth/authorize', $option); | ||
} else { | ||
return $this->loginAgentUrl . '?' . $this->http_build_query($option); | ||
} | ||
} | ||
|
||
/** | ||
* 第二步:处理回调并获取access_token。与getAccessToken不同的是会验证state值是否匹配,防止csrf攻击。 | ||
* | ||
* @param string $storeState 存储的正确的state | ||
* @param string $code 第一步里$redirectUri地址中传过来的code,为null则通过get参数获取 | ||
* @param string $state 回调接收到的state,为null则通过get参数获取 | ||
* | ||
* @return string | ||
*/ | ||
protected function __getAccessToken($storeState, $code = null, $state = null) | ||
{ | ||
$response = $this->http->post($this->getAuthLoginUrl('oauth/token'), [ | ||
'client_id' => $this->appid, | ||
'client_secret' => $this->appSecret, | ||
'code' => isset($code) ? $code : (isset($_GET['code']) ? $_GET['code'] : ''), | ||
'redirect_uri' => $this->getRedirectUri(), | ||
'state' => isset($state) ? $state : (isset($_GET['state']) ? $_GET['state'] : ''), | ||
'grant_type' => 'authorization_code', | ||
]); | ||
$this->result = $response->json(true); | ||
if (isset($this->result['error_description'])) { | ||
throw new ApiException($this->result['error_description'], 0); | ||
} else { | ||
return $this->accessToken = $this->result['access_token']; | ||
} | ||
} | ||
|
||
/** | ||
* 获取用户资料. | ||
* | ||
* @param string $accessToken | ||
* | ||
* @return array | ||
*/ | ||
public function getUserInfo($accessToken = null) | ||
{ | ||
$token = null === $accessToken ? $this->accessToken : $accessToken; | ||
$this->result = $this->http->header('Authorization', "Bearer {$token}") | ||
->get($this->getUrl('user')) | ||
->json(true); | ||
if (isset($this->result['error_description'])) { | ||
throw new ApiException($this->result['error_description'], 0); | ||
} else { | ||
$this->openid = $this->result['id']; | ||
|
||
return $this->result; | ||
} | ||
} | ||
|
||
/** | ||
* 刷新AccessToken续期 | ||
* | ||
* @param string $refreshToken | ||
* | ||
* @return bool | ||
*/ | ||
public function refreshToken($refreshToken) | ||
{ | ||
$response = $this->http->post($this->getAuthLoginUrl('oauth/token'), [ | ||
'client_id' => $this->appid, | ||
'client_secret' => $this->appSecret, | ||
'refresh_token' => $refreshToken, | ||
'grant_type' => 'refresh_token', | ||
'redirect_uri' => $this->getRedirectUri(), | ||
]); | ||
$this->result = $response->json(true); | ||
if (isset($this->result['error_description'])) { | ||
throw new ApiException($this->result['error_description'], 0); | ||
} else { | ||
return $this->accessToken = $this->result['access_token']; | ||
} | ||
} | ||
|
||
/** | ||
* 检验授权凭证AccessToken是否有效. | ||
* | ||
* @param string $accessToken | ||
* | ||
* @return bool | ||
*/ | ||
public function validateAccessToken($accessToken = null) | ||
{ | ||
try { | ||
$this->getUserInfo($accessToken); | ||
|
||
return true; | ||
} catch (ApiException $e) { | ||
return false; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
<!DOCTYPE html> | ||
<html> | ||
|
||
<head> | ||
<meta charset="UTF-8"> | ||
<title>GitLab登录</title> | ||
</head> | ||
|
||
<body> | ||
<script> | ||
var GWC = { | ||
version: '1.0.0', | ||
urlParams: {}, | ||
appendParams: function(url, params) { | ||
if (params) { | ||
var baseWithSearch = url.split('#')[0]; | ||
var hash = url.split('#')[1]; | ||
for (var key in params) { | ||
var attrValue = params[key]; | ||
if (attrValue !== undefined) { | ||
var newParam = key + "=" + attrValue; | ||
if (baseWithSearch.indexOf('?') > 0) { | ||
var oldParamReg = new RegExp('^' + key + '=[-%.!~*\'\(\)\\w]*', 'g'); | ||
if (oldParamReg.test(baseWithSearch)) { | ||
baseWithSearch = baseWithSearch.replace(oldParamReg, newParam); | ||
} else { | ||
baseWithSearch += "&" + newParam; | ||
} | ||
} else { | ||
baseWithSearch += "?" + newParam; | ||
} | ||
} | ||
} | ||
|
||
if (hash) { | ||
url = baseWithSearch + '#' + hash; | ||
} else { | ||
url = baseWithSearch; | ||
} | ||
} | ||
return url; | ||
}, | ||
getUrlParams: function() { | ||
var pairs = location.search.substring(1).split('&'); | ||
for (var i = 0; i < pairs.length; i++) { | ||
var pos = pairs[i].indexOf('='); | ||
if (pos === -1) { | ||
continue; | ||
} | ||
GWC.urlParams[pairs[i].substring(0, pos)] = decodeURIComponent(pairs[i].substring(pos + 1)); | ||
} | ||
}, | ||
doRedirect: function() { | ||
var code = GWC.urlParams['code']; | ||
var appId = GWC.urlParams['client_id']; | ||
var state = GWC.urlParams['state']; | ||
var response_type = GWC.urlParams['response_type']; | ||
var redirectUri; | ||
|
||
if (!code) { | ||
//第一步,没有拿到code,跳转至授权页面获取code | ||
redirectUri = GWC.appendParams('https://gitlab.com/oauth/authorize', { | ||
'client_id': appId, | ||
'redirect_uri': encodeURIComponent(GWC.appendParams(location.href.split('?')[0], { | ||
'redirect_uri': encodeURIComponent(GWC.urlParams['redirect_uri']), | ||
})), | ||
'state': state, | ||
'response_type': response_type, | ||
}); | ||
} else { | ||
//第二步,从授权页面跳转回来,已经获取到了code,再次跳转到实际所需页面 | ||
redirectUri = GWC.appendParams(GWC.urlParams['redirect_uri'], { | ||
'code': code, | ||
'state': state | ||
}); | ||
} | ||
|
||
location.href = redirectUri; | ||
} | ||
}; | ||
|
||
GWC.getUrlParams(); | ||
GWC.doRedirect(); | ||
</script> | ||
</body> | ||
|
||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
<?php | ||
|
||
require __DIR__ . '/common.php'; | ||
$gitlabOAuth = new \Yurun\OAuthLogin\GitLab\OAuth2($GLOBALS['oauth_gitlab']['appid'], $GLOBALS['oauth_gitlab']['appkey'], $GLOBALS['oauth_gitlab']['callbackUrl']); | ||
// 解决只能设置一个回调域名的问题,下面地址需要改成你项目中的地址,可以参考./loginAgent.php写法 | ||
// $gitlabOAuth->loginAgentUrl = 'http://test.com/test/GitLab/loginAgent.php'; | ||
|
||
var_dump( | ||
'access_token:', $gitlabOAuth->getAccessToken($_SESSION['YURUN_GITLAB_STATE']), | ||
'我也是access_token:', $gitlabOAuth->accessToken, | ||
'请求返回:', $gitlabOAuth->result | ||
); | ||
var_dump( | ||
'用户资料:', $gitlabOAuth->getUserInfo(), | ||
'openid:', $gitlabOAuth->openid | ||
); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
<?php | ||
|
||
require dirname(__DIR__) . '/common.php'; | ||
$GLOBALS['oauth_gitlab'] = [ | ||
'appid' => '', | ||
'appkey' => '', | ||
'callbackUrl' => 'http://test.com/test/GitLab/callback.php', | ||
]; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
<?php | ||
|
||
require __DIR__ . '/common.php'; | ||
$gitlabOAuth = new \Yurun\OAuthLogin\GitLab\OAuth2($GLOBALS['oauth_gitlab']['appid'], $GLOBALS['oauth_gitlab']['appkey'], $GLOBALS['oauth_gitlab']['callbackUrl']); | ||
|
||
// 解决只能设置一个回调域名的问题,下面地址需要改成你项目中的地址,可以参考./loginAgent.php写法 | ||
// $gitlabOAuth->loginAgentUrl = 'http://localhost/test/GitLab/loginAgent.php'; | ||
|
||
// 所有为null的可不传,这里为了演示和加注释就写了 | ||
$url = $gitlabOAuth->getAuthUrl( | ||
null, // 回调地址,登录成功后返回该地址 | ||
null, // state 为空自动生成 | ||
null // scope 只要登录默认为空即可 | ||
); | ||
$_SESSION['YURUN_GITLAB_STATE'] = $gitlabOAuth->state; | ||
header('location:' . $url); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
<?php | ||
|
||
require __DIR__ . '/common.php'; | ||
$gitlabOAuth = new \Yurun\OAuthLogin\GitLab\OAuth2(); | ||
$gitlabOAuth->displayLoginAgent(); |