CakePHP2系でSecurityコンポーネントを使いながらajax通信する方法

DSC08907

2014年01月20日(月)

最近、ちょっとテスト的な意味も込めて色々記事を投稿してきましたが、やっぱり技術系の記事もたまってきたのでこちらも更新していこうと思います。まぁ例の通りCakePHPネタばかりですが、まぁ誰かの参考になるでしょう。


通常、ajaxによる通信ではSecurityコンポーネントに引っかかってしまいうまくできないと思いますが、2通りのやり方で突破できたので忘れないように記述しておこうと思います。

 

jQueryでフォーム値を取得して一緒に渡す

こちらのやり方であればきちんとセキュリティを通っての通信となるのでなるべくこちらのやり方でやりましょう。

JSの自作関数を使用しているのは都度フォーム値を取得するためです。これで一応できました。

 

認証や登録の失敗時(バリデーションエラー等)にトークンをリフレッシュしなければ、すでに更新されているので、location.reload() でリフレッシュする処理を入れています。

これやっちゃうとajaxぽくないかなぁ。。。まぁやり方はあれかもしれませんがこれでなんとかできます。

 

サンプルは以下になります。

ビュー等、適所に入れてもらえば問題ないでしょう。

<script>
$(function() {
	// ログイン時
	$('#login_submit').on('click', function(){
		login_request( $('#UserUsername').val(), $('#UserPassword').val(), $('#UserLoginForm input:hidden[name="data[_Token][fields]"]').val(), $('#UserLoginForm input:hidden[name="data[_Token][key]"]').val(), $('#UserLoginForm input:hidden[name="data[_Token][unlocked]"]').val() );
		return false;
	});

	// アカウント登録時
	$('#signup_submit').on('click', function(){
		signup_request( $('#UserEmail').val(), $('#UserPassword').val(), $('#UserCheck').val(), $('#UserSignupForm input:hidden[name="data[_Token][fields]"]').val(), $('#UserSignupForm input:hidden[name="data[_Token][key]"]').val(), $('#UserSignupForm input:hidden[name="data[_Token][unlocked]"]').val() );
		return false;
	});

	function login_request( _username, _password, _fields, _key, _unlocked  ){
		var request_url = '<?php echo $this->Html->url( array('controller' => 'users', 'action' => 'api_login' ) ); ?>';
		var request_data = {
				'User' : { 'username' : _username, 'password' : _password },
				'_Token' : { 'fields' : _fields, 'key' : _key, 'unlocked' : _unlocked }
		};

		// ajax通信
		$.ajax({
			type: 'POST',
		    url: request_url,
		    data: request_data
		}).done(function(_return){
			if( _return.status === 'OK' ){
				// 成功
				alert( _return.message );
			}
			else {
				// 失敗
				alert( _return.message );
				location.reload();			// トークンリフレッシュ
			}
		}).fail(function(_return){
	    	// 通信失敗
			alert( '通信に失敗しました。リロードしてもう一度お試しください。' );
		});
	}

	function signup_request( _email, _password, _check, _fields, _key, _unlocked  ){
		var request_url = '<?php echo $this->Html->url( array('controller' => 'users', 'action' => 'api_signup' ) ); ?>';
		var request_data = {
				'User' : { 'email' : _email, 'password' : _password, 'check' : _check },
				'_Token' : { 'fields' : _fields, 'key' : _key, 'unlocked' : _unlocked }
		};

		// ajax通信
		$.ajax({
			type: 'POST',
		    url: request_url,
		    data: request_data
		}).done(function(_return){
			if( _return.status === 'OK' ){
				// 成功
				alert( _return.message );
			}
			else {
				// 失敗
				alert( _return.message );
				location.reload();			// トークンリフレッシュ
			}
		}).fail(function(_return){
	    	// 通信失敗
			alert( '通信に失敗しました。リロードしてもう一度お試しください。' );
		});
	}
});
</script>

どうなんでしょうか。

みなさんの意見もうかがいたいものです。。。

 

最後の手段。セキュリティ回避

こちらは最後の手段になります。

セキュリティをかけない方法になるのでなるべくこちらの方法はお勧めしません。どうしてもという場合に最後の手段として使ってください。

 

以下、Securityコンポーネントを読み込んでいる該当コントローラに指定。

public function beforeFilter() {
    parent::beforeFilter();

    if ($this->params['action'] == アクション名) {
         $this->Security->csrfCheck = false;
         $this->Security->validatePost = false;
    }
}

これを行うことにより、Securityコンポーネントの一番の強みの機能を失うことになりますが、同時にチェックをスルーするので処理を通すことができます。

 

これは本当に最後の手段なのでできれば行わない方がいいです。とだけ言っておきます。僕は使いません。

 

それではまた会いましょう。

 

 

スポンサードリンク

運営サービスPR

スポンサードリンク

運営サービスPR