web-dev-qa-db-ja.com

angle_deviseでログアウトするまでグローバルに現在のユーザーを維持する方法は?

ページの読み込み時にcurrentUser()によってサーバーを1回だけ呼び出す、グローバルにアクセス可能な独自のサービスを作成するには、ユーザーがログインしている場合はそれを保持し、ログアウトするまでデータをコントローラーまたは状態に提供しますか?今、私は多くの状態またはコントローラーで何度も解決していますcurrentUser()、ドキュメントで見つけました: authparseresponse 独自のサービスを作成する可能性がありますが、方法がわかりませんこれを正しい方法で処理します。

たとえば、ui-routerでは2つのサーバー呼び出しがあり、ページが読み込まれた場合にのみ十分です。

.state('login', {
  url: '/login',
  templateUrl: 'auth/_login.html',
  controller: 'AuthCtrl',
  onEnter: [
    '$state', 'Auth',
    function($state, Auth) {
      Auth.currentUser().then(function() {
        $state.go('home');
      });
    }
  ]
})
.state('dashboard', {
  url: '/dashboard',
  templateUrl: 'dashboard.html',
  onEnter: [
    '$state', 'Auth',
    function($state, Auth) {
      Auth.currentUser().then(function(user) {}, function(err) {
        $state.go('home');// user not logged in
      });
    }
  ]
})

または、次のサーバーがNavControllerを呼び出すたびに:

app.controller('NavController', [
  '$state', '$scope', 'Auth', function($state, $scope, Auth) {
    $scope.signedIn = Auth.isAuthenticated;
    $scope.logout = Auth.logout; // logout function
    Auth.currentUser().then(function(user) {
      $scope.user = user;
    });
    $scope.$on('devise:login', function(e, user) {
      $scope.user = user;
    });
    $scope.$on('devise:logout', function(e, user) {
      $scope.user = {};
      $state.go("home");
    });
  }
]);

私は答えのない同様の質問を見つけました: stackoverflow

19
luzny

ご存知のとおり、ファクトリはシングルトンオブジェクトであり、基本的にはデータ共有に使用されます。任意のコントローラーに注入でき、依存関係として機能します。これで問題が解決する場合もあります。このサービスを状態解決ブロックに挿入し、ユーザーが存在するかどうかを確認してから、ファクトリのユーザーフェッチ関数を呼び出します。

app.factory("User", function($http, $q, $rootScope) {
var user = null;
return {
    fetchUser: function() {
        /*your ajax call that return current user*/
        user = YOUR_SERVER_RESPONSE;
        return user;

    },
    getUser : function(){
        return user;
    },
    setUser : function(u){
        user = u;
    }
}

});

状態構成ブロックは次のようになります

  .state('dashboard', {
  url: '/dashboard',
  templateUrl: 'dashboard.html',
  resolve : function(User){
    if(User.getUser()){
        return User.getUser();
    }else{
        return User.fetchUser();
    }
  }
})
11
Bharat Bhushan

大規模なAngularアプリでユーザー認証を処理する必要があり、この記事は非常に便利であることがわかりました: https://medium.com/opinionated-angularjs/techniques-for- authentication-in-angularjs-applications-7bbf0346acec

「それを一度だけ実現する方法」に固有:

  • app.runブロックでサービスのinit()を呼び出すことができます
  • アプリの外部状態のresolve要件として追加します(ネストされた状態を使用する場合)

ユーザーのログイン状態を表すUserServiceサービスは、アプリケーション全体で状態を共有するのに適しています。ログインおよびログアウト機能は、このサービスを通じて公開でき、ユーザーの詳細もここに保存できます。 $resourceを拡張するUserApiを定義することは、実際のHTTPの懸念をユーザー状態の管理から分離するのにも役立つでしょう。

記事で取り上げられているその他の懸念事項:ページの更新後の永続的な状態、およびユーザーがログインしている場合にのみアクセスできるサイトの領域。

8
zayquan

メインのHTMLページの下部に次のJavaScript(jQuery)コードを追加することで、current_user情報の問題をangular)で解決しました。

$("meta[name=current_user]").data('current_user', {
    id: <%=j current_user.id.to_s %>, 
    username: "<%=j current_user.full_name.to_s %>"
});

必要な情報を解析できます。これはたまたまRails Projectであり、必要なのはIDとNAMEだけでした(IDを使用してUserファクトリオブジェクトをクエリし、JSONを受け取ることができます)必要に応じて完全な情報)。

次に、AngularJS Controllerに追加できます(mine iscoffeescript):

# Grab User Info
current_user = angular.element("meta[name=current_user]").data 'current_user'

# Stop Here if you Have the Info you Need
$scope.user = current_user

# **** OR Get More Info if User is Logged In 
if current_user.id is not undefined
   $scope.user = User.get {id: current_user.id}

これが私のファクトリコードユーザー向けです(coffeescriptagain):

# In order to prevent minification from effecting the code
# must wrap functions as arrays and pass in the variables as 
# strings before the function call
app.factory "User", ["$resource", ($resource) ->
    $resource("/api/angular/users/:id", 
    { id: "@id" }, 
    {
        update: { method: "PUT" }
    })
]

ご不明な点がございましたらお知らせください。

1
blnc

編集:angular_deviceモジュールで使用するためにいくつかのパーツを変更する

一般的に、私はここで提供されるソリューションを使用しています( https://vickev.com/#!/article/authentication-in-single-page-applications-node-js-passportjs-angularjs ) HTTP呼び出しごとにユーザーがログインしているかどうかを確認する方法について説明します。

ユーザーがログインしている場合は、ロードを確認します

myApp.config(['$routeProvider','$locationProvider',
function($routeProvider, $locationProvider) {
//================================================
// Check if the user is connected
//================================================
var checkLoggedin = function($q, $rootScope, Auth, User){
  // Initialize a new promise
  var deferred = $q.defer();
  Auth.currentUser().then(function(userObj){
    deferred.resolve();
    //option a: just save the user object into the $rootScope
    $rootScope.User = userObj;
    //option b: create a factory 'User' and a method 'save()' which parses the JSON returned from your Server 
    User.save(userObj);
  }, function(error){
    deferred.reject();
  });
  return deferred.promise;
};


//================================================
// Define all the routes
//================================================
$routeProvider
  //Start page, where the user gets a list of registered SO and can add new ones
  .when('/', {
    templateUrl: 'templates/index.html', 
    controller: 'indexCtrl',
    resolve: {
      loggedin: checkLoggedin
    }
  })
  .when('/login', {
    templateUrl: 'templates/login.html', 
    controller: 'loginCtrl'
  })
  // do more here
  .otherwise({
      redirectTo: '/'
  });
}]).run(function($rootScope, $http){
//Do some initial tasks or set some values
});

「User」という名前の追加のサービスを作成し(サービスはシングルトンであるため)、いくつかのメソッドを定義します。 save()およびget()は、ユーザーをサービスシングルトンに保存し、必要な場所に返すようにします。関数「checkLoggedIn」を使用すると、ルートの「解決」オプションを定義でき、promiseが解決された場合、ユーザーは制限されたページにアクセスできます。

1
Fer To

ユーザーの詳細をGlobal.userに保存します。コントローラーまたはサービスで「グローバル」モジュールを使用します。

ユーザーにアクセスする必要がある場合は、Global.userを使用してアクセスします。

0
ashishkumar148