nodejs 和 Angular 应用程序使用 JWT 发送 401 Unauthorized 和 200 OK
Posted
技术标签:
【中文标题】nodejs 和 Angular 应用程序使用 JWT 发送 401 Unauthorized 和 200 OK【英文标题】:nodejs and angular app sending 401 Unauthorized and 200 OK with JWT 【发布时间】:2018-02-12 16:35:53 【问题描述】:当我在我的表单上单击注册时,据我所知,角度是在节点服务器可以授权 JWT 并发送 200 OK 之前将 url 设置为 /profile(受保护的路由)。我不确定如何防止这种情况。
即使我在本地存储中有令牌,受保护的路由也会返回和未经授权的错误。所以即使发送了 200 OK 响应,如果我重新加载 /profile 路由,它仍然会得到 401。
路线:
const path = require('path');
const Company = require('./models/app');
const User = require('./models/users');
const jwt = require('express-jwt');
let auth = jwt(
secret: process.env.CONFIG_SR,
requestProperty: 'payload'
);
module.exports = function(app , passport)
function profileCheck(req , res , next)
if(!req.payload._id)
res.status(401).json(
"message" : "UnauthorizedError: private profile"
);
else
User.findById(req.payload._id)
.exec(function(err, user)
res.status(200).json(user);
);
app.get('/' , function(req , res)
res.sendFile(path.join(__dirname , '../public' , 'index.html'));
);
app.get('/login' , function(req , res)
res.sendFile(path.join(__dirname , '../public' , 'login.html'));
);
app.post('/api/login' , function(req, res)
passport.authenticate('local' , function(err, user, info)
if(err)
return res.json(
'message': err
);
if(user)
token = user.generateJwt();
res.status(200);
res.json(
"token" : token
);
else
return res.json(
'message': 'User not found'
);
)(req, res);
);
app.get('/register' , function(req , res)
res.sendFile(path.join(__dirname , '../public' , 'register.html'));
);
app.post('/api/register' , function(req, res)
User.findOne('local.email': req.body.email, function(err, user)
if(err)
return res.json(
'message': err
);
if(user)
return res.json(
'message': 'User already exists'
);
else
let newUser = new User();
newUser.local.email = req.body.email;
newUser.local.name = req.body.name;
newUser.local.password = newUser.setPassword(req.body.password);
newUser.save(function(err)
// passport.authenticate('local', session: false , function(req, res) );
var token;
token = newUser.generateJwt();
res.status(200);
res.json(
'token': token
);
);
);
);
app.get('/profile', auth, profileCheck, function(req , res)
res.render('profile.jade');
);
app.get('/logout' , function(req , res)
req.logout();
res.json(
'message': 'Bye'
);
);
控制器
app.controller('authController', ['$scope', '$http', '$window', 'authenticationService', 'restrictData', function($scope, $http, $window, authenticationService, restrictData)
$scope.credentials =
name : "",
email : "",
password : ""
$scope.user = ;
$scope.regSubmit = function()
authenticationService.register($scope.credentials)
.error(function(err)
console.log(err);
).then(function()
restrictData.getProfile()
.success(function(data)
$scope.user = data;
).error(function(e)
console.log(e);
);
var url = '/profile';
$window.location.href = url;
);
$scope.logSubmit = function()
authenticationService.login($scope.credentials)
.error(function(err)
console.log(err);
).then(function()
var url = '/profile';
$window.location.href = url;
);
$scope.isLoggedIn = authenticationService.isLoggedIn();
$scope.currentUser = authenticationService.currentUser();
]);
服务1:
app.factory('authenticationService',['$http', '$window', '$timeout', '$q' , function($http, $window, $timeout, $q)
var saveToken = function(token)
$window.localStorage['mean-token'] = token;
var getToken = function()
return $window.localStorage['mean-token'];
var logout = function()
$window.localStorage.removeItem('mean-token');
var isLoggedIn = function()
var token = getToken();
var payload;
if(token)
payload = token.split('.')[1];
payload = $window.atob(payload);
payload = JSON.parse(payload);
return payload.exp > Date.now() / 1000;
else
return false;
var currentUser = function()
if(isLoggedIn())
var token = getToken();
var payload = token.split('.')[1];
payload = $window.atob(payload);
payload = JSON.parse(payload);
return
email : payload.email,
name : payload.name
;
register = function(user)
return $http.post('/api/register', user).success(function(data)
saveToken(data.token);
);
;
login = function(user)
return $http.post('/api/login', user).success(function(data)
saveToken(data.token);
);
;
return
saveToken: saveToken,
getToken: getToken,
isLoggedIn: isLoggedIn,
currentUser: currentUser,
register: register,
login: login,
logout: logout
;
]);
服务 2:
app.factory('restrictData', function($http, authenticationService)
var getProfile = function()
return $http.get('/profile',
headers:
Authorization: 'Bearer ' + authenticationService.getToken()
);
return
getProfile: getProfile
);
【问题讨论】:
restrictData.getProfile() .success(function(data) $scope.user = data; ).error(function(e) console.log(e); ); var url = '/个人资料'; $window.location.href = 网址;为什么要触发 /profile 两次? @karthick 这是一个很好的观点。但是,当我删除 window.location 调用时,我应该如何将用户重定向到 /profile?返回 200 OK 但我留在 /register 页面。 profile.jade 未呈现,用户未重定向。 profile.jade 在 /profile 中渲染? @karthick 在响应中 app.get('/profile', auth, profileCheck, function(req , res) res.render('profile.jade'); );跨度> 【参考方案1】:因此,根据我在研究中的发现,使用 JWT 保护非 api 路由是不明智的或不可行的。因此,为了让我的应用程序正常工作,我将前端页面的所有路由都转移到了有角度的一侧。它并不是特别想要,但它最终解决了这个问题。
我删除了所有导致前端页面的获取请求,如下所示:
app.get('/' , function(req , res)
res.sendFile(path.join(__dirname , '../public' , 'index.html'));
);
然后我使用 routeProvider(确保在您的页面上包含 angular-route 以便此工作)来路由所有路径:
app.config(function($routeProvider , $locationProvider)
$routeProvider
.when('/',
templateUrl: './ui/home.html',
).when('/compare',
templateUrl: './ui/compare.html',
).when('/contact',
templateUrl: './ui/contact.html',
).when('/login',
templateUrl: './ui/login.html',
).when('/register',
templateUrl: './ui/register.html',
).when('/profile',
templateUrl: './ui/profile.html',
);
$locationProvider.html5Mode(true);
);
app.run(function($rootScope, $location, authenticationService)
$rootScope.$on('$routeChangeStart', function(event, nextRoute, currentRoute)
if ($location.path() === '/profile' && !authenticationService.isLoggedIn())
$location.path('/');
);
);
然后相应地调整其余代码
【讨论】:
以上是关于nodejs 和 Angular 应用程序使用 JWT 发送 401 Unauthorized 和 200 OK的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 Mongoose、Express、Angular 4 和 NodeJS 上传/保存和显示图片
从 mongoDB 获取数据并使用 Angular 和 NodeJs 在屏幕上打印
nodejs 和 Angular 应用程序使用 JWT 发送 401 Unauthorized 和 200 OK
使用 nodejs/express 登录后将用户重定向到 Angular 应用程序