javascript - 身份验证 - 调用 $http 的 .then() 成功回调而不是错误回调

标签 javascript angularjs authentication jwt angular-http-interceptors

这可能只是因为误解了如何在 MEAN 堆栈应用程序中最好地进行身份验证,或者我对 promises 和 $http 的 .then() 方法如何工作缺乏了解,但每当我尝试使用不正确的凭据向我的后端节点服务器进行身份验证,它正在调用 $http 的 .then() 方法的成功回调而不是错误回调。这是我的设置:

我正在使用 jsonwebtokenexpress-jwt 包,AngularJS 拦截器将 token 添加到请求并检查状态 401 responseErrors,一个 TokenService 设置/删除等 JWT 和一个 UserService 来处理登录、注销等。

从调试来看,这是正在发生的事情:

  1. 发送登录请求
  2. 服务器捕获请求,查找指定用户,但无法在数据库中找到他们。返回 401 错误,JSON 对象包括错误消息等。
  3. HttpInterceptor 使用 responseError 方法,正确地看到它是状态 401,删除任何可能的现有 token ,重定向到 /login 屏幕,然后返回s $q.reject(response).
  4. UserService.login() 正确使用错误回调并执行返回响应
  5. 问题 - 我的 login.js .login() 方法中的成功回调运行,而不是第二个错误回调。我感觉这与 this article about promise chaining 中讨论的内容有关,但我的专业知识在这里有其局限性,我不太明白接下来我应该做什么来告诉链中的下一个回调,前一个回调有错误......

这是我的设置:

express :

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(...) 行,所以这部分似乎没问题。

Angular :

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

用户服务.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"); 是正在运行并试图重定向用户到 Todo 项目列表,当我希望它运行 console.log("There was a problem: "+ response); 行而不是...

就像我上面说的,我觉得它与链接 promise 以及如何在链中途处理错误而不是通过链向下冒泡有关。不确定我是否需要像我上面提到的网站所说的那样添加 .catch() block 。即使这是答案,我也不确定如何写。

如果我有更好的组织方式,我也绝对乐于接受建议。我必须将这个教给一类学生,并希望确保我教的是好的做法。

在此先感谢您的帮助!

最佳答案

仔细看看这部分代码:

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

...或者确保你返回失败的 promise

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

关于javascript - 身份验证 - 调用 $http 的 .then() 成功回调而不是错误回调,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34276945/

相关文章:

javascript - Jquery下拉菜单鼠标输入延迟

javascript - 禁用 Vanilla-tilt.js 的鼠标移动但保持陀螺仪效果

tomcat - 登录后如何刷新JSESSIONID cookie

php - 我正在使用使用 session 的登录脚本(PHP、MySQL)。我需要创建一个变量,以便我可以在其他页面中使用它?

java - 如何实现Grpc用户名/密码认证。 Python 客户端、Java 服务器

javascript - mongodb在事件评论中将用户添加到喜欢的数组

javascript - JQuery 滚动动画不粘在 DIV 内

javascript - Angular - 从 Controller 切换状态

javascript - 未评估的 ng 类

javascript - 来自静态文件的 Angular 用户 JSON 请求