这可能只是因为误解了如何在MEAN堆栈应用程序中进行最佳身份验证,或者我对promises和$ http .then()
方法的工作方式缺乏了解,但每当我尝试使用不正确的凭据对我的后端节点服务器进行身份验证时,它就是调用$ http .then()
方法的成功回调而不是错误回调.这是我的设置:
我正在使用jsonwebtoken
和express-jwt
包,AngularJS拦截器添加请求的令牌并检查状态401 responseErrors,设置/删除的TokenService等JWT,以及用于处理登录,注销等的UserService.
从调试开始,这是正在发生的事情:
发出登录请求
服务器捕获请求,查找指定的用户,但无法在数据库中找到它们.使用JSON对象返回401错误,包括错误消息等.
HttpInterceptor使用该responseError
方法,正确地看到它是状态401,删除任何可能的现有令牌,重定向到/login
屏幕和return
s $q.reject(response)
.
UserService.login()
正确使用错误回调并执行return response
.
问题 - 我的login.js .login()
方法中的成功回调运行,而不是第二个错误回调.我有一种感觉这与本文中讨论的关于承诺链的内容有关,但我的专业知识在这里有其限制,我无法理解我接下来应该做什么来告诉链中的下一个回调前一个有错误...
这是我的设置:
表达: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(...)
行,所以这部分似乎没问题.
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" }); });
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; }; }]);
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");
是正在运行并尝试将用户重定向到Todo项目列表的行,当我希望它运行该console.log("There was a problem: " + response);
行时...
就像我上面所说的那样,我有一种感觉,它与链接承诺有关,以及如何在链中途处理错误,而不是通过链条冒泡.不确定我是否需要.catch()
像我上面提到的网站那样添加一个块.即使这是答案,我也不完全确定如何写.
如果有更好的方法我应该组织这个,我也绝对愿意接受建议.我必须向一班学生传授这一点,并希望确保我教授良好的实践.
在此先感谢您的帮助!
仔细看看这部分代码:
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; }) }
在这里,您提供了一个带有返回值的错误回调,该返回值将传递给promise链中的下一个回调.您混淆的原因是,如果您希望错误进一步传播,您仍然需要从回调中返回被拒绝的throw的promise .否则它是否有效意味着您从错误情况中恢复,并且流程中的下一步将成功.这就是你现在拥有的.
在您的情况下,您要么完全删除错误回调
return $http.post("http://localhost:8080/auth/login", user).then(function (response) { if (response.data.success) TokenService.setToken(response.data.token); return response; });
......或确保你失败的承诺
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 $q.reject(response); });
...或扔:
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) { throw new Error(response); });