顯示具有 library 標籤的文章。 顯示所有文章
顯示具有 library 標籤的文章。 顯示所有文章

2017年10月27日 星期五

Firebase 開發筆記 - 使用 PHP 之 Verify ID tokens using a third-party JWT library

PHP 漸漸地越來越沒有愛了 XD Ubuntu server 預設還是停留在 php5.5 系列,而許多套件都進入了 PHP 7 世界了。不知是不是這樣子,所以官方沒再推出 PHP SDK ?於是乎,只好自己刻一下下。也順勢認識 JWT,第一次認識是在 APNs Auth Key 的使用,沒想到這麼快又要上戰場了 XD

網路資源:
若覺得很煩,就直接用 https://github.com/kreait/firebase-php 吧!這篇專注在紀錄 JWT - Firebase 的使用和驗證。

用法:

$ mkdir jwt-3.2.2 ; cd jwt-3.2.2 ; composer require lcobucci/jwt
$ vim test.php
<?php
require 'vendor/autoload.php';

$token_string = 'XXXXXXXXXXX';

$signer = new Lcobucci\JWT\Signer\Rsa\Sha256();
$keychain = new Lcobucci\JWT\Signer\Keychain;
$parser = new Lcobucci\JWT\Parser;

try {
$token = $parser->parse($token_string);
} catch( Exception $e ) {
echo "decode failed\n";
exit;
}

// check key field
foreach (array( 'iat', 'exp', 'aud', 'iss', 'user_id' ) as $field) {
if (!$token->hasClaim($field)) {
echo "no $field\n";
exit;
}
}

if ($token->isExpired()) {
echo "exp expired\n";
exit;
}

if (!$token->hasHeader('kid')) {
echo "no kid\n";
exit;

}
$kid = $token->getHeader('kid');

$keys = json_decode(file_get_contents('https://www.googleapis.com/robot/v1/metadata/x509/securetoken@system.gserviceaccount.com'), true);

if (!isset($keys[$kid])) {
echo "kid not found\n";
exit;
}


try {
if( $token->verify($signer, $keychain->getPublicKey($keys[$kid])) )
echo "PASS\n";
} catch (Exception $e) {
echo "Failed";
}

$user_id = $token->getClaim('user_id');


連續動作(PHP Codeigniter Usage):

$ cat Jwt_library.php
<?php
require_once 'jwt-3.2.2/vendor/autoload.php';
class Jwt_library {
public function __construct() {
$this->ci = &get_instance();
$this->parser = new Lcobucci\JWT\Parser;
$this->keychain = new Lcobucci\JWT\Signer\Keychain;
$this->signer = new Lcobucci\JWT\Signer\Rsa\Sha256;
}

public function verify_firebase_token(&$error, $user_token, $project_id, $service_public_keys = array()) {
$user_id = NULL;
$error = NULL;
$token = false;
try {
$token = $this->parser->parse($user_token);
} catch (Exception $e) {
$error= 'decode failed';
return NULL;
}

// check filed name
foreach (array( 'iat', 'exp', 'aud', 'iss', 'user_id' ) as $field) {
if (!$token->hasClaim($field)) {
$error = "no $field";
return NULL;
}
}

if ($token->isExpired()) {
$error = 'exp expired';
return NULL;
}
//if ($token->getClaim('iat') > time() )
// return 'token has been issued in the future';

if ($token->getClaim('aud') != $project_id ) {
$error = 'aud error';
return NULL;
}

$user_id = $token->getClaim('user_id');

$kid = false;
try{
$kid = $token->getHeader('kid');
} catch (Exception $e) {
$error = 'no kid';
return NULL;
}

if (!isset($service_public_keys[$kid])) {
$error = 'kid not found: '.$kid;
return NULL;
}

try {
if ($token->verify($this->signer, $this->keychain->getPublicKey($service_public_keys[$kid])))
return $user_id;
} catch (Exception $e) {
$error = 'verify failed';
}

return NULL;
}
}


$ cat php_ci_controller.php
<?php
$output = array( 'status' => false );

$authorization_info = $this->input->get_request_header('Authorization', True);
if (empty($authorization_info) || strstr($authorization_info, 'Bearer ') == false) {
        $output['error'] = -1;
        $output['message'] = 'no Authorization';
        $this->_json_output($output);
        return;
}

$firebase_user_token = trim(substr($authorization_info, strlen('Bearer ')));
$this->load->library('jwt_library');
$keys = @json_decode(@file_get_contents('https://www.googleapis.com/robot/v1/metadata/x509/securetoken@system.gserviceaccount.com'), true);
$firebase_user_id = $this->jwt_library->verify_firebase_token($verify_error, $firebase_user_token, 'YourFirebaseProjectId', $keys);
if (empty($firebase_user_id)) {
$output['error'] = 1;
$output['message'] = 'verify: '.$verify_error;
$this->_json_output($output);
return;
}

2015年1月21日 星期三

[C++] JSON Library - jsoncpp @ Ubuntu 14.04, Mac OS X 10.10.1

JSON Format 現今已經是一個非常常見的溝通管道,最近常在 Ubuntu server 上練習 C++,偶爾沒網路時也會想用 Mac OS X 進行,因此,著重在如何輕鬆管理 C++ JSON Library 的用法,找了一下,大概就是 jsoncpp 啦

在 Ubuntu 14.04:

$ sudo apt-get install libjsoncpp-dev
$ g++ -I/usr/include/jsoncpp/ main.cpp -ljsoncpp


在 Mac OS X 10.10.1 搭配 MacPorts 管理:

$ sudo port install jsoncpp
$ g++ -std=c++11 -I/opt/local/include/ -L/opt/local/lib main.cpp -ljsoncpp


由於都可以透過系統常見的管理工具安裝,即可省去下載 source code 編譯等管理成本。簡易範例:

$ vim example.cpp
#include <iostream>       // std::cout
#include <string>         // std::string
#include <json/json.h>

int main() {
        std::string raw = "{\"key\":\"value\",\"我\":\"是誰\",\"array\":[\"a\",\"b\",123]}";
        Json::Reader reader;
        Json::Value value;
        std::cout << "Input: " << raw << std::endl;
        if (reader.parse(raw, value)) {
                std::cout << "parsing: " << value ;//<< std::endl;
                std::cout << "get: " << value["我"] ;//<< std::endl;
                std::string data = value["key"].asString();//toStyledString();
                std::cout << "string: [" << data << "]" << std::endl;

                // with -std=c++11
                std::cout << "---" << std::endl;
                for (auto it : value) {
                        std::cout << "elm: " << it ;//<< std::endl;
                        if (it.isArray()) {
                                for (auto it2 : it)
                                        std::cout << "array data: " << it2 ;//<< std::endl;
                        }
                }        
        }
        return 0;
}
$ g++ -I/opt/local/include/ -L/opt/local/lib main.cpp -ljsoncpp
$ ./a.out
Input: {"key":"value","我":"是誰","array":["a","b",123]}
parsing:
{
"array" : [ "a", "b", 123 ],
"key" : "value",
"我" : "是誰"
}
get: "是誰"
string: [value]
---
elm: [ "a", "b", 123 ]
array data: "a"
array data: "b"
array data: 123
elm: "value"
elm: "是誰"

2014年11月25日 星期二

[PHP] CodeIgniter 與 Facebook PHP SDK v4 整合筆記 @ Ubuntu 14.04

整個流程並主要是把 Facebook PHP sdk v4 source code 下載到 ci_proj/application/libraries 中,接著撰寫一隻 ci library: facebook.php 來橋接一下,就差不多可以收工了。在此謹驗證收到的 facebook token 是否有效,其他部分並不實作:

$ cd /path/ci_proj/application/libraries
$ git clone https://github.com/facebook/facebook-php-sdk-v4.git
$ ln -s facebook-php-sdk-v4 facebook


建立 Facebook 相關 config:

$ vim /path/ci_proj/application/config/facebook.php
<?php defined('BASEPATH') OR exit('No direct script access allowed');
$config['facebook']['api_id'] = 'FACEBOOK APP ID';
$config['facebook']['app_secret'] = 'FACEBOOK APP SECRET KEY';


編輯橋接的 library 用法:

$ vim /path/ci_proj/application/libraries/facebook.php

<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
require_once APPPATH . 'libraries/facebook/autoload.php';

use Facebook\FacebookRedirectLoginHelper;
use Facebook\FacebookSession;
use Facebook\FacebookRequest;
use Facebook\GraphUser;
use Facebook\FacebookRequestException;

class Facebook {
var $ci;
var $helper;
var $session;
var $permissions;

public function __construct() {
$this->ci =& get_instance();
$this->ci->load->config('facebook');
$this->permissions = $this->ci->config->item('permissions', 'facebook');
FacebookSession::setDefaultApplication( $this->ci->config->item('api_id', 'facebook'), $this->ci->config->item('app_secret', 'facebook') );
        }
public function token_validation($token) {
try {
$this->session = new FacebookSession( $token );
if ( $this->session->validate() )
return true;
} catch ( Exception $e ) {
}
$this->session = null;
return false;
}
public function get_user($token = NULL) {
if ( $this->session || (!empty($token) && $this->token_validation($token)) ) {
$request = ( new FacebookRequest( $this->session, 'GET', '/me' ) )->execute();
$user = $request->getGraphObject()->asArray();
return $user;
}
return false;
}
}


使用方式:

<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
class Test extends CI_Controller {
public function index()
{
$this->load->config('facebook');
$this->load->library('facebook');
$output = array(
'reqeusts' => $_REQUEST,
'app_id' => $this->config->item('api_id', 'facebook'),
'user_id' => $this->facebook->get_user($_REQUEST['token'])
);
$this->output->set_content_type('application/json')->set_output(json_encode($output));
        }
}

2014年7月15日 星期二

iOS 開發筆記 - 使用 CocoaPods 管理第三方函式庫

記得前幾年都用 git 跟 git submodule 管理,一切都是手動處理,包含 Xcode 添加 include path 等,現在則是想要把一些把玩的東西 open 出來,就想到用 CocoaPods 來管理,畢竟不是每個人都那麼勤勞的 XD

在此以 CocoaAsyncSocket 和 facebook-ios-sdk 為例。

首先,先安裝 CocoaPods:

$ sudo gem install cocoapods
$ pod update


接著搜尋想要的套件:

$ pod search CocoaAsyncSocket

-> CocoaAsyncSocket (7.3.5)
   Asynchronous socket networking library for Mac and iOS.
   pod 'CocoaAsyncSocket', '~> 7.3.5'
   - Homepage: https://github.com/robbiehanson/CocoaAsyncSocket
   - Source:   https://github.com/robbiehanson/CocoaAsyncSocket.git
   - Versions: 7.3.5, 7.3.4, 7.3.3, 7.3.2, 7.3.1, 7.2.2, 7.0.3, 0.0.1 [master repo]

$ pod search facebook-ios-sdk

-> Facebook-iOS-SDK (3.15.1)
   The iOS SDK provides Facebook Platform support for iOS apps.
   pod 'Facebook-iOS-SDK', '~> 3.15.1'
   - Homepage: https://developers.facebook.com/docs/ios/
   - Source:   https://github.com/facebook/facebook-ios-sdk.git
   - Versions: 3.15.1, 3.15.0, 3.14.1, 3.14.0, 3.13.1, 3.13.0, 3.12.0, 3.11.1, 3.11.0, 3.10.0, 3.9.0, 3.8.0, 3.7.1, 3.7.0, 3.6.0, 3.5.3, 3.5.2, 3.5.1,
   3.5.0, 3.2.1, 3.2.0, 3.1.1, 3.1.0, 3.0.8, 3.0.7, 3.0.6.b, 3.0.5.b, 1.2, 1.last, 0.0.1 [master repo]




接著,開始透過 Xcode 新增一個 Project (HelloPods) 後,接著改用 Terminal 在 Project 目錄下新增 Podfile

$ cd ~/path/ios-project
$ vim Podfile
pod 'CocoaAsyncSocket'
pod 'Facebook-iOS-SDK'
$ pod install
Analyzing dependencies
Downloading dependencies
Installing Bolts (1.1.0)
Installing CocoaAsyncSocket (7.3.5)
Installing Facebook-iOS-SDK (3.15.1)
Generating Pods project
Integrating client project

[!] From now on use `HelloPods.xcworkspace`.


接著,就改用 HelloPods.xcworkspace 吧!

$ open HelloPods.xcworkspace

現況雖然可以輕鬆添加新增的函式庫 header files 了,但在 import 時沒有 autocomplete 的功能,若很在意的話,可在 Project (HelloPods) -> Target (HelloPods) -> Build Settings -> User Header Search Paths -> 增加 ${SRCROOT} 以及 recursive 屬性。(添加完出錯時,在把它刪掉吧)

如此一來,工作應該就跟平常沒什麼兩樣啦。未來,可以一樣可以用 pod update / pod outdated 更新套件最新資訊。

另外,目前 Project (HelloPods) 目錄結構:

$ ls ~/path/ios-project
HelloPods HelloPods.xcworkspace Podfile Pods
HelloPods.xcodeproj HelloPodsTests Podfile.lock


對於哪些目錄需要用 git 管理,可以參考一下官網介紹:Should I ignore the Pods directory in source control?

以上則是利用 CocoaPods 及其管理的第三方函式庫的用法,至於不再 CocoaPods 管理的套件呢?除了在 Podfile 中描述來源外,其套件也要撰寫 *.podspec 描述,請參考 CocoaAsyncSocket / CocoaAsyncSocket.podspec;對於 Podfile 的部分,則是直接指定 git 位置即可:

$ vim Podfile
pod 'AFNetworking', :git => 'https://github.com/gowalla/AFNetworking.git'