AngularJS和ExpressJS会话pipe理?

我想保持整个页面的会话。 对于这个项目,我使用expresJs,nodeJS作为服务器端。 AngularJS在前端。

我不确定,当查看更改或URL更改时如何处理会话。 因为我需要照顾expresJS路由器或者angularJs路由器

请让我知道,我应该遵循什么方法。

angularJS路由器

myApp.config(['$routeProvider', function($routeProvider) { $routeProvider.when('/welcome', {templateUrl: 'partials/welcome.html', controller: 'MyCtrl2'}); $routeProvider.when('/login', {templateUrl: 'partials/login.html', controller: 'MyCtrl2'}); $routeProvider.when('/signup', {templateUrl: 'partials/signup.html', controller: 'singupController'}); $routeProvider.otherwise({redirectTo: '/'}); }]); 

注册控制器

  myApp.controller('singupController',function($scope,$rootScope,$http){ $scope.doSingnup = function() { var formData = { 'username' : this.username, 'password' : this.password, 'email' : null }; var jdata = JSON.stringify(formData); $http({method:'POST',url:'/signup',data:jdata}) .success(function(data,status,headers,config){ console.log(data); }). error(function(data,status,headers,config){ console.log(data) }); } }) 

ExpressJS路由器

  module.exports = exports = function(app, db) { var sessionHandler = new SessionHandler(db); var contentHandler = new ContentHandler(db); // Middleware to see if a user is logged in app.use(sessionHandler.isLoggedInMiddleware); app.get('/', contentHandler.displayMainPage); app.post('/login', sessionHandler.handleLoginRequest); app.get('/logout', sessionHandler.displayLogoutPage); app.get("/welcome", sessionHandler.displayWelcomePage); app.post('/signup', sessionHandler.handleSignup); app.get('*', contentHandler.displayMainPage); // Error handling middleware app.use(ErrorHandler); } 

注册后,我想redirect到login页面。 我怎么能在上面的路由器。 我应该使用以下哪一个来更改应用程序的视图1)angularJS的$位置2)ExpresJS的redirect

谢谢大家

所以我有同样的问题,公平的,我可能已经读了一个地方,我不记得了。

问题 :Angular构build单页面应用程序。 刷新之后,您将取消范围并使用经过身份validation的用户。

途径

AngularJS模块提供了一个称为run的启动函数,它在加载页面时总是被调用。 完美刷新/重新加载。

 myApp.run(function ($rootScope, $location, myFactory) { $http.get('/confirm-login') .success(function (user) { if (user && user.userId) { $rootScope.user = user; } }); } 

快递会话会为您保存会话,并使用您的浏览器发送的会话身份validation您的身份。 所以它总是知道你是否被authentication。

 router.get('/confirm-login', function (req, res) { res.send(req.user) } ); 

我所要做的只是刷新后,所有的依赖被加载,问我是否通过身份validation,并设置$ rootScope.user = authenticatedUserFromExpress;

这里有两个不同的概念 – 服务器端会话状态和Angular客户端的用户状态。 在express中,您可以通过req.session使用会话来pipe理基于会话的数据。

在angular度方面,你的控制器只有一个范围。 如果要跟踪多个控制器上的某些数据,则需要创build一个服务来存储数据,并将服务注入到所需的控制器中。

典型的生命周期是首先检查服务中是否有数据,如果是这样的话。 如果没有,等待数据填充(由用户或应用程序或其他),然后检测这些变化,并与您的服务同步。

注册控制器

 function SignupCtrl($scope, $http, $location) { $scope.form = {}; // to capture data in form $scope.errorMessage = ''; // to display error msg if have any $scope.submitPost = function() { // this is to submit your form can't do on //traditional way because it against angularjs SPA $http.post('/signup', $scope.form). success(function(data) { // if success then redirect to "/" status code 200 $location.path('/'); }).error(function(err) { // if error display error message status code 400 // the form can't be submitted until get the status code 200 $scope.errorMessage = err; }); }; } 

sessionHandler.handleSignup

  this.handleSignup = function(req, res, next) { "use strict"; // if you have a validate function pass the data from your // Signup controller to the function in my case is validateSignup // req.body is what you need validateSignup(req.body, function(error, data) { if(error) { res.send(400, error.message); // if error send error message to angularjs }else { // do something else // rmb to res.send(200) } }); } 

validatesignup

 function validateSignup(data,callback) { "use strict"; // the data is req.body //so now you can access your data on your form // eg you have 2 fields name="password" and name="confirmPassword on your form" var pass = data.password, comPass = data.confirmPassword; if(pass != comPass){ callback(new Error('Password must match'), null); // then show the error msg on the form by using //angular ng-if like <div ng-if="errorMessage">{{errorMessage}}</div> }else{ callback(null, data); } } 

希望这个帮助

在这里的所有答案中,我最喜欢@ alknows的方法。 但是,像其他答案一样,您向服务器发送请求以获取当前的用户数据,我遇到了一些问题:

  • 由于您的AJAX($ http)调用,您必须处理竞争条件。
  • 您在向服务器发送不必要的请求之后,它已经呈现您的index.html

我尝试了@alknow的方法,在解决了由于我的angular度应用程序控制器和configuration需要当前用户执行他们的工作而导致的许多竞争条件之后,我find了解决scheme。 在适当的时候,我尽我所能避免出现竞争状况,所以我有点不情愿继续这种做法。 所以我想到了一个更好的方法:使用index.html将当前用户数据向下发送,并将其存储在本地。

我的方法:将currentUserembedded到客户端的index.html&本地存储

在你的服务器上的index.html ,制作一个脚本标记来保存你想传递给客户端的任何数据:

“`

 <!--YOUR OTHER index.html stuff go above here--> <script id="server-side-rendered-client-data" type="text/javascript"> var __ssr__CData = { currentUser: { id: '12345', username: 'coolguy', etc: 'etc.' } } </script> 

“`

然后,按照@alknows的build议,在app.js或任何你启动你的angular度的应用程序,添加app.run(..., () => {...}) 。 在app.run()中,您将需要获取服务器端呈现的客户端数据对象,我将其__ssr_CData命名为__ssr_CData这样我就不太可能在后面的其他javascript中碰到跨全局名称空间的名称冲突:

 var myAngularApp = angular.module("mainApp", ['ngRoute']); myAngularApp.run(function ($rootScope) { const currentUserFromServer = __ssr__CData.currentUser const currentUserAccessTokenFromServer = __ssr__CData.accessToken const currentUser = CurrentUser.set(currentUserAccessTokenFromServer, currentUserFromServer) $rootScope.currentUser = currentUser }); 

如你所知, app.run()将在页面完成重新加载时被调用。 CurrentUser是一个在单页面环境中pipe理angular度应用程序当前用户的全局类。 因此,当我调用CurrentUser.set(...)它将当前用户数据存储在稍后可以通过调用CurrentUser.get()在angular度应用程序中检索的位置。 所以,在你的任何angular度的应用程序控制器,你现在可以检索当前用户服务器提供的只是这样做:

 myAngularApp.controller('loginController',function($scope, $rootScope, $http){ //check if the user is already logged in: var currentUser = CurrentUser.get() if(currentUser) { alert("HEY! You're already logged in as " +currentUser.username) return $window.location.href = "/"; } //there is no current user, so let user log in //... } 

在这个例子中,我使用CurrentUser.get() (我在上面解释过)从服务器获取之前存储的当前用户。 我也可以通过访问$rootScope.currentUser检索当前用户,因为我也存储在那里。 随你便。

 myAngularApp.controller('signupController',function($scope, $rootScope, $http){ //check if the user is already logged in: var currentUser = CurrentUser.get() if(currentUser) { alert("HEY! You're already logged in as " +currentUser.username) return $window.location.href = "/"; } //there is no current user, so let user signup //... you run your signup code after getting form data $http({method:'POST',url:'/signup',data:jdata}) .success(function(data,status,headers,config){ //signup succeeded! //set the current user locally just like in app.js CurrentUser.set(data.newUser) //send user to profile return $window.location.href = "/profile"; }) .error(function(data,status,headers,config){ //something went wrong console.log(data) }); } 

现在,在新用户注册后,您的服务器将从AJAX调用中返回新用户。 我们通过调用CurrentUser.set(...)将该新用户设置为当前用户并将用户发送到他们的configuration文件。 现在,您可以像查看当前用户是否存在于login和注册控制器中那样获取configuration文件控制器中的当前用户。

我希望这可以帮助任何遇到此问题的人。 为了供您参考,我正在使用客户端会话模块来处理服务器上的会话。