AngularJS and ExpressJS session management?

I would like to save the session all over the page. For this project, I am using expressJs, nodeJS as the server side. AngularJS in front.

I am not sure how to handle the session when the view or URL changes. Because I need to take care of both the expressJS router and the angularJs router .

Which approach should I follow?

AngularJS router

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: '/'}); }]); 

Registration controller

 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 router

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

After registering, I would like to redirect to the login page. How can I do this in the above router. which of the following should I use to change the look of the application
1) $ location angularJS
2) redirect ExpressJS

+7
angularjs express
source share
4 answers

So I had the same problem, and frankly, I could read an approach where I don't remember anymore.

Problem : Angular creates single-page applications. After the upgrade, you release the scope and the authenticated user with it.

An approach

AngularJS modules offer a run function, which is invoked whenever a page loads. Ideal for upgrade / reboot.

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

An express session saves sessions for you and authenticates you using the session that your browser sends. Therefore, he always knows if you are authenticated or not.

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

All I had to do, after updating and downloading all the dependencies, was asking if I had completed authentication and set $ rootScope.user = authenticatedUserFromExpress;

+8
source share

There are two different concepts here: server-side session state and client-side user state in Angular. In express, you can use a session through req.session to manage session-based data.

On the angular side, your controllers have only scope. If you want to track some data on several controllers, you need to create a service for storing data and enter the service in the necessary controllers.

A typical life cycle is to first check if there is data in the service, if they use it. If not, wait until the data is filled out (by the user or application or something else), then it will detect these changes and synchronize with your service.

+7
source share

registration controller

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

hope this help

+1
source share

Of all the answers here, I like @alknows best suited. However, like other answers that suggest sending a request to the server to receive current user data, there are several problems that I take with me:

  • You must deal with race conditions as a result of an AJAX call ($ http).
  • You send an unnecessary request to the server after it has already displayed your index.html

I tried the @alknow approach, and it worked for me after I was able to resolve many race conditions that arose as a result of using my application controllers and wiki angular, which need the current user to do their job. I try my best to avoid race conditions when appropriate, so I was a little reluctant to continue this approach. So I thought of a more efficient approach: send the current user data down with index.html and save it locally.

My approach: insert currentUser in index.html and save locally on the client

In the index.html on your server, make a script tag to store any data that you want to pass to the client:

`` ``

 <!--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> 

`` ``

Then, as suggested by @alknows, in app.js or where you start your angular application, add app.run(..., () => {...}) . In app.run (), you'll want to grab the server-side client data object, which I named obscurely __ssr_CData , so I’m less likely to encounter name conflicts in the global namespace later in my other 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 }); 

As you know, app.run() will be called whenever the page does a full reload. CurrentUser is a global class for managing my current user of an angular application in a single page environment. Therefore, when I call CurrentUser.set(...) , it saves the current user data in a place that I can get later in my angular application by calling CurrentUser.get() . Therefore, in any of your angular application controllers, you can now get the current user provided by the server simply by doing this:

 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 //... } 

In this example, I used CurrentUser.get() , which I explained above, to get the previously saved current user from the server. I could also get this current user by contacting $rootScope.currentUser because I saved it too. It depends on you.

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

Now, after the new user has registered, your server has returned the new user from the AJAX call. We set the new user as the current user by calling CurrentUser.set(...) and sending the user to our profile. Now you can get the current user in the profile controller just like you to check if the current user exists in the login and registration controllers.

I hope this helps anyone who comes across this. For your reference, I use the client session module to handle sessions on my server.

0
source share

All Articles