達成するためのセキュリティPHPインターフェース?

https://www.cnblogs.com/afsj/p/7424320.html
PHP APPインタフェースを行う場合、どのようにセキュリティインターフェイスを確保するには?

ユーザがAPPをログに記録した場合に1が、関連するインターフェイスをコールバックするために、HTTPSプロトコルを使用して、サーバは、セッションに格納されたユーザ名とパスワードとACCESS_KEYに従ってACCESS_KEYを生成し、APPの端にACCESS_KEY SESSION_ID復帰を結果として生じます。

2、APPのACCESS_KEY端部は、SESSION_IDを受信して​​保存します

図3は、インタフェースのデータ転送は、APP端末を呼び出すとき、送信されたデータと署名ACCESS_KEY署名は、暗号化アルゴリズム、及び署名SESSION_IDを使用して生成され、サーバに一緒に送信されます。

サーバが生成された署名と受信された署名が同じであれば、対応する署名を生成するために、同じ暗号化アルゴリズムを使用してACCESS_KEY、ACCESS_KEYにSESSION_IDと、受信したデータを使用して、セッションから得るために対応するデータを受信した場合4は、そのデータが有効であることを示し

https://www.cnblogs.com/zouke1220/p/9394356.html
セキュリティのPHPインターフェイスデザイン
トークン認証メカニズムの
タイムスタンプタイムアウトメカニズム:
署名メカニズム:
拒否された繰り返しの呼び出し:クライアントの最初の訪問、署名する署名ストアキャッシュサーバに、タイムアウトがタイムアウトタイムスタンプと一致するように設定される、一度だけアクセスすることができ、タイムスタンプのURL内または外部の制限時間の両面で同じ時間を保証することができます。
不正なIPアクセス制限は、ここでの制限は、一般的にホワイトリストこの制限を行うには、サーバーの呼び出しの間のインターフェイスで使用されている
HTTPSアクセス

メインインターフェイストークンの周りのセキュリティは、タイムスタンプとサインを改ざんし、ビューの次の特定のポイント、繰り返し呼び出されることはありませんデータインタフェースを確保するために設計された3つのメカニズムを開始しました:

(1)トークン認証機構:(トークンは、クライアントアクセスサーバーの資格情報です) - クライアントへのサーバーのログを記録するために、ユーザーのユーザー名・パスワードトークン(通常はUUID)を返し、キーと値のペアのトークン・ユーザーIDの形式キャッシュサーバに保存されています。トークン検証サービスは、要求が無効であったことを示し、何のトークンが存在しない場合は、要求の受信後に終了しました。

時間差が所定時間よりも大きい場合(2)データが改ざんされていないことを確認する:(タイムアウト機構スタンプ署名機構)サーバ、続いてユーザの要求が現在の時刻のタイムスタンプのタイムスタンプに置かれるたびに、比較のために現在の時刻のタイムスタンプを受信します(例えば5分など)、要求は無効であると考えられます。タイムスタンプのタイムアウトメカニズムは、防衛DOS攻撃の有効な手段です。

(3)署名メカニズム:トークン要求パラメータ及びタイムスタンプに加えて他の次にMD5またはSHA-1アルゴリズム(塩、状況に応じて添加することができる)、暗号化、データが署名は、この要求に署名暗号化され、サービスは、要求を受信します同じアルゴリズムの署名後、パラメータは、エラーが識別直接返される変更されたことを示す場合、同じではない、現在の署名と比較します。
コードをコピー

/ **

  • @descパラメータ処理受け入れ
    * /
    プライベートdealParam関数(){
    //パラメータヘッダが受け入れるを-システムパラメータ
    $ systemParam getAllHeadersParam =();
    身体受信//データ-サービスパラメータ(JSON形式)
    $ DATA =のfile_get_contents(「PHP: //入力「);

    //設定ファイル読み込むための秘密鍵の情報
    $ api_apiKey = C( 'api_apiKeyを');
    $ $ api_apiKeyのPrivateKey = [$ systemParam [ 'トークン']];

    $ ARR [ 'トークン'] = $ systemParam [ 'トークン']; // サーバに割り当てられた識別子(異なるクライアントは異なるIDを使用する必要がある)
    $ ARR [ 'タイムスタンプ'] = $ systemParam [ 'タイムスタンプ']; / /タイムスタンプ、GMT東にUTCタイムゾーン(8)8が勝つ
    $ ARRを[ 'バージョン'] = $ systemParam [ 'バージョン']; // バージョン番号
    の$ ARR [ '記号'] = $ systemParam [ '記号']; //署名
    $のARR [ 'ソース'] = $ systemParam [ 'ソース']; // 原点(0〜アンドリュース/ 1-IOS / 2-H5 / 3-PC / 4-PHP / 5- Javaの)
    $ ARR [ 'データ'] json_decodeの= trueに($データ); //サービスパラメータJSON形式
    の$ ARR [ '方法'] = $データ[ 'メソッドは']; // アクセスインターフェイス、形式:モデル名。メソッド名

    $ ARRを返します。
    }

コードをコピー

コードをコピー

/ *

  • HTTPヘッダー内のすべてのヘッダパラメータを取得@desc
  • @returnアレイ
    * /
    プライベート関数getAllHeadersParam(){
    $ヘッダー=配列();
    foreachの($ {$キー=> $値としてSERVER)
    IF(SUBSTR($キー、0、5)=== 'HTTP
    '){
    $キー= SUBSTR($キー、5)。
    $キー= str_replace( '_'、 ''、$キー)。
    $キー= str_replace(」」、 ' - '、$キー)。
    $キー= strtolower($キー)。
    $ヘッダー[$キー] = $値。
    }
    }
    $ヘッダを返します。
    }

コードをコピー

コードをコピー

/ *

  • @desc署名検証
  • (異なるクライアントが異なるIDを使用する必要があります)に割り当てられた$トークンサーバ識別文字列を@param
  • @param $タイムスタンプ北京東地区8(8)内の文字列のタイムスタンプ、UTC時間は、勝ちます
  • $バージョン文字列のバージョン番号を@param
  • @paramの$記号列署名
  • ソース(0-アンドリュース/ 1-IOS / 2-H5 / 3-PC / 4-PHP / 5-javaの)int型@paramの$ソース
  • $ PrivateKeyの文字列のプライベートを@param
  • JSON形式のパラメータ@paramの$データサービス
  • BOOLの@return
    * /
    プライベート機能checkAuth(トークン$、$タイムスタンプ、バージョン$、$サインオン、ソース$、$のPrivateKey、$データ){
    //パラメータの決意
    ()($トークンを空にする)IF {
    E(「トークン缶ではありません空');!
    }
    (($タイムスタンプを空にする)IF){
    E('タイムスタンプは空にすることはできません! ');
    }
    (($バージョンを空にするIF)){
    E('バージョン番号は「空にすることはできません);!
    }
    IF(空($データ)){
    E( 'サービスパラメータを空にすることはできません!');
    }
    IF(空($ソース)&& $ソース<> '0'){
    E( 'ソースは空にすることはできません!');
    }
    IF(($)サインを空にする){
    E( '署名が空にすることはできません!');
    }
    IF(($のPrivateKey)を空にする){
    E( '秘密鍵を空にすることはできません!');
    }
    //チェック時間
    $ expire_second = C( 'expire_second'、 NULL、10)。
    $ timestamp_t = $タイムスタンプ+ $ expire_second。
    IF($ timestamp_t <時間()){
    Eは( '要求の期限が切れた!');
    }
    $公共= D( '公共');
    $ DATAS =の$ this - >オリジナル;
    //システムパラメータ
    $ paramArr =配列(
    "トークン'=> $トークン、
    'タイムスタンプ'=> $タイムスタンプ、
    'バージョン'=>バージョン$、
    'ソース'=>ソース$、
    'データ「=>データ$、
    );

     //按规则拼接为字符串
     $str = $this->createSign($paramArr,$this->privatekey);
    
     if($str != $this->sign){
         E('验签错误!');
     }
     return true;

    }

コードをコピー

生成規則とのステップに署名:

①最初のステップ:ASCIIでのパラメータ名に基づいて昇順に(ログイン除き、空のパラメータ値、ファイルのバイトストリーム)サーバにリクエストパラメータを送信するために、すべての必要性(辞書式)

注意:

  l 参数名ASCII码从小到大排序(字典序);

  l 如果参数的值为空不参与签名;

  l 文件、字节流不参与签名;

  l sign不参与签名;

  l 参数名、参数值区分大小写;

②第二段階:ソート済みキーURLに応じたパラメータのフォーマットは、(すなわち、KEY1 =値1&KEY2 =値2 ...)列STRAに組み立てます。

③第三の工程:STRA APIKEY striSignTemp列を与えるために、スプライシング後、MD5計算は、着信サービスMD5計算の終わりの印としてstrSignTemp列小文字の文字列の得られた値の後に行われます。

例(すべてのパラメータは、パラメータ値は一例であり、開発者は、フォーマットを参照することができます)。

トークン:cd171009328172Ad3sc

APIKEY:cd13H2ddd22212ds1da

①最初のステップ(パラメータ名でリクエストパラメータを取得し、大量注文にASCIIコードを育ったため):

トークン= cd173309328172Ad322

データ= { "userNameに": "18817201899"、商品:[ "addrId":323、{ "skuNo": "p12232-023" は、 "カウント":3}、{ "skuNo": "p12232-013"、」 「カウント:1}]}

タイムスタンプ= 1507537036

バージョン= v3.6.0

(ストリングSTRAステッチ規則に従って)②第二段階:

トークン= cd171009328172Ad3sc&データ= { "userNameに": "18817201899" は、商品:[ "addrId":323、{ "skuNo": "p12232-023"、 "カウント":3}、{ "skuNo": "p12232-013" "カウント":1}]}タイムスタンプ= 1507537036&バージョン= v3.6.0

③第三のステップ(世代記号):

1)文字列strSignTemp署名します。

トークン= cd171009328172Ad3sc&データ= { "userNameに": "18817201899" は、商品:[ "addrId":323、{ "skuNo": "p12232-023"、 "カウント":3}、{ "skuNo": "p12232-013" "カウント":1}]}タイムスタンプ= 1507537036&バージョン= v3.6.0cd13H2ddd22212ds1da

2)文字列を低下させます

strtolower()

暗号化された3)MD5暗号文

6D556D52822658FD47F7FE362544CEE1は、
コードをコピー

/ *

  • @desc署名機能
  • @param $ paramArrシステムパラメータ
  • @param $ APIKEYプライベート
  • @return文字列戻り署名
    * /
    プライベート機能createSign($ paramArr、APIKEY $){
    ksort($ paramArr);
    $ログイン= '';

    foreachの($ paramArr $キーなど=> $ valの){
    場合($キー= '' && $ valを=! ''!){
    $記号= $キー"=" $ valの"&"。。。。。
    }
    }
    $記号= RTRIM($記号"&")。
    $記号= $ APIKEY。
    $記号= strtolower($記号)。
    $記号= MD5($記号)。
    $記号を返します。
    }

コードをコピー

キャッシュサーバに格納された署名を署名する、タイムアウトがタイムアウトタイムスタンプと一致するように設定され、両方の時間的に限られた時間またはタイムスタンプの中に一貫性のあることを確認することができ、クライアントの最初の訪問:(4)はコールを繰り返すことを拒否しました外部URLは一度しかアクセスすることができます。誰かが同じURLに別の訪問を使用している場合は、キャッシュサーバを見つけた場合、すでにこの署名、サービス拒否のために存在します。誰かが同じURLを使用して再度アクセスし、故障のキャッシュ内の署名の場合場合は、タイムスタンプのタイムアウトメカニズムは、傍受されます。タイムスタンプ要求タイムアウトタイムアウトのタイムスタンプと一致し設定する理由です。URLは、他者によって傍受機構は(例えばデータ捕捉として)使用することができないことを確実にするために繰り返し呼び出しを拒否しました。
コードをコピー

/ **

  • 要求インタフェースの数を制限@desc
  • BOOL @return
    * /
    プライベートask_count関数(){
    $ CLIENT_IP =の$ this - > sys_get_client_ip();
    $ ask_url =の$ this - > sys_GetCurUrl();
    //の数制限
    $ limit_num = C( 'api_ask_limitを' 、NULL、5) ;
    //有効な時間、単位:秒
    $ limit_time C =( 'api_ask_time');
    $ now_time =時間();
    $ valid_time now_time = $ - $のlimit_time;
    $ ipwhere [ 'creatime'] =配列( 'EGT'、 DATE( 'はYmd H:I:S'、$ valid_time));
    $ ipwhere [ 'IP_NAME'] = $ CLIENT_IP;
    $ ipwhere [ 'ask_url'] = $ ask_url;
    $ check_result = M( 'log_ip_ask') - > ($ ipwhere) - > COUNT();
    IF {(!$ check_result == '0')
    IF($ check_result> = $ limit_num){
    E( '!倍の制限数を超えました');
    }
    }
    //挿入
    $はadd_data =配列(
    'IP_NAME' => $ CLIENT_IP、
    'ask_url' => $ ask_url、
    'creatime' =>日付( 'はYmd H:I:s'は、時間())
    );
    $結果= M( 'log_ip_ask') - >データ($はadd_data) - >()を追加。
    もし($結果===偽){
    E( '写入记录失败!');
    }
    trueを返します。
    }

コードをコピー

コードをコピー

/ **

  • クライアントのIPアドレスを取得
  • @param整数$タイプは、IPアドレス、IPv4アドレス番号タイプ0 1リターンリターンを返します。
  • @paramブール$ ADVアドバンスモードを取得するかどうか(そこに偽装することができます)
  • @return混合
    / *
    プライベート関数sys_get_client_ip($ = 0、$ ADV =偽を入力){
    $ = $タイプを入力しますか?1:0。
    静的IP $ = NULL;
    (!$ IP == NULL)場合は、$ IP [$タイプ]を返します。
    IF($ ADV){
    IF(ISSET($ _ SERVER [ 'HTTP_X_FORWARDED_FOR'])){
    $ ARR =爆発( ' ' $ _SERVER [' HTTP_X_FORWARDED_FOR'])。
    $ POS = array_search( '不明'、$ arrが);
    (偽== $ POS!)であれば解除($ ARR [$ POS]);
    $ IP =トリム($ ARRを[0]);
    } ELSEIF(ISSET($ _ SERVER [ 'HTTP_CLIENT_IP'])){
    $ IP = $ _SERVER [ 'HTTP_CLIENT_IP']。
    } ELSEIF(ISSET($ _ SERVER [ 'REMOTE_ADDR'])){
    $ IP = $ _SERVER [ 'REMOTE_ADDR']。
    }
    } elseifを(ISSET($ _、SERVER [ 'REMOTE_ADDR'
    ])){ $ IP = $ _SERVER [ 'REMOTE_ADDR']。
    }
    合法的な検証の// IPアドレス
    $ロング=はsprintf( "%U"、ip2long($ IP));
    $ IP = $ロング・アレイ($ IP、$ロング):配列( '0.0.0.0'、0);?
    戻りますIP $ [$タイプ];
    }

/ **

  • @desc現在のアクセスの完全なURLアドレスを取得するPHP
  • @return文字列
    * /
    プライベート関数sys_GetCurUrl(){
    $ URL = 'のhttp://';
    もし(ISSET($ _SERVER [ 'HTTPS'])&& $ _SERVER [ 'HTTPS'] == 'に'){
    $ URL = 'https://で';
    }
    もし($ _SERVER [ 'SERVER_PORT']!= '80'){
    $ URL。= $ _SERVER [ 'HTTP_HOST']。':'。$ _SERVER [ 'SERVER_PORT']。$ _SERVER [ 'REQUEST_URI'];
    }他{
    $ URL。= $ _SERVER [ 'HTTP_HOST']。$ _SERVER [ 'REQUEST_URI'];
    }
    $ URLを返します。
    }

コードをコピー

ホワイトリスト
違法なIPアクセス制限、ここでの制限は、一般的に、この制限を行うには、サーバーの呼び出しの間のインタフェースで使用されている
コードをコピー

// 允许访问的IP列表    
private $ip_allow = array(
    '111.11.111.111', // 局域网ip
    '111.11.111.112', // 任务服务器
    '111.11.111.113', // 代理IP
);

/ **
* @desc非法IP限制访问
* @paramアレイ$ CONFIG
* @return BOOL
* /
プライベート関数illegalip(){
(の$ this - > ip_limit!){場合は
trueを返します。
}
$ REMOTE_IP = GET_CLIENT_IP()。
(in_array($ REMOTE_IP、$ ip_allow)){場合は
trueを返します。
}
falseを返します。
}

コードをコピー

参考リンクします。https://www.jianshu.com/p/c6518a8f4040

設計と実装のアプリオープンインタフェースAPIセキュリティ-token署名符号
入門

ほとんどのインタフェースは、ユーザーの個人情報や機密性の高いデータに関連するため、これらのインタフェースは、アイデンティティを認証される必要があるので、アプリのオープンインタフェースAPIの設計では、避けるには、セキュリティ上の問題であることはできませんが、それはいくつかを提供するために、ユーザーが必要ですユーザーの数ができるだけ平文パスワードを暴露するように安全上の理由など、ユーザー名とパスワードなどの情報、しかし、我々は、ほとんどの場合、Webプロジェクトでは、一般的に保存されたセッションであり、そして維持するために、クッキーを維持するためにユーザの正当性に答えます。しかし、着陸後にユーザがログインを確認し、そのユーザーの有効性を維持するためにどのようにアプリが提供するオープンなインターフェース、バックエンドサーバーでは、以下の項目は、次のようなリファレンス・デザイン・ソリューション、原則とオープンインタフェースとして最もセキュアな認証、あります淘宝網オープンインタフェーストークン妥当性確認、検証トークンマイクロチャネルの開発プラットフォームは共感です。

署名のデザイン
に敏感なAPIインタフェースのため、あなたは、httpsプロトコルを使用する必要があります

HTTPSは、通信ネットワークが暗号化されている間にハイパーテキスト転送プロトコルHTTP SSL層に添加され、暗号化証明書が必要です。

HTTPSプロトコルは、一般的に支払いが必要、CA証明書が必要です。

シグネチャーデザイン

仕組み:ユーザーが(アカウントやパスワードなど)のユーザ認証情報、トークントークン後の復帰にクライアントに認証サーバ、ユーザは、再び情報を取得するときに、このトークンを取るを提供するために、サーバーにログオントークンZhengquを返す場合データ。トークン情報を得るために、アクセスユーザインタフェースは、次のパラメータを取るために、クライアントの要求URLの必要性:

タイムスタンプ:タイムスタンプ

Token令牌:token

その後、すべてのパラメータは、より多くのMD5暗号化(あなたには、いくつかの塩を追加することができます)、すべてのキャップは、URL署名アルゴリズムと呼ばれる記号署名を生成する、(タイムスタンプを含む、トークン)アルファベット順に、ユーザによって要求されました。次に、ユーザーのログイン情報の各呼び出しは、記号、タイムスタンプ、トークンのパラメータを取ります。

たとえば、次のように元の要求https://www.andy.cn/api/user/update/info.shtml?city=北京(ポストと同じ、ソート、すべての暗号化パラメータを取得します)

スタンプトークン

https://www.andy.cn/api/user/update/info.shtml?city=北京×タンプ= 12445323134&トークン= wefkfjdskfjewfjkjfdfnc
、より多くのURLパラメータ生成サイン

最後のリクエスト

12445323134&トークン= wefkfjdskfjewfjkjfdfnc&記号= FDK2434JKJFD334FDF2 https://www.andy.cn /api/user/update/info.shtml?city= 北京×タンプ=
最後の原則が露出平文の数を減らすことで、データのセキュリティアクセス。

特定には、以下を達成します。

  1. API要求クライアントは、サーバがユーザ認証情報(ユーザ名とパスワード)、利用者の情報が正しいことを確認し、要求を変更するには、サーバー側の要求を送信したいと考えています。

それが正しい場合:ユニークな非繰り返した文字列は、(一般的にUUID)を返し、その後、Redisの中のユーザ情報関係トークン---- UID(任意のキャッシュサーバ)を維持されるので、そのトークンのための他のAPIチェック。

エラーの場合:エラー・コードが返されます。

2.サーバーは、ルールをブロックしたURLリクエストを設計します

(1)が含まれていない場合、エラーコードを返し、タイムスタンプを含むか否かを判断するトークン、符号パラメータ。

盗まれた場合(2)決意サーバが要求を受信し、タイムスタンプパラメータは非常に長い時間(Customなどの時間の半分の時間、)によって異なり、それはURLが期限切れ超えていることを示し(URLは、彼が時間を変更しました)スタンプが、不平等なサイン署名につながることができます。

(3)トークンが有効であるかどうかを判断取得できない場合は、トークン、クエリのRedisキャッシュuidを超える要求に応じて、これはトークンの有効期限が切れていることを示しています。

(4)ユーザ要求のURLパラメータは、サーバが同じルールに従って署名符号を生成する、等価の署名の比較、同じリリースです。(ナチュラルURL署名は100%のセキュリティを保証することはできませんが、また、安全性を確保するので、唯一の署名の大部分、データおよびURLを暗号化することができますが、これは、公開鍵は、公開鍵AESによって失われていることを確認することができない場合)。

(5)だけで(例えば、ランディングURLなど)このURLインターセプト認証URLのリリースを取得するには、すべての残りの部分は、URL傍受の対象となります。

3.Tokenとの関係の維持のUid

関係のUIDを - あなたは、ユーザーがトークンを終了するときに削除する必要があり、UIDの関係 - 私たちは、トークンのユーザのログインを作成する必要があります。

署名アルゴリズム

すべてのリクエストパラメータを取得
重複したコードを

文字列記号= request.getParameter(「記号」)。
<?>列挙pNames = request.getParameterNames();
地図<文字列、オブジェクト>のparams =新しいHashMapの<文字列、オブジェクト>();
一方、(pNames.hasMoreElements()){
文字列はpName =(文字列)pNames.nextElement();
もし( "記号" .equals(pnameが))続けます。
オブジェクトp値= request.getParameter(はpName)。
params.put(はpName、p値)。
}

コードをコピー

署名を生成します

コードをコピー

公共の静的な文字列createSign(MAP <文字列、文字列> paramsは、ブールエンコードは)
にUnsupportedEncodingException {スロー
セット keysSet = params.keySet()。
オブジェクト[]キー= keysSet.toArray()。
(キー)は、Arrays.sort。
StringBufferのの一時=新しいStringBufferを();
ブール最初=はtrue。
{(キーオブジェクトキー)のための
(最初の){もし
最初= FALSE;
} {他
temp.append( "&")。
}
temp.append(キー).append( "=")。
オブジェクト値= params.get(キー)。
文字列で、valueString = "";
IF(!= NULL値){
ここで、valueString = String.valueOf(値)。
}
(エンコード){もし
temp.append(URLEncoder.encode(ここで、valueString、 "UTF-8"));
}他{
temp.append(ここで、valueString)。

    return MD5Utils.getMD5(temp.toString()).toUpperCase();
}

https://www.cnblogs.com/whcghost/p/5657594.html

おすすめ

転載: www.cnblogs.com/djwhome/p/12536305.html