【发布时间】:2016-03-20 12:27:07
【问题描述】:
这可能只是来自对如何在 MEAN 堆栈应用程序中进行最佳身份验证的误解,或者我对 Promise 和 $http 的 .then() 方法如何工作缺乏了解,但每当我尝试对我的后端节点服务器进行身份验证时如果凭据不正确,它会调用 $http 的 .then() 方法的成功回调而不是错误回调。这是我的设置:
我正在使用 jsonwebtoken 和 express-jwt 包,AngularJS 拦截器添加令牌以请求并检查状态 401 responseErrors,设置/删除等 JWT 的 TokenService,以及处理登录的 UserService,注销等
从调试来看,发生了什么:
- 发送登录请求
- 服务器捕获请求,查找指定用户,但在数据库中找不到它们。使用 JSON 对象返回 401 错误,包括错误消息等。
- HttpInterceptor 使用
responseError方法,正确地看到它是一个状态 401,删除任何可能的现有令牌,重定向到/login屏幕和returns$q.reject(response)。 -
UserService.login()正确使用错误回调并执行return response。 -
问题 - 我的 login.js
.login()方法中的成功回调运行,而不是第二个错误回调。我感觉这与this article about promise chaining 中讨论的内容有关,但我的专业知识在这里有其局限性,我不太明白接下来应该做什么来告诉链中的下一个回调前一个回调出错了...
这是我的设置:
快递:
authRoutes.js
authRoutes.post("/login", function (req, res) {
User.findOne({username: req.body.username}, function (err, user) {
if (err) res.status(500).send(err);
if (!user) {
res.status(401).send({success: false, message: "User with the provided username was not found"})
} else if (user) {
bcrypt.compare(req.body.password, user.password, function (err, match) {
if (err) throw (err);
if (!match) res.status(401).json({success: false, message: "Incorrect password"});
else {
var token = jwt.sign(user, config.secret, {expiresIn: "24h"});
res.json({token: token, success: true, message: "Here's your token!"})
}
});
}
});
});
从调试中,当我使用错误的凭据登录时,它正确地点击了res.status(401).send(...) 行,所以这部分似乎没问题。
角度:
app.js(包括 HttpInterceptor)
var app = angular.module("TodoApp", ["ngRoute"]);
app.factory("AuthInterceptor", ["$q", "$location", "TokenService", function ($q, $location, TokenService) {
return {
request: function (config) {
var token = TokenService.getToken();
if (token) {
config.headers = config.headers || {};
config.headers.Authorization = "Bearer " + token
}
return config;
},
responseError: function (response) {
if (response.status === 401) {
TokenService.removeToken();
$location.path("/login");
}
return $q.reject(response);
}
}
}]);
app.config(function ($routeProvider, $httpProvider) {
$httpProvider.interceptors.push('AuthInterceptor');
$routeProvider
.when("/", {
templateUrl: "landing/landing-page.html"
});
});
userService.js
var app = angular.module("TodoApp");
app.service("UserService", ["$http", "TokenService", function ($http, TokenService) {
this.signup = function (user) {
return $http.post("http://localhost:8080/auth/signup", user).then(function (response) {
return response;
}, function (response) {
return response;
});
};
this.login = function (user) {
return $http.post("http://localhost:8080/auth/login", user).then(function (response) {
if (response.data.success) TokenService.setToken(response.data.token);
return response;
}, function (response) {
return response;
})
};
this.isAdmin = function (user) {
return user.admin;
};
}]);
login.js(问题似乎很明显)
var app = angular.module("TodoApp");
app.config(function ($routeProvider) {
$routeProvider
.when("/login", {
templateUrl: "auth/login.html",
controller: "LoginController"
})
});
app.controller("LoginController", ["$scope", "$http", "$location", "UserService", "TokenService", function ($scope, $http, $location, UserService, TokenService) {
$scope.login = function (user) {
UserService.login(user).then(function (response) {
$location.path("/todo");
}, function (response) {
console.log("There was a problem: " + response);
});
}
}]);
最后一部分,UserService.login(user).then(function (response) { $location.path("/todo"); 是正在运行并试图将用户重定向到待办事项列表的行,当我想要它运行 console.log("There was a problem: " + response); 行时。 .
就像我上面所说的,我感觉它与链式 Promise 以及如何在链的中途处理错误而不是通过链向下冒泡有关。不确定我是否需要像上面提到的网站那样添加.catch() 块。即使这是答案,我也不完全确定该怎么写。
如果我有更好的组织方式,我当然也愿意接受建议。我必须将这一点教给一班学生,并希望确保我在传授良好的做法。
提前感谢您的帮助!
【问题讨论】:
-
您正在正确处理
UserService中的错误,因此当您访问login.js页面时,它会将 UserService 的任何失败视为正确处理的承诺。如果您删除$http请求中的错误处理部分,它将按预期工作 -
@tykowale 这就像一个魅力。非常感谢!我还尝试添加
$q.reject(response),效果也不错,现在我对 $q 的理解更好了。
标签: javascript angularjs authentication jwt angular-http-interceptors