MEAN堆栈如何处理login和redirect

我有一个简单的MEAN堆栈应用程序,只是尝试了解身份validation,并使其工作。

你可以在github上签出完整的程序: https : //github.com/7seven7lst/chatterApp

在Angular(app.js)中,我有以下的个人资料路由被限制:

angular.module('chat', ['ui.router', 'chat.main', 'chat.signin', 'chat.profile']) .config(function($stateProvider, $urlRouterProvider, $httpProvider) { $urlRouterProvider.otherwise('/'); $stateProvider .state('home', { url: '/', templateUrl: 'views/main.html', controller: 'MainCtrl' }) .state('signin', { url: '/signin', templateUrl: 'views/signin.html', controller: 'SigninCtrl' }) .state('profile', { url: '/profile', templateUrl: 'views/profile.html', controller: 'ProfileCtrl' }); // the following will give angular injection error /* $httpProvider.interceptors.push(function($q, $state) { return { response: function(response) { // do something on success return response; }, responseError: function(response) { if (response.status === 401) { $state.go('home'); } return $q.reject(response); } }; }); */ }); 

我有NodeJSfunction来处理authentication:

 var express = require('express'); var bodyParser = require('body-parser'); var cookieParser = require('cookie-parser'); var path = require('path'); var session = require('express-session'); var passport = require('passport'); var LocalStrategy = require('passport-local').Strategy; // setup passport passport.use(new LocalStrategy( function(username, password, done){ if (username !== 'test' || password !='password'){ console.log("not loged in "); return done(null, false); // login failed } else { console.log("somehow we are here"); return done(null, {username: username}); } } )); passport.serializeUser(function(user, done){ done(null, user); }); passport.deserializeUser(function(user, done){ done(null, user); }) // middleware function to handle protected route var requireAuthentication = function(req, res, next){ if (req.isAuthenticated()){ next(); } else { console.log("401 should be sent here..."); res.end(401); //res.redirect('/login'); } } var app = express(); app.use(bodyParser.json()); app.use(bodyParser.urlencoded({ extended: false })); // middleware to parse the form data app.use(express.static(__dirname + '/public')); // server static file in public folder. app.use('/bower_components', express.static(__dirname + '/bower_components')); app.use(cookieParser()); app.use(session({ secrete: 'make this a good secret', resave: false, saveUninitialized: true })); app.use(passport.initialize()); app.use(passport.session()); app.get('/', function(req, res){ console.log("here, homepage"); res.sendFile('index.html'); }) app.post('/signin', passport.authenticate('local', { successRedirect: '/profile', failureRedirect: '/login' }), function(req, res){ res.send(req.user); }); app.get('/profile', [requireAuthentication, function(req, res){ console.log("here, profile page"); res.json(200, {username: req.session.passport.user.username}); }]) app.get('*', function(req, res){ res.redirect('/'); }) app.listen(8080, function(){ console.log("listening on port 8080"); }) 

我testing了我的应用程序,并没有从服务器发送401。 而angular度拦截器似乎不工作,如果我试图取消注释上述行。 我怎样才能得到在anuglar工作的保护路线?

从查看存储​​库代码,看起来像signin.html中的signin.html正试图调用提交signinfunction。 这个函数没有定义,所以没有请求被发送到服务器,因此没有响应。

编辑:

处理MEAN应用程序的身份validation时有两个独立的考虑因素。 在服务器和客户端上完成身份validation。

服务器

在服务器上,对于使用requireAuthentication中间件的路由,如果用户未通过身份validation,客户端将发送401个状态码响应。

在您的浏览器中,如果您inputlocalhost:8080/profile ,则将从服务器获得401响应。

客户

在客户端上,因为你没有指定你想要使用html5mode 。 客户端路由使用片段url(以#开头的url部分)完成。 url的这部分不会发送到服务器。 如果向localhost:8080/#/profile发出请求localhost:8080/#/profile ,则服务器在http请求中获取的path是/

/路线在服务器上configuration,以您的案件中的index.html文件作出回应。 index.html然后使请求加载angular度脚本并运行您的客户端代码。

此时, ui.router将处理客户端路由。 这是您需要在客户端进行身份validation检查的地方。 有几种策略用于指示需要身份validation的状态。

其中一种方法是在实际的状态定义上加上一个标签:

 $stateProvider .state('home', { url: '/', // is actually /#/ templateUrl: 'views/main.html', controller: 'MainCtrl' }) ... .state('profile', { url: '/profile', // is actually /#/profile templateUrl: 'views/profile.html', controller: 'ProfileCtrl', authRequired: true }); 

然后添加一个运行模块,在监视器上为stateChangeStart事件添加监听:

 app.run(function($rootScope, $state, Auth) { $rootScope.$on('$stateChangeStart', function(event, nextState, params) { if (nextState.authRequired && !Auth.isAuthenticated()) { $state.go('signin'); } }); }); 

身份validation服务需要知道用户是否经过身份validation,可能需要第一次往返服务器。 有关如何做到这一点stackoverflow吨的答案。


另一部分是$httpProvider.interceptors部分。 从您的angular度客户端,如果您向服务器请求一个需要身份validation的路由,在您的示例/profile (而不是/#/profile ,请记住只是/ ),并且您没有身份validation,您将得到一个401响应。 auth拦截器部分告诉angular客户端如何在这种情况下做出响应。

 .config(function($stateProvider, $urlRouterProvider, $httpProvider, $injector) { ... $httpProvider.interceptors.push(function($q) { return { responseError: function(response) { if (response.status === 401) { $injector.get('$state').go('signin'); } return $q.reject(response); } }; }); });