如何使用angular _ design保持全局当前用户直到注销

How to keep globally current user until logout with angular_devise?

本文关键字:用户 注销 全局 angular 何使用 design      更新时间:2023-09-26

如何创建自己的可全局访问的服务,该服务将在页面加载时仅由currentUser()调用服务器一次,如果用户已登录,则将其保留并向控制器或状态提供数据,直到注销?现在我在很多状态或控制器currentUser()中解决了很多次,我在docs:authparseresponse中发现有可能创建自己的服务,但我不知道如何以正确的方式处理这一问题。

例如,在ui路由器中,我有两个服务器调用,只有当页面加载时才足够:

.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

正如我们所知,工厂是一个单例对象,基本上用于数据共享。我们可以将其注入任何控制器,并作为依赖项发挥作用。所以这可能也能解决你的问题。将此服务注入到您的状态解析块,并检查用户是否存在,如果不存在,则调用工厂的获取用户函数

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();
    }
  }
})

我不得不在一个大型Angular应用程序中处理用户身份验证,发现这篇文章非常有用:https://medium.com/opinionated-angularjs/techniques-for-authentication-in-angularjs-applications-7bbf0346acec

具体到"如何让它只发生一次":

  • 可以在app.run块中调用Service的init()
  • 将其添加为应用程序外部状态的resolve要求(如果使用嵌套状态)

代表用户登录状态的UserService服务可以很好地在整个应用程序中共享状态。登录和注销功能可以通过该服务公开,用户的详细信息也可以存储在这里。定义一个扩展$resourceUserApi可能也有助于将实际的HTTP问题与管理用户状态区分开来。

您将遇到的其他问题,这两个问题都在本文中介绍:跨页面刷新的持久状态,以及只有当用户登录时才能访问的站点区域。

我通过在主HTML页面的底部添加以下JavaScript(jQuery)代码来解决当前用户信息与angular的问题:

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

你可以解析任何你需要的信息,这恰好是一个Rails项目,我所需要的只是ID和NAME(带有ID I可以查询用户工厂对象并接收包含完整信息的JSON如果我需要的话)。

然后在您的AngularJS控制器中,您可以添加(我的是coffeescript):

# 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}

这是我的用户工厂代码(再次咖啡脚本):

# 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" }
    })
]

如果你有任何问题,请告诉我。

编辑:更改一些零件以与angular _ device模块一起使用

一般来说,我使用这里提供的解决方案(https://vickev.com/#/单页应用程序节点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"的附加服务(因为服务是singleton),定义一些方法,例如save()和get(),将User保存到服务singleton中,并在必要时返回它。使用"checkLoggedIn"功能,您可以为路由定义一个"解析"选项,如果承诺得到解析,用户就可以访问受限页面。

将用户详细信息保存在Global中。user在控制器或服务中使用"Global"模块。

当您必须访问用户时,请使用Global.user

进行访问