Tarantoolのアプリケーション。 パート2. OAuth2認証

Tarantool用のアプリケーションを構築すると同時に、一見基本的なことをしたいときに毎回庭をフェンスしないようにするにはどうすればよいですか? これは、独自のTarantoolアプリケーションの作成方法に関する一連の記事の続きです。







今日は、ネットワークの相互作用、サードパーティのモジュールのインストールと使用の問題を検討します。













Tarantoolアプリケーションシリーズの内容



- パート1:ストアドプロシージャ

- パート2:OAuth2認証

- パート3:テストと起動







外部サービスとの相互作用



例として、 tarantool-authmanアプリケーションで Facebookを介したOAuth2認証の実装を検討します 。 OAuth2認証中、ユーザーはソーシャルネットワーク上のログインウィンドウにつながるリンクをたどります。 承認データを入力し、許可(許可)を確認した後、ソーシャルネットワークは、GETリクエストパラメーターの承認コードを使用してユーザーをサイトにリダイレクトします。 サーバーは、このコードをトークン(またはトークンのペア-アクセスと更新)に交換する必要があります。 トークンを使用すると、ソーシャルネットワークからユーザーに関する情報を取得できます。 この記事で OAuth2許可の詳細を読んでください













Tarantoolアプリケーションは、アクセストークン(トークン)の認証コード(コード)のソーシャルネットワークからのユーザー情報への交換を引き継ぎ、このトークンのユーザーデータも受信します。 私たちの場合、これはメール、名前、姓です。 アクセストークンの認証コードを交換するには、Facebookアプリケーションの設定であるclient_idとclient_secretとともに、コードと共にリクエストをFacebookに送信する必要があります。







バージョン1.7.4-151以降のTarantoolには、 libcurl



基づく組み込みのhttp.clientモジュールがあります。 このモジュールを使用すると、HTTP要求を送受信できます。 このモジュールを使用して、OAuth2認証を実装します。 最初に、authman / utils / http.luaモジュールでHTTPリクエストを送信するための補助関数を作成します。







 local http = {} local utils = require('authman.utils.utils') local curl_http = require('http.client') -- config —    authman function http.api(config) local api = {} --    local timeout = config.request_timeout function api.request(method, url, params, param_values) local response, body, ok, msg if method == 'POST' then -- utils.format —      placeholder' body = utils.format(params, param_values) --   pcall        ok, msg = pcall(function() response = curl_http.post(url, body, { headers = {['Content-Type'] = 'application/x-www-form-urlencoded'}, timeout = timeout }) end) end return response end return api end return http
      
      





pcall関数に注意する価値があります。 無名関数の実行中に発生する例外を処理します。 この場合、HTTPクライアントが生成するネットワークエラーを処理する必要があります。 pcall呼び出しの結果は、変数ok(true / false)およびmsg(エラーメッセージ、成功するとnil)に書き込まれます。







OAuth2アプリケーション認証



ソーシャルモデルを作成し、認証コードget_token(provider, code)



を使用してトークンを取得するメソッドと、プロファイルデータget_profile_info(provider, token, user_tuple)



を取得または更新するメソッドを作成します。 次の方法を検討してください。







 --    function model.get_token(provider, code) local response, data, token if provider == 'facebook' then --  http —  authman/utils/http.lua response = http.request( 'GET', 'https://graph.facebook.com/v2.8/oauth/access_token', '?client_id=${client_id}&redirect_uri=${redirect_uri}&client_secret=${client_secret}&code=${code}', { -- config —  ,       --       client_id = config[provider].client_id, redirect_uri = config[provider].redirect_uri, client_secret = config[provider].client_secret, code = code, } ) if response == nil or response.code ~= 200 then return nil else data = json.decode(response.body) return data.access_token end end end --     function model.get_profile_info(provider, token, user_tuple) local response, data user_tuple[user.PROFILE] = {} if provider == 'facebook' then response = http.request( 'GET', 'https://graph.facebook.com/me', '?access_token=${token}&fields=email,first_name,last_name', { token = token } ) if response == nil or response.code ~= 200 then return nil else data = json.decode(response.body) user_tuple[user.EMAIL] = data.email user_tuple[user.PROFILE][user.PROFILE_FIRST_NAME] = data.first_name user_tuple[user.PROFILE][user.PROFILE_LAST_NAME] = data.last_name return data.id end end end
      
      





次に、アプリケーションAPIメソッドを追加します。これにより、ユーザーを作成したり、Facebookを介して既存のメソッドにログインしたりできます。 このメソッドは、セッションデータとともにユーザーを返します。 セッションがどのように形成され、検証されるかについての詳細は、ソースコードに記載されています







 --  api  authman/init.lua function api.social_auth(provider, code) local token, social_id, social_tuple local user_tuple = {} if not (validator.provider(provider) and validator.not_empty_string(code)) then return response.error(error.WRONG_PROVIDER) end --  OAuth2- token = social.get_token(provider, code, user_tuple) if not validator.not_empty_string(token) then return response.error(error.WRONG_AUTH_CODE) end --     social_id = social.get_profile_info(provider, token, user_tuple) if not validator.not_empty_string(social_id) then return response.error(error.SOCIAL_AUTH_ERROR) end user_tuple[user.EMAIL] = utils.lower(user_tuple[user.EMAIL]) user_tuple[user.IS_ACTIVE] = true user_tuple[user.TYPE] = user.SOCIAL_TYPE -- ,    space     social_id social_tuple = social.get_by_social_id(social_id, provider) if social_tuple == nil then --   —   user_tuple = user.create(user_tuple) social_tuple = social.create({ [social.USER_ID] = user_tuple[user.ID], [social.PROVIDER] = provider, [social.SOCIAL_ID] = social_id, [social.TOKEN] = token }) else --    —    user_tuple[user.ID] = social_tuple[social.USER_ID] user_tuple = user.create_or_update(user_tuple) social_tuple = social.update({ [social.ID] = social_tuple[social.ID], [social.USER_ID] = user_tuple[user.ID], [social.TOKEN] = token }) end --    local new_session = session.create( user_tuple[user.ID], session.SOCIAL_SESSION_TYPE, social_tuple[social.ID] ) return response.ok(user.serialize(user_tuple, { session = new_session, social = social.serialize(social_tuple), })) end
      
      





メソッドが機能することを確認する方法は? まず、Facebookでアプリケーションを登録する必要があります。 Facebook開発者ページでそれやってみましょう。 作成したアプリケーションで、製品「Facebook経由でログイン」を追加し、redirect_uri-「OAuthリダイレクトの有効なURL」を指定する必要があります。 redirect_uriパラメーターは、ソーシャルネットワークでの認証が成功した後、ソーシャルネットワークがcodeパラメーターでユーザーをリダイレクトするサイトのURLです。 次に、ブラウザでURLを開きますhttps://www.facebook.com/v2.8/dialog/oauth?client_id=${client_id}&redirect_uri=${redirect_uri}&scope=email



、ここで







•client_id-Facebook上のアプリケーションのID。

•redirect_uri-前に指定したリダイレクトのURL。

•scope-権限のリスト(この場合、メールのみ)。







Facebookは許可の確認を求め、確認後、GETパラメーターコードでリダイレクトします。 これは、 api.social_auth()



メソッドで受け入れられるまさに承認コードです。 コードの機能を確認する前に、構成ファイルauthman / config / config.luaを作成します。このファイルには、Facebookアプリケーションの設定を示します。







 return { facebook = { client_id = 'id from fb application', client_secret = 'secret from fb application'', redirect_uri='http://redirect_to_your_service', } }
      
      





次に、コードが機能し、アプリケーションがソーシャルネットワークからユーザーに関する情報を受け取ることを確認しましょう。







 $ tarantool version 1.7.4-384-g70898fd type 'help' for interactive help tarantool> config = require('config.config') tarantool> box.cfg({listen = 3331}) tarantool> auth = require('authman').api(config) tarantool> code = 'auth_code_from_get_param' tarantool> ok, user = auth.social_auth('facebook', code) tarantool> user --- - is_active: true social: provider: facebook social_id: '000000000000001' profile: {'first_name': '', 'last_name': ''} id: b1e1fe02-47a2-41c6-ac8e-44dae71cde5e email: ivanov@mail.ru session: ... ...
      
      





サードパーティモジュールのインストール



多くの問題を解決するには、既成のソリューションを手元に置いておくとよいでしょう。 たとえば、バージョン1.7.4-151よりも前のバージョンのTarantoolでは、そのままHTTP要求を送信することはできませんでした。 tarantool-curlモジュールが必要でした。 現在、このモジュールはサポートされていないため、使用しないことをお勧めします。 ただし、他にも多くの有用なモジュールがあり、そのうちの1つ-tarantool-queue -FIFOキューの実装です。







tarantool-queueをインストールする方法はいくつかあります。 最初の、最も簡単で便利なものは、比較的最近、Tarantoolバージョン1.7.4-294に登場しました。







 $ tarantoolctl rocks install queue
      
      





他のTarantoolパッケージも、パッケージマネージャーを使用してインストールできます。 Tarantoolのモジュールの完全なリストは、Rocksページにあります







2番目の方法は、OSのパッケージマネージャーを使用することです。 ここで、インストール段階で接続していない場合は、Tarantoolリポジトリを接続する必要があります。また、対応するパッケージがリポジトリにあることを確認してください。 たとえば、Ubuntuの場合:







 $ sudo apt-get install tarantool-queue
      
      





3番目の方法はより複雑ですが、Tarantoolのアプリケーションだけでなく、既製のLuaモジュールも使用できます。 TarantoolとLuaのモジュールのインストールは、LuaRocksパッケージマネージャーを使用すると便利です。 それと利用可能なモジュールの詳細は、ドキュメントに記載れています 。 LuaRocksをインストールし、Tarantoolリポジトリで動作するように構成します。







 $ sudo apt-get install luarocks
      
      





次に、LuaパッケージだけでなくTarantoolのパッケージもインストールするようにLuaRocksを構成します。 これを行うには、次の内容の〜/ .luarocks / config.luaファイルを作成します。







 rocks_servers = { [[http://luarocks.org/repositories/rocks]], [[http://rocks.tarantool.org/]] }
      
      





モジュール自体をインストールし、その動作を確認します。







 #  tarantool-queue $ sudo luarocks install queue #       : $ tarantool version 1.7.3-433-gef900f2 type 'help' for interactive help tarantool> box.cfg({listen = 3331}) tarantool> queue = require('queue') tarantool> test_queue = queue.create_tube('test_queue', 'fifo') tarantool> test_queue:put({'task_1'}) tarantool> test_queue:put({'task_2'}) tarantool> test_queue:take() --- - [0, 't', ['task_1']] ...
      
      





そのため、複雑なアーキテクチャと外部の相互作用を備えたアプリケーションを作成できます。 次のパートでは、アプリケーションのテスト、および構成とバトルの開始について検討します。 じゃあね!








All Articles