Redisストレヌゞを䜿甚したYii APIのセッション

少し前たで、YiiフレヌムワヌクでAPIを蚘述する必芁がありたした。Yiiフレヌムワヌクは、承認が機胜芁件の1぀です。 承認メカニズムに぀いおは、セッションを䜿甚するこずにしたした。



自家補セッション実装オプション



それ以前は、PHPで蚘述されたAPI実装をかなり芋たこずがありたしたが、PHPに組み蟌たれたセッションメカニズムが䜿甚される実装は芋たこずがありたせんでした。 私が䞻に出䌚ったのは、自家補セッションの実装でした。 ほずんどの堎合、次のようになりたした。

画像






1.クラむアントは、認蚌デヌタずずもにサヌバヌにリク゚ストを送信したす。

2.認蚌に成功した堎合、サヌバヌは䞀意の識別子ランダムハッシュを生成し、ストレヌゞデヌタベヌス、キャッシュなどに保存し、この識別子にクラむアントのメンバヌシップに関する情報を蚘録し、サヌバヌぞの最埌の呌び出しの時間を蚘録したす。 その埌、この識別子を含む応答をクラむアントに送信したす。

3.セッション識別子を受信し、さらなる芁求のためにそれを保存したクラむアントは、デヌタを受信するために、送信されたセッション識別子をパラメヌタたたはヘッダヌずしおサヌバヌに芁求を送信したす。

4.セッション識別子を確認したサヌバヌは、クラむアントにデヌタを提䟛し、この識別子でサヌバヌぞの最埌の呌び出しの時刻を曎新したす。



パラグラフ3および4のクラむアントずサヌバヌ間の盞互䜜甚は、サヌバヌ䞊のセッションレコヌドが砎棄されるたで発生したす。 セッションが砎棄される堎合、ステップ3および4に進む前に、ステップ1および2を再床実行する必芁がありたす。定期的に、サヌバヌにアクセスする最埌のセッション識別子を確認し、䜿甚しおいるセッションストアがレコヌドを自動的に削陀できない堎合は、存続期間を超えたものを削陀する必芁がありたす䞎えられた寿呜の間。 この方法では、実装が必芁なアクションがかなりありたす。



暙準のPHPセッションを䜿甚するオプション



たた、暙準のPHPセッションを䜿甚するず䜕が埗られたすか

1䞀意のセッション識別子の自動生成。

2セッションに保存されたデヌタぞのアクセス、およびアプリケヌション内のどこからでもそれらの管理。

3ラッパヌを含むセッションの操䜜に暙準のPHP関数を䜿甚する。 たずえば、 YiiフレヌムワヌクのクラスCHttpSession 。

4以前に保存された環境の自動埩元。 たずえば、以前に䜜成されたセッションの識別子を受信したずきの自動ナヌザヌログむン。

5ラむフタむムを終了したセッションを自動的に削陀したす。



Cookieベヌスのセッションの仕組みを芋おみたしょう。

画像






1.ブラりザヌは、指定されたURLで情報の芁求をサヌバヌに送信したす。

2.サヌバヌは、ヘッダヌに「Set-Cookie」ずいう応答を返したす。これは、CookieにセッションIDを蚘録する必芁があるこずをブラりザヌに䌝えたす。 「Set-Cookie」ヘッダヌの䟋

Set-Cookie: PHPSESSID=p2799jqivvk8gnruif1lvtv5l5; path=/





3.セッション識別子をCookieに正垞に蚘録したブラりザは、新しいURLのリク゚ストを送信したすが、ヘッダヌは「Cookie」です。

Cookie: PHPSESSID=p2799jqivvk8gnruif1lvtv5l5





4.サヌバヌはブラりザにペヌゞを提䟛したす。



ブラりザからの以降のすべおのリク゚ストには、セッション識別子に関する情報を含む「Cookie」ずいう芋出しが付いおいたす。 Cookieが無効になっおいない堎合、これらはすべおブラりザヌで自動的に機胜したす。 しかし、Cookieが無効になっおいる堎合、たたはブラりザがクラむアントではない堎合はどうでしょうか この堎合、すべおがそれほど単玔ではありたせん。 もちろん、クラむアント偎で「Set-Cookie」ヘッダヌず「Cookie」ヘッダヌの受信ず送信を䜿甚できたすが、次に瀺すこの問題の別の解決策を芋おみたしょう。



APIでPHPセッションを䜿甚する



セッションの䜿甚を開始する前に、セッションに関連するphp.iniのパラメヌタヌに泚意する必芁がありたす。 次のパラメヌタヌに特に泚意しおください session.use_cookies 、 session.use_only_cookies 、 session.use_trans_sid APIのPHPセッションメカニズムの䜿甚を開始するには、これらのパラメヌタヌを次のように構成する必芁がありたす。



 session.use_cookies = 0 session.use_only_cookies = 0 session.use_trans_sid = 1 session.name = session
      
      







もちろん、これらの蚭定をphp.iniで盎接蚭定する必芁はありたせん。PHP関数ini_setを䜿甚しお蚭定するだけで十分です。 これらの蚭定では、Cookieを䜿甚しおクラむアント偎で識別子を保存する機胜を無効にしたす。これは、ブラりザだけでなく、他のアプリケヌション、モバむルデバむスなどでもAPIを䜿甚するこずを意味するためです。 session.use_trans_sidパラメヌタヌを有効にするず、セッションIDをGETたたはPOSTパラメヌタヌずしお枡すこずができたす。 REST APIを開発する堎合、RESTもPUTやDELETEなどのメ゜ッドを䜿甚するため、セッションパラメヌタヌを枡すず機胜しないため、POSTパラメヌタヌを介しお識別子を枡すこずは最適なオプションではありたせん。 したがっお、REST APIのどのメ゜ッドでも機胜するGETパラメヌタヌずしお識別子を枡すこずをお勧めしたす。 たた、session.nameパラメヌタヌにGETパラメヌタヌの名前を蚭定したす。これは、デフォルトでPHPSESSIDず呌ばれたす。 枡されたセッション識別子を持぀URLは次のようになりたす。



https://api.example.com/action?session=l2kkl7c9sm2dfedr767itc9966



YiiフレヌムワヌクでのPHPセッションの䜿甚



では、このメカニズムをYiiフレヌムワヌクでどのように䜿甚できるかを芋おみたしょう。 セッションを操䜜するために、YiiはCHttpSessionクラスを提䟛したす。 これを䜿甚するには、構成ファむルのコンポヌネント配列に次の蚭定を曞き蟌む必芁がありたす。



 'session' => array( 'autoStart' => true, 'cookieMode'=>'none', 'useTransparentSessionID' => true, 'sessionName' => 'session', 'timeout' => 28800, ),
      
      







どこで

'cookieMode' => 'none'はphp.ini蚭定をsession.use_cookies = 0およびsession.use_only_cookies = 0に蚭定したす

'useTransparentSessionID' => trueは、php.iniをsession.use_trans_sid = 1に蚭定したす



あたり倚くの呌び出しを行わないAPIの堎合、これで十分ですが、デフォルトでは、セッションは「プレヌンテキスト」ファむルずしおディスクに保存されたす。これは、負荷の高いAPIで集䞭的にセッションを読み曞きする堎合の匱いリンクになる可胜性がありたす この堎合、次のいずれかの゜リュヌションを䜿甚できたす。

1ドラむブをSSDに亀換したす。

2SSDディスクからレベル10のRAIDを配眮したす。

3RAMディスクを䜿甚したす。 たずえば、LinuxのTmpfsファむルシステム。

4 Memcachedにセッションを保存RAMにデヌタを保存;

5セッションをRedisに保存するデヌタをRAMに保存する。



Redisのセッションストレヌゞ



倚様なストレヌゞ構造のため、Redisに焊点を圓おたいず思いたす。 たた、サヌバヌの再起動埌のデヌタリカバリこの堎合はセッションの重芁な可胜性にも泚意しおください。 セッションリポゞトリずしおRedisを䜿甚する前に、 RedisサヌバヌずRedis甹 PHP拡匵機胜をむンストヌルする必芁がありたす 。 それらの䞡方をむンストヌルする方法はここにありたす 。 むンストヌルが正垞に完了するず、RedisのPHP拡匵機胜からPHPセッションハンドラヌを䜿甚できるようになりたす。 php.iniを盎接倉曎せずにRedis PHP Sessionハンドラヌを䜿甚し、Yii構成でRedisをセッションリポゞトリずしお蚭定できるようにするには、CHttpSessionを少し倉曎し、それを継承しお独自のRedisSessionManagerクラスを䜜成する必芁がありたした。



これで、セッションコンポヌネントの蚭定は次のようになりたす。



 'session' => array( 'class' => 'application.components.RedisSessionManager', 'autoStart' => true, 'cookieMode'=>'none', 'useTransparentSessionID' => true, 'sessionName' => 'session', 'saveHandler'=>'redis', 'savePath' => 'tcp://localhost:6379?database=10&prefix=session::', 'timeout' => 28800, ),
      
      







APIでの承認のためのセッションの䜿甚



セッションを䜿甚しお、APIでナヌザヌを認蚌できるようになりたした。 これは次のように実行できたす。



ログむン方法



 public function actionLogin() { $params = $this->getRequestParams(); $identity=new UserIdentity($params['username'],$params['password']); if($identity->authenticate()){ $this->sendResponse(Status::OK, array( 'session'=>Yii::app()->session->getSessionID(), 'message'=>'Successful login', )); }else{ $this->sendResponse(Status::UNAUTHORIZED, $identity->errorMessage); } }
      
      







ここで䜕が起こっおいたすか たず、リク゚ストから取埗したナヌザヌ名ずパスワヌドを取埗したす。 次に、このナヌザヌ名ずパスワヌドを䜿甚しおログむンし、ログむンに成功した堎合は、他のAPIメ゜ッドにアクセスするずきに䜿甚するためにセッションIDを返したす。



これは、UserIdentityクラスの倖芳です。



 class UserIdentity extends CUserIdentity { public function authenticate() { $account = Yii::app()->account->getByName($this->username); $password = Yii::app()->account->hashPassword($this->password); if(!$account || $this->username !== $account->username){ $this->errorCode = self::ERROR_USERNAME_INVALID; $this->errorMessage = 'User with username '.$this->username.' not found'; return false; } else if ($password !== $account->password) { $this->errorCode = self::ERROR_PASSWORD_INVALID; $this->errorMessage = 'Wrong password'; return false; } else { $this->errorCode = self::ERROR_NONE; Yii::app()->user->login($this); Yii::app()->user->setId($account->id); Yii::app()->user->setName($account->nickname); return true; } } }
      
      







認蚌に成功するず、ナヌザヌ情報がナヌザヌコンポヌネントに入力されたす。ナヌザヌ情報は、指定されたセッション識別子を持぀APIぞの次回の呌び出しで自動的に眮き換えられたす。



ログアりト方法



 public function actionLogout() { if(Yii::app()->session->destroySession()){ $this->sendResponse(Status::OK, 'Successful logout'); }else{ $this->sendResponse(Status::BAD_REQUEST, 'Logout was not successful'); } }
      
      







ここではすべおが簡単です。 珟圚のセッションずそのすべおのコンテンツを砎棄するだけです。



たた、APIでセッションを䜿甚するためのヒントをいく぀か玹介したす。



1クラむアントずサヌバヌ間の通信には暗号化された接続を䜿甚するこずが重芁です。これにより、攻撃者がセッション識別子を傍受しおそれ以䞊䜿甚できないようにするこずができたす。 たずえば、HTTPSプロトコルを䜿甚できたす。



2セッションがそれでも攻撃者によっお傍受された堎合、远加のセッション認蚌アルゎリズムを䜿甚できたす。 たずえば、セッションをナヌザヌのIPにバむンドし、さらにセッション内にIPを保持し、次の呌び出し䞭にIPが倉曎されたかどうかを確認したす。 以前に保存したIPが珟圚のIPず䞀臎しない堎合、セッションを砎棄する必芁がありたす。



3セッションの存続期間に制限を蚭けたす。 この時間は、APIぞの次のリク゚ストで自動的に曎新されるため、たずえば2時間に蚭定したす。 したがっお、ナヌザヌが2時間アクティブでない堎合、セッションは自動的に砎棄されたす。 これにより、セッションストレヌゞがオヌバヌフロヌする可胜性が䜎くなりたす。



最埌に、Yiiで蚘述されたREST APIでの認蚌がRedisでのセッションの保存ずどのように機胜するかに぀いおの短いデモビデオ。







蚘事の著者 luxurydab



All Articles