FeathersJsでロール別にユーザーを分割する

画像

それは過小評価されているfeathersjsフレームワークについてです。



一言で言えば、それがどのように機能するかは、 ここで読むことができます 。 ある朝、メッセンジャーで新しいTKが届きました。次のように説明されました。2つのサービス(つまり、バックエンドが2つの異なるフロントからの認証要求を処理するため)にユーザーを分ける必要があります。



つまり、VueJsで書かれた2つの分割されたフロント、異なるドメイン名に配置され、共通のバックエンドが羽で書かれています(そして当然、ロールを持つデータベース内の1つのユーザーテーブル)。



つまり、テーブルには2つのそのようなフィールドが含まれる場合があります



email pass project +------------+--------+------- 1@gmail.com 123 front_one 1@gmail.com 123 front_two
      
      





当然、パスワードはハッシュされます。



サービスに入るためのモジュールとして、 feathers-authenticationpassportjsの羽に適合したバージョン)を使用します。

したがって、ローカルログインに関しては、すべてが簡単です。 ログイン/パスワードのペアを持つリクエストがどこに来たのかを判断するために、「project」などの別のパラメータをリクエスト本文の先頭に挿入し、このパラメータを使用してデータベースで必要なユーザーを検索できます。



ローカル認証ユーザーの作成方法についてもう少し詳しく説明します。 認証用の別のファイル(ファイルであり、サービスを生成しませんでした)auth.jsを作成し、app.jsに接続しました。 auth.jsはこのようになります



 const authentication = require('feathers-authentication'); const jwt = require('feathers-authentication-jwt'); const local = require('feathers-authentication-local'); const oauth2 = require('feathers-authentication-oauth2'); const FacebookStrategy = require('passport-facebook'); const commonHooks = require('feathers-hooks-common'); module.exports = function () { const app = this; const config = app.get('authentication'); app.configure(authentication(config)); app.configure(jwt()); app.configure(local(config.local)); app.service('authentication').hooks({ before: { create: [ commonHooks.lowerCase('email'), authentication.hooks.authenticate(config.strategies) ], remove: [ authentication.hooks.authenticate('jwt') ] } }); };
      
      





一般的に、今は何も面白いものはありません。私が注意したいのは、フックを個別のファイルに入れなかったということです(標準の生成サービスを呼び出すときに起こります)。それは何のためですか。



次に、魔法を追加します。 ドキュメントを調べてみると、verifier classが見つかりまし 。これは拡張して機能に追加できます。 ローカル認証用の新しい構成を匿名関数に追加しました



 app.configure(local({ Verifier: CustomVerifier }));
      
      





そして、私の新しいクラスを呼び出しました



 class CustomVerifier extends Verifier { verify(req, username, password, done) { return this.app.service('users').find({ query: { email: username, roles: req.query.project } }).then(res => { const user = res.data[0]; if (user) { const userId = res.data[0].id; this._comparePassword(user, password).then(() => { if (!user.isVerified) { done(null) } else { done(null, user, { userId: userId }); } }).catch(err => { done(null) }) } else { done(null) } }) } }
      
      





このクラスは何をしますか? まず、ユーザーサービスthis.app.service( 'users')に接続し、クエリパラメーターを指定してfindメソッドを呼び出します。 つまり、2つのフィールドで必要なユーザーのデータベースを検索し、それが見つかった場合、答え(res変数)にユーザーの配列があり、ユーザーが見つからなかった場合、配列は空を返します。 次に、f-tionを呼び出します



 this._comparePassword()
      
      





ここでは、ユーザーが見つけたパラメーターと、前面から送られたパスワードを渡します。 _comparePassword関数はパスワードをハッシュし、それをデータベース内のパスワードと比較します。パスワードが一致する場合は、次に呼び出します()



 done(null, user, { userId: userId });
      
      





ここで、最初の引数はエラーオブジェクト、2番目は現在のユーザー、3番目はデータベース内のユーザーID、done()は正しいトークンを返します。 null引数のみをdone()に渡すと、リクエストのステータスは401になり、レスポンスでは次のようになります



 lassName:"not-authenticated" code:401 errors:{} message:"Error" name:"NotAuthenticated"
      
      





そして、それで終わりです。しかし、facebook経由で私たちのサービスにアクセスすることもできます。 これを可能にするには、匿名関数に次を追加する必要があります。



 app.configure(oauth2(Object.assign({ name: 'facebook', Strategy: FacebookStrategy, Verifier: CustomVerifierFB }, config.facebook)));
      
      





このコードでも、「Verifier:CustomVerifierFB」というパラメーターのみに関心があります。 ローカル登録の場合と同様に、組み込みのVerifierクラスを拡張します。 fbを介してログインすると、フロントはバックの特定のURLにリクエストを送信しませんが、リンクをクリックします。つまり、フロントでは次のようになります。



 <a href="/auth/facebook">  Fb</a>
      
      





簡単に言えば、リンクをクリックすると、バックエンドへのリダイレクトが発生し、バックエンドはFBにリダイレクトされ、FBはバックエンドにリダイレクトされ、バックエンドは生成されたトークンをCookieに書き込み、フロントページに送信します。 前面では、Cookieを解析し、次のリクエストを新しいトークンで背面に送信する必要があります。



そして、この記事はありませんが、私は質問に多くの時間を費やしました-しかし、ユーザーがどこから来たのかを実際に調べる方法は?



答えは非常に簡単でした。 FBを介して入力するコンポーネントを登録する前に、これを行う必要があります。



 app.get('/auth/facebook', (req, res, next) => { referOrigin = req.headers.referer next(); }) app.configure(oauth2(Object.assign({ name: 'facebook', Strategy: FacebookStrategy, Verifier: CustomVerifierFB }, config.facebook)));
      
      





つまり、「/ auth / facebook」への移行をキャッチし、値req.headers.refererをグローバル変数(referOrigin)に書き込み、oauth2()の登録を開始します。 したがって、グローバル変数でホスト値を取得し、CustomVerifierFBクラスでこの値を使用できます。これは次のようになります。



 class CustomVerifierFB extends Verifier { verify(req, accessToken, refreshToken, profile, done) { const refer = referOrigin let roles = '' if (refer === 'front_one') { roles = 'front_one' } else { roles = 'front_two' } return this.app.service('users').find({ query: { facebookId: profile.id, roles: roles } }).then(res => { if (res.data[0]) { done(null, res.data[0], { userId: res.data[0].id }); } else { return this.app.service('users').create({ facebookId: profile.id, email: profile._json.email, first_name: profile._json.first_name, last_name: profile._json.last_name, gender: profile._json.gender, avatar: profile._json.picture.data.url, roles: roles, isVerified: true, username: profile._json.email + 'whereFromUser' }).then(createRes => { done(null, createRes, { userId: createRes.id }); }) } }) } }
      
      





検証では、次のことを行いました。





これにより、2つの異なる分野でユーザーを分離する問題を解決しました。



PS-次に、2つのユーザーグループのパスワード回復方法を書きます。



All Articles