首先介绍下实现的 结构
类似 QQ一键登录 用户点击某个网站 然后跳转到QQ登录页面 确定登录之后 在回来这个网站 并且登录
我现在需要2个网址 http://www.test.com 应用网址 http://www.cuzn-oauth.com oauth验证网址
过程就是 我的网址 用指定的key和秘钥 请求一个oauth 指定接口 获取 code 然后用得到的 code 来获取access_token 最后通过 access_token来获取 对应的信息
其实 oauth可以当做一个代理 下面这个是我写的代理过程
http://www.wulinlw.org/post-511.html
下面开始 写http://www.test.com 的 代码
有一个 index.php文件
<?php
$authorized = empty ( $_POST ['authorized'] ) ? '' : $_POST ['authorized'];
include 'oauth_sdk_php.php';
$oauth = new OAuth ( 'testclient', 'testpass' );
if (! empty ( $authorized )) {
$getAuthorizeURL = $oauth->getAuthorizeURL ();
header ( "location: $getAuthorizeURL" );
}
$data['code'] = empty ( $_GET ['code'] ) ? '' : $_GET ['code'];
if (! empty ( $data['code'] )) {
$url = $oauth->getAccessTokenURL ( $data);
$getAccessToken = $oauth->getAccessToken ( $url, $data );
$getAccessToken = json_decode ( $getAccessToken['content'], true );
if (! empty ( $getAccessToken ['access_token'] )) {
$resourceURL = $oauth->url.'/oauth/resource/';
$extheaders = array(
"Authorization : Bearer ".$getAccessToken ['access_token'],
"cuzncuzn : asdfasdf"
);
$ret = $oauth->getResource ($resourceURL,array(),"GET", $extheaders);
var_dump($ret);die;
$ret = json_decode ( $ret['content'], true );
if ($ret ['success']) {
header ( "location: http://www.demo.com/t.php" );
}
}else{
var_dump($getAccessToken);die;
}
}
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>是否授权</title>
</head>
<body>
<form method="post" action="">
<input type="submit" name="authorized" value="一键登陆">
</form>
</body>
</html>
和一个sdk
<?php
/**
* OAuth授权类
*
* @author cuzn
* @version 1.0 2015-07-15
*/
class OAuth{
public $url = 'http://www.yy-oauth.com';
public $client_id = '';
public $client_secret = '';
public $oauthURL = '/oauth/index/';
public $accessTokenURL = '/oauth/token/';
// public $resourceURL = '/oauth/resource/';
public $refreshURL = '/oauth/refresh/';
/**
* 初始化
*
* @param $client_id 即
* appid
* @param $client_secret 即
* appkey
* @return
*
*/
public function __construct($client_id, $client_secret) {
if (! $client_id || ! $client_secret)
exit ( 'client_id or client_secret is null' );
$this->client_id = $client_id;
$this->client_secret = $client_secret;
}
/**
* 获取授权URL
*
* $client_id 应用用户名
* $response_type 授权类型,为code
* return string
*/
public function getAuthorizeURL($params=array()) {
$params = array_merge ( array (
'client_id' => $this->client_id ,
'response_type' => 'code' ,
'state' => 'xyz'
), $params );
return $this->url . $this->oauthURL . '?' . http_build_query ( $params );
}
/**
* 获取请求token的url
*
* @param $data['code'] 调用oauth时返回的code
* @param $data['scope'] 调用oauth时返回的scope
* @return string
*/
public function getAccessTokenURL($data) {
$params = array_merge ( array (
'client_id' => $this->client_id ,
'client_secret' => $this->client_secret ,
'grant_type' => 'authorization_code'
), $data );
return $this->url . $this->accessTokenURL . '?' . http_build_query ( $params );
}
/**
* 获取请求token的
*
* @param
* $data['code']
* @param $data['client_secret'] 应用用户秘钥
* @param $data['client_id'] 应用用户名
* @param $data['grant_type'] 类型
* @return array
*/
public function getAccessToken($url, $data) {
$data = array_merge ( array (
'client_id' => $this->client_id ,
'client_secret' => $this->client_secret ,
'grant_type' => 'authorization_code'
), $data );
$ret = $this->getResource ( $url, $data, "POST" );
return $ret;
}
/**
* 根据 refresh_token 重新生成 access_token
*
* @param $data['client_secret'] 应用用户秘钥
* @param $data['client_id'] 应用用户名
* @param $data['refresh_token'] refresh_token
* @param $data['grant_type'] 类型
* @return array
*/
public function getRefreshToken($data) {
$data = array_merge ( array (
'client_id' => $this->client_id ,
'client_secret' => $this->client_secret ,
'grant_type' => 'refresh_token'
), $data );
$ret = $this->getResource ( $this->url . $this->refreshURL, $data, "POST" );
return $ret;
}
/**
* 发起一个HTTP/HTTPS的请求
*
* @param $url 接口的URL
* @param $params 接口参数
* array('content'=>'test', 'format'=>'json');
* @param $method 请求类型
* GET|POST
* @param $extheaders 扩展的包头信息
* 比如 $extheaders = array("authorization : Bearer $access_token");
* @param $multi 图片信息
* @return string
*/
public function getResource($url, $params, $method = "GET", $extheaders = array(), $multi = false) {
if (! function_exists ( 'curl_init' ))
exit ( 'Need to open the curl extension' );
$method = strtoupper ( $method );
$ci = curl_init ();
curl_setopt ( $ci, CURLOPT_USERAGENT, 'PHP-SDK OAuth2.0' );
curl_setopt ( $ci, CURLOPT_CONNECTTIMEOUT, 3 );
curl_setopt ( $ci, CURLOPT_TIMEOUT, 3 );
curl_setopt ( $ci, CURLOPT_RETURNTRANSFER, true );
curl_setopt ( $ci, CURLOPT_SSL_VERIFYPEER, false );
curl_setopt ( $ci, CURLOPT_SSL_VERIFYHOST, false );
curl_setopt ( $ci, CURLOPT_HEADER, 1 );
// curl_setopt ( $ci, CURLOPT_HEADER, false );
curl_setopt($ci, CURLOPT_CUSTOMREQUEST, $method);
$headers = ( array ) $extheaders;
$headers = array_merge ( array (
"X-Forwarded-For: ".$this->getIp()
), $headers );
switch ($method) {
case 'POST' :
curl_setopt ( $ci, CURLOPT_POST, TRUE );
if (! empty ( $params )) {
if ($multi) {
foreach ( $multi as $key => $file ) {
$params [$key] = '@' . $file;
}
curl_setopt ( $ci, CURLOPT_POSTFIELDS, $params );
$headers [] = 'Expect: ';
} else {
curl_setopt ( $ci, CURLOPT_POSTFIELDS, http_build_query ( $params ) );
}
}
break;
case 'DELETE' :
case 'PUT' :
curl_setopt ( $ci, CURLOPT_POSTFIELDS, http_build_query ( $params ) );//设置提交的字符串
break;
case 'GET' :
if (! empty ( $params )) {
$url = $url . (strpos ( $url, '?' ) ? '&' : '?') . (is_array ( $params ) ? http_build_query ( $params ) : $params);
}
break;
}
curl_setopt ( $ci, CURLINFO_HEADER_OUT, TRUE );
curl_setopt ( $ci, CURLOPT_URL, $url );
if ($headers) {
curl_setopt ( $ci, CURLOPT_HTTPHEADER, $headers );
}
$response = curl_exec ( $ci );
// $response['tmpInfo'] = curl_exec ( $ci );
// $response['getinfo'] = curl_getinfo($ci);
curl_close ( $ci );
$result = explode("\r\n\r\n", $response, 2);
$headArr = explode("\n",$result[0]);
$ret = array(
'status' => '200',
'header' => $headArr,
'content' => $result[1]
);
return $ret;
}
// Figure out requester's IP to shipt it to X-Forwarded-For
public function getIp(){
$ip = '';
if (!empty($_SERVER['HTTP_CLIENT_IP'])) {
$ip = $_SERVER['HTTP_CLIENT_IP'];
//echo "HTTP_CLIENT_IP: ".$ip;
} elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
$ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
//echo "HTTP_X_FORWARDED_FOR: ".$ip;
} else {
$ip = $_SERVER['REMOTE_ADDR'];
//echo "REMOTE_ADDR: ".$ip;
}
return $ip;
}
}
首先在YII2里面装Oauth主键
具体参考 http://bshaffer.github.io/oauth2-server-php-docs/
我这里用 composer 安装
{
"require": {
"bshaffer/oauth2-server-php": "~1.7",
... },
... }
然后 安装/vendor/bshaffer/oauth2-server-php
在 components新建一个My_oauth.php 参考 http://www.wulinlw.org/post-511.html
<?php
namespace app\components;
use OAuth2;
use Yii;
use app\models\clients;
class My_oauth{
public $server = "";
public $storage = "";
function server() {
$dsn = Yii::$app->db->dsn;
$username = Yii::$app->db->username;
$password = Yii::$app->db->password;
// error reporting (this is a demo, after all!)
ini_set ( 'display_errors', 1 );
error_reporting ( E_ALL );
// Autoloading (composer is preferred, but for this example let's just do this)
// require_once('../src/OAuth2/Autoloader.php');
OAuth2\Autoloader::register ();
// $dsn is the Data Source Name for your database, for exmaple "mysql:dbname=my_oauth2_db;host=localhost"
$this->storage = new OAuth2\Storage\Pdo ( array (
'dsn' => $dsn ,
'username' => $username ,
'password' => $password
) );
// Pass a storage object or array of storage objects to the OAuth2 server class
$config = array (
"access_lifetime" => 7200
);
$server = new OAuth2\Server ( $this->storage, $config );
// Add the "Client Credentials" grant type (it is the simplest of the grant types)
$server->addGrantType ( new OAuth2\GrantType\ClientCredentials ( $this->storage ) );
// Add the "Authorization Code" grant type (this is where the oauth magic happens)
$server->addGrantType ( new OAuth2\GrantType\AuthorizationCode ( $this->storage ) );
// add the grant type to your OAuth server
$server->addGrantType ( new OAuth2\GrantType\RefreshToken ( $this->storage, array (
"always_issue_new_refresh_token" => true ,
"unset_refresh_token_after_use" => true ,
"refresh_token_lifetime" => 2419200
) ) );
$this->server = $server;
}
/*
* 访问api前检查AccessToken
*/
function checkAccessToken(){
// Handle a request for an OAuth2.0 Access Token and send the response to the client
if (! $this->server->verifyResourceRequest ( OAuth2\Request::createFromGlobals ())) {
// header('HTTP/1.1 403 Forbidden');
$return = [
'status' => '401',
'message' => 'AccessToken Unauthorized '
];
// echo json_encode ($return );
$this->server->getResponse()->setParameters($return);
$this->server->getResponse()->setStatusCode(401);
$this->server->getResponse()->send();
exit;
}
}
/*
* 访问api前检查AccessToken
*/
function checkScope($client_id,$scope){
$M_clients = new clients();
$getScope = $M_clients->getClientsByClientId($client_id);
$scopeArr = explode(" ",$getScope['scope']);
if(!in_array($scope, $scopeArr)){
// header('HTTP/1.1 403 Forbidden');
$return = [
'status' => '401',
'message' => 'Scope Unauthorized '
];
// echo json_encode ($return );
$this->server->getResponse()->setParameters($return);
$this->server->getResponse()->setStatusCode(401);
$this->server->getResponse()->send();
exit;
}
}
// Figure out requester's IP to shipt it to X-Forwarded-For
public function getIp(){
$ip = '';
if (!empty($_SERVER['HTTP_CLIENT_IP'])) {
$ip = $_SERVER['HTTP_CLIENT_IP'];
//echo "HTTP_CLIENT_IP: ".$ip;
} elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
$ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
//echo "HTTP_X_FORWARDED_FOR: ".$ip;
} else {
$ip = $_SERVER['REMOTE_ADDR'];
//echo "REMOTE_ADDR: ".$ip;
}
return $ip;
}
}
然后 在 Controller新建OauthController .php 控制器
<?php
namespace app\controllers;
use Yii;
use yii\web\Controller;
use OAuth2;
use app\components\My_oauth;
use app\components\OP_CAS;
class OauthController extends Controller{
public $enableCsrfValidation = false;
public $layout = false;
public $server = "";
public $storage = "";
public $My_oauth = "";
function init() {
$this->My_oauth = new My_oauth ();
$this->My_oauth->server ();
$this->server = $this->My_oauth->server;
$this->storage = $this->My_oauth->storage;
}
/*
* 跳转 传递get 然后验证用户的资料在回调 返回code
*/
function actionIndex() {
$req = yii::$app->request;
$request = OAuth2\Request::createFromGlobals ();
$response = new OAuth2\Response ();
// validate the authorize request
if (! $this->server->validateAuthorizeRequest ( $request, $response )) {
$response->send ();
die ();
}
$urlGet ['response_type'] = $req->get ( "response_type" );
$urlGet ['client_id'] = $req->get ( "client_id" );
$urlGet ['state'] = $req->get ( "state" );
$ticket = $req->get ( "ticket", "" );
if ($ticket) {
$op_cas = new OP_CAS ( 'login.gamebar.com', 'gb', 1 );
$userinfo = $op_cas->get_userinfo ();
if ($userinfo ['username'] && $userinfo ['uid']) {
$this->server->handleAuthorizeRequest ( $request, $response, true ,$userinfo ['uid']);
$url = $response->getHttpHeader ( 'Location' );
$this->redirect ( $url );
}
} else {
return $this->render ( 'index' );
}
}
/*
* 接口
*
* 参数
* $data['grant_type'] = 'authorization_code'; //类型
* $data['client_id'] = 'testclient'; //应用id
* $data['client_secret'] = 'testpass'; //应用秘钥
* $data['code'] = $code; //code
* 返回 json 数据
*/
function actionToken() {
$ret = $this->server->handleTokenRequest ( OAuth2\Request::createFromGlobals () );
$ret = substr ( $ret, strpos ( $ret, '{' ) -1 );
return $ret;
}
/*
* 接口
* 参数 $data['access_token']; //access_token值 http header "Authorization : Bearer ".$data ['access_token'],
* 返回 access_token
*/
function actionResource() {
//获取 访问的model和action
$requestedRoute = Yii::$app->requestedRoute;
//获取 AccessTokenData 值
$getAccessTokenData = $this->server->getAccessTokenData(OAuth2\Request::createFromGlobals () );
//验证 传来的access_token是否正确
$this->My_oauth->checkAccessToken();
//根据 client_id 查询 scope 是否有访问权限
$this->My_oauth->checkScope($getAccessTokenData['client_id'],$requestedRoute);
//获取access_token
return json_encode ( array (
'success' => '200' ,
'message' => 'You accessed my APIs!'
) );
}
/*
* 接口 RefreshToken
* $data['grant_type'] = 'refresh_token'; //类型
* $data['client_id'] = 'testclient'; //应用id
* $data['client_secret'] = 'testpass'; //应用秘钥
* 参数 $data['access_token']; //access_token值
* 返回 array
*/
function actionRefresh(){
$ret = $this->server->handleTokenRequest ( OAuth2\Request::createFromGlobals () );
$ret = substr ( $ret, strpos ( $ret, '{' ) -1 );
return $ret;
}
}
以上只是零散的实现代码
声明:此文系舞林cuzn(www.wulinlw.org)原创稿件,转载请保留版权