如果不应该,身份验证返回"401(未授权)"

Zac*_*ook 6 authentication node.js angularjs sails.js passport-local

我第一次设置了身份验证功能,并且在用户登录后得到了一些意想不到的结果.一位同事给了我一个带有工作身份验证的应用程序来模拟我的应用程序,看起来我所做的一切都是正确的.

我在前端使用AngularJS,SailsJS后端框架和PassportJS身份验证中间件.

我的源代码(现在)公开存储...后端API在Github上(API Github),前端代码在这里找到(前端Github)

基本上发生的是用户

  1. 点击登录按钮,触发此功能

    login: function (credentials) {
        return baseAuth.customPOST(credentials, 'login').then(function (user) {
            $log.debug('User logged in: ', user);
            isAuthenticated = true;
            return user;
        });
    },
    
    Run Code Online (Sandbox Code Playgroud)
  2. 该customPOST的控制器逻辑就是这个

    login: function (req, res, next) {
       passport.authenticate('local', function (err, user, info) {
           if (err) { return res.json(err); }
           else if (user) {
               req.logIn(user, function (err) {
                   if (err) { return res.json(err); }
                   return res.json(user);
               });
           } else { return res.json(400, info); }
    
       })(req, res);
    
    },
    
    Run Code Online (Sandbox Code Playgroud)
  3. 在那一步,护照应该做它的事情并登录用户

    passport.use(new LocalStrategy({ usernameField: 'email', passwordField: 'password' },
    function(email, password, next) {
       User.findOne({ email: email })
           .exec(function (err, user) {
               if (err) { return next(err); }
               if (user) {
                    if (user.activated) {
                    bcrypt.compare(password, user.password, function (err, valid) {
                        if (err) { next(err); }
                        if (valid) {
                            return next(null, user, { message: 'Logged In' });
                        } else { return next(null, false, { message: 'Incorrect password'}); }
                    });
                } else { next(null, false, { message: 'User is not activated. Please contact admins.'}); }
            } else { next(null, false, { message: 'Could not find user with email ' + email }); }
        });
       }
     ));
    
    Run Code Online (Sandbox Code Playgroud)

在控制台中,我总是认为这是成功的.

控制台读取:

User logged in:  Object {firstName: "John", lastName: "Doe", email: "john_doe@work.com", activated: true, isUser: true…}
Run Code Online (Sandbox Code Playgroud)
  1. 然后,我对发生的事情的理解变得有些模糊.我知道应用程序然后尝试查看用户是否经过身份验证.IsAuthenticated被触发,在AngularJS中看起来像这样:

    isAuthenticated: function (force) {
        var deferred = $q.defer();
    
        if (isAuthenticated && currentUser) {
            deferred.resolve(currentUser);
        } else {
            return baseAuth.customGET('authenticated').then(function (user) {
                deferred.resolve(currentUser);
                isAuthenticated = true;
                currentUser = user;
                return user;
            });
        }
    
        return deferred.promise;
    }
    
    Run Code Online (Sandbox Code Playgroud)
  2. 它在后端UserController中执行此操作

    isAuthenticated: function (req, res) {
       if (req.isAuthenticated() && req.user.isUser) { return res.json(req.user); }
       else { return res.send(401); }
    },
    
    Run Code Online (Sandbox Code Playgroud)

然后它失败了:( GET http://localhost:1337/user/authenticated 401 (Unauthorized) 无论是req.isAuthenticated还是req.user.isUser都没有通过.我把它们分开来进行单独测试,它们都不是真的."isUser"是一个我默认为true的值,所以它应该是真的db.req.isAuthenticated中的每个用户也都失败了,我并不完全理解.

有人对我的问题有所了解吗?我在这里做错了什么?

Ale*_*N-o 3

如果您的前端应用程序与后端应用程序具有不同的来源,则 AJAX 请求将不包含会话 cookie,并且req.isAuthenticated()永远不会返回 true。

使用 withCredentials 选项强制执行。

$http({ withCredentials: true, ... })
Run Code Online (Sandbox Code Playgroud)

看起来 Restangular 使用相同的选项:

https://github.com/mgonto/restangular#setdefaulthttpfields

https://docs.angularjs.org/api/ng/service/$http#usage

编辑:您还应该检查idbehold 指出的服务器端配置


正如 Matan 所建议的,您确实应该尝试一下服务器端的 sails-generate-auth 生成器。

https://github.com/sails101/even-more-passport

https://github.com/kasperisager/sails-generate-auth

  • 他还需要将服务器端的“Access-Control”标头配置为“Allow-Credentials”,并确保“Allow-Origin”标头设置为实际请求的“Origin”标头,而不仅仅是“*”。 (2认同)