VK APIを使用したAjaxサイトユーザーの単純なクライアントおよびサーバー認証

1つのプロジェクトでは、クライアント側(javascript Open APIを使用)とサーバー側(PHPを使用)の両方でVKontakte APIを使用してサイトのユーザーを承認する必要がありました。



VK APIへのアクセス許可



VKontakteには、何がどのように、そしてどのようにクライアント認証の例が詳細に記述されているか、さらにVKontakte APIを介した認証を備えたネットワーク上のサイトがすでに多数あるため、タスクは一見興味深いものではありません。



2つのユーザーフレンドリストを取得してみましょう。1つはサーバーAPIを使用し、もう1つはクライアントを使用します。

同時に、実際には、認可プロセスの両方のオプションを扱います。



ただし、最初に、タスクの詳細をもう少し詳しく説明します。

  1. ページをもう一度リロードするのではなく、Ajaxを介してのみサーバーとのすべての通信を行います。
  2. ユーザーの場合、承認プロセスでは、「後戻り」をできる限り少なくする必要があります。つまり、すべてをできるだけ便利に行う必要があります。


次のHTMLコードを用意しましょう
<!doctype html> <html> <head> <meta charset="utf-8"> <title>  </title> <link rel="stylesheet" href="style.css" /> <script src="script.js"></script> </head> <body> <section id="serverApi"> API</section> <section id="clientApi"> API</section> </body> </html>
      
      





クライアント認証


クライアント認証に複雑なことは本当にありません。

ドキュメントによると、 openapi.jsを非同期に読み込み、 window.vkAsyncInit



イベントでVK.init({appid: YOUR_APP_ID})



をハングさせるだけで十分です。その後、 VK.Auth.login(authInfo, YOUR_APP_PERMISSIONS)



関数VK.Auth.login(authInfo, YOUR_APP_PERMISSIONS)



呼び出して実行します。ユーザー認証。



Open APIによる承認とリクエスト
 var vk = { data: {}, api: "//vk.com/js/api/openapi.js", appID: YOUR_APP_ID, appPermissions: YOUR_APP_PERMISSIONS, init: function(){ $.js(vk.api); window.vkAsyncInit = function(){ VK.init({apiId: vk.appID}); load(); } function load(){ VK.Auth.login(authInfo, vk.appPermissions); function authInfo(response){ if(response.session){ //   vk.data.user = response.session.user; vk.getFriends(); }else alert("  !"); } } }, getFriends: function(){ VK.Api.call('friends.get', {fields: ['uid', 'first_name', 'last_name'], order: 'name'}, function(r){ if(r.response){ r = r.response; var ol = $('#clientApi').add('ol'); for(var i = 0; i < r.length; ++i){ var li = ol.add('li').html(r[i].first_name+' '+r[i].last_name+' ('+r[i].uid+')') } }else alert("     "); }) } } $.ready(vk.init);
      
      





まず、ここで使用する関数がjQuery



ではないことをすぐに予約します。 ただし、その目的は直感的ではない可能性があるため、この機能またはその機能が何をするのかを説明します。 すべてのjQuery



コードの転送のように、それらの独立した実装は難しくありません。



だから

$.ready(function)



-これはDOMContentLoaded



のハンドラーです。

$.js(text)



-JavaScriptファイルを非同期でロードします。

$(element)



-DOMノードelement



ラッパーを返します。

$(element).add(node)



- element



新しいノードnode



子を作成し、そのラッパーを返します。

$(element).html(string)



element.innerHTML = string



ラッパー。



基本的に、このコードは次のことを行います。

ドキュメントの準備が整うと、VKontakte APIが読み込まれ、初期化の後、 VK.Auth.login()



メソッドがVK.Auth.login()



れます。これにより、ユーザーがクライアントアプリケーションにデータを提供するための同意を確認する必要があるバナーカッターを正常に「ブロック」するポップアップウィンドウ表示されます。

authInfo



関数authInfo



、ユーザーの同意またはauthInfo



同意の後に呼び出され、承認が成功した場合、友人のリストを要求します。



したがって、クライアント部分は完全と見なすことができますが、ブラウザが確認ウィンドウをブロックする可能性があることをユーザーに警告することは価値があります。



サーバー認証


サーバー認証はもっと楽しいです。 サードパーティのサイトからVKontakte APIにアクセスするためのサーバー認証メカニズムは、OAuth 2.0プロトコルに基づいています。



承認プロセスは次のとおりです。

  1. ユーザーのブラウザで、アプリケーションが自分のデータにアクセスできるページを表示する必要があります。
  2. アプリケーションの認証に成功すると、ユーザーのブラウザは、認証ダイアログを開くときに指定されたREDIRECT_URIアドレスにリダイレクトされます。 この場合、アクセスキーを取得するためにコードがGETパラメーターで送信されます。
  3. APIへのリクエストを行うために必要なaccess_tokenアクセスキーを受け取るために、アプリケーションコードと秘密データを特別なアドレスに転送してリクエストを満たす必要があります。


残念ながら、2番目のポイント、つまりブラウザーのリダイレクトは常に機能するわけではありません。より正確には、IE以外のどこでも機能しません。ユーザーが初めてアプリケーションにデータへのアクセスを許可するときです。 そして、開発者が倒錯しなくなったらすぐに、望んでいるコードを手に入れるだけです。

ある有名な音楽サービスでの認可の例
1つの音楽サービスでVK APIを使用した承認

確かに、開いているページに「ログイン成功」と書く代わりに、かなり長い間、書かれているとおりに行う必要はないという警告があります。このメッセージはトピックの冒頭の写真で見ました。


さらに、追加のウィンドウを開くと、再びブロックされる危険性があります。



幸いなことに、ウィンドウを開くためのリンクがわかっている場合は、ブロックされないようにするための多くの良い方法があります。 たとえば、古き良きiframe



タグはまだHTML標準のランクにあり、私たちのタスクに最適です。



まず、住所がわかっているので、フレームを開いて、すべてを手動で実行できるリンクをユーザーに表示できます。



次に、リダイレクトが発生し、ドメインのページがフレームで開いた場合、フレームからメインウィンドウにアクセスし、自動的にフレームを閉じる機能を開始できます。 同時に、サーバーにはすでにaccess_tokenがあります。これをセッションに保存し、メインウィンドウからサーバーへのリクエストを実行することで、回答を受け取ることができます。 ページの再読み込みは行われず、問題が完全に解決されます。



第三に、リダイレクトが行われず、ユーザーがアプリケーションのアクセス確認ページを手動で開いた場合、ドメインからページへのリダイレクトが既にあります。これは、フレームではなくメインのページではなく開かれます。 残念ながら、これは再起動ですが、それは可能な限り小さな犠牲です。 このページからユーザーをメインページに再度送信できます。再起動せずに2回目の認証が行われます。



PHPOAuth VK APIアクセスクラスの実装は、githubで簡単に見つけることができます(PHP> = 5.4)。

(このクラスは、 ユーザーvladkensによって作成された可能性が非常に高いことが偶然判明しました。



次に、最も興味深いものに移りましょう。

ページのAJAXリクエストに応答するサーバースクリプトを実装します
 <?php require_once('vk.php'); session_start(); function getPostStr($data, $default = false){ //   -  $_POST[$data] if(!isset($_POST[$data])) return $default; $data = $_POST[$data]; $data = htmlspecialchars(strip_tags(trim($data))); return ($data != "" ? $data : $default); } function error($code, $text, $params = Array()){ $result = Array('error' => Array('code' => $code, 'message' => $text)); if(count($params) > 0) foreach($params as $key => $value) $result['error'][$key] = $value; die(json_encode($result)); } $vkConf = Array( 'appID' => YOUR_APP_ID, 'apiSecret' => YOUR_API_SECRET, 'callbackUrl' => YOUR_DOMAIN . '/auth.php', 'apiSettings' => YOUR_APP_PERMISSIONS ); $vk = (isset($_SESSION['accessToken'])) ? new VK($vkConf['appID'], $vkConf['apiSecret'], $_SESSION['accessToken']) : null; function userIn($vk, $vkConf){ //   unset($_SESSION['accessToken']); $vk = new VK($vkConf['appID'], $vkConf['apiSecret']); $authorizeUrl = $vk -> getAuthorizeURL($vkConf['apiSettings'], $vkConf['callbackUrl']); error(-1, "  !", Array('url' => $authorizeUrl)); } function getFriends($fields, $order, $vk){ //     $userFriends = $vk -> api('friends.get', array('fields' => $fields, 'order' => $order)); $result = Array(); foreach($userFriends['response'] as $key => $value){ $result[] = Array('firstName' => $value['first_name'], 'lastName' => $value['last_name'], 'uid' => $value['uid']); } echo json_encode($result); } $method = strtolower($api -> getStr("method")); switch($method){ case "user.in" : userIn($vk, $vkConf); break; case "friends.get" : getFriends(getPostStr("fields"), getPostStr("order"), $vk); break; default: Api::error(0, "   Api"); } ?>
      
      





POSTメソッドを使用してこのページにリクエストを送信します。このmethod



パラメータには、サーバーで実行するメソッドの名前が含まれます。



認証を成功させるuser.in



に、メインページの準備ができたらuser.in



にリクエストを送信します。サーバーはエラーコード-1



で応答し、キャッチして処理します。

同時に、エラーとともに、ユーザーがアプリケーションへのアクセスを確認する必要があるページのURLも表示され、フレームで開きます。

クライアントスクリプトをAJAX処理で補完します
 function Api(method, params, callback){ if(!params) params = {}; $.ajax($.copy({method: method}, params), 'server.php', function(r){ if(r.error){ switch(r.error.code){ case -1: { // notAuth var div = $(document.body).add('div').id('authPopup'), iframe = div.add('iframe').attr({src: r.error.url}); div.add('p').html('                 ,   -          .      ,      ,   ').add('a').attr({href: r.error.url}).html(' '); $.splash.open({onclose:function(){ div.remove() }}); } break; default: alert(r.error.code+': '+r.error.message); } }else if(callback) callback(r); }); } $.ready(function(){ Api('user.in'); });
      
      





$



関数について簡単に説明します。

$.copy(object1, object2)



object1



すべてのパラメーターをコピーします。

$.ajax(text, addr, callback)



POST要求を送信し、 text



メッセージを渡します。 応答はJSONの形式を取り、 callback



関数に渡します。

$(element).id(elemID)



element.id = elemID



ラッパー。

$(element).attr(object)



-要素element



タグ属性を設定します。 object



キー-属性名、キー値は属性値として設定されます。

$(element).remove()



- element



削除しelement



;

$.splash.open(params)



-半透明の暗いブロックでブラウザーウィンドウを描画します。 params.onclose



パラメーターは、 $.splash.close()



ときに呼び出される関数です。



そのため、ドキュメントをロードすると、アプリケーションのクライアント認証ウィンドウとサーバー認証確認ページのあるフレームがポップアップ表示されます。 または、フレーム内の確認ウィンドウの代わりに警告が表示されますが、この場合、ユーザーがアプリケーションの権限を確認できるリンクがあります。



リダイレクトが実行されるページを作成するためだけに残ります。

VKサーバー認証確認ページ
 <?php require_once('vk.php'); session_start(); $vkConf = Array( 'appID' => YOUR_APP_ID, 'apiSecret' => YOUR_API_SECRET, 'callbackUrl' => YOUR_DOMAIN . '/auth.php', ); if(isset($_REQUEST['code'])){ $vk = new VK($vkConf['appID'], $vkConf['apiSecret']); $accessToken = $vk -> getAccessToken($_REQUEST['code'], $vkConf['callbackUrl']); $_SESSION['accessToken'] = $accessToken['access_token']; }else die('Auth failed'); ?> <!doctype html> <html> <head> <meta charset="utf-8" /> <title>     </title> <script> $.ready(function(){ if(window.top){ window.top.vk.getFriends(); window.top.$.splash.close(); } }) </script> </head> <body> <h4> !</h4> <p>   <a href="YOUR_DOMAIN">  </a>,   </p> </body> </html>
      
      





ここでは、 access_tokenをセッション変数に保存するだけで、Ajaxリクエストを処理するスクリプトがそれを使用できるようになります。 さらに、このページがフレームで開く場合、メインウィンドウメソッドを呼び出して、サーバーに友人のVKリストとフレームを閉じるメソッドを要求します。



次に、VK APIを介したサイトユーザーの控えめな承認の実装を示します。

スクリーンショット
結果






宿題として、確認ページからYOUR_DOMAIN



ページがフレームで開かれていない場合はYOUR_DOMAIN



ページにリダイレクトし、 userIn()



がセッション内にある場合はその有効性がチェックされ、キーが有効な場合は新しい認証の代わりに使用されるようにuserIn()



メソッドを改善します。



All Articles