Node.js、Vue.js 和 Passport.js。 .isAuthenticated() 总是返回 false? Axios 标头可能吗?

Posted

技术标签:

【中文标题】Node.js、Vue.js 和 Passport.js。 .isAuthenticated() 总是返回 false? Axios 标头可能吗?【英文标题】:Node.js, Vue.js and Passport.js. .isAuthenticated() always returns false? Axios headers possibly? 【发布时间】:2019-01-05 02:34:09 【问题描述】:

我正在将一个项目转移到 Vue.js,但我无法使用任何中间件来检查用户是否已登录或检查用户对工作的所有权。在无休止地搜索之后,我认为问题在于我从客户端发送到服务器的标头不包含护照序列化用户之类的东西?我怎样才能做到这一点?

这是我在后端的登录路径:

      router.post("/login", function (req, res, next) 
    if (!req.body.username || !req.body.password) 
      res.send("Error");
     else if(req.body.username.length > 40 || req.body.password.length > 40)
      res.send("Error");
     else if (req.body.username) 
      req.body.username = req.body.username.toLowerCase();
      next();
    
  , passport.authenticate('local', 
    failureRedirect: '/login'
  ), function(req, res)
        User.findById(req.user.id, function(err, user)
          if(err)
            res.send("User not found");
           else 
            res.send(user.toJSON());
          
        )
  );

这是我在客户端的登录页面:

          async login () 
          const response = await AuthenticationService.login(
                username: this.username,
                password: this.password,
            )
            if(response.data == "Error")
                this.$router.push(
                    name: 'login'
                )
             else 
            this.$store.dispatch('setUser', response.data._id);
            this.$router.push(
                name: 'home'
            )
            
        

这是 AuthenticationService.login 引用的 axios 调用:

    login(credentials)
    return Api().post('login', credentials);
,

Api 来自:

import axios from 'axios';

 export default function()
   return axios.create(
      baseURL: `http://localhost:8081/`
   );
  

那么在用户通过身份验证后,如何让前端向后端发送正确的标头?如您所见,我将用户 ID 存储在 vuex 状态中,但我认为使用它来确认所有权以及用户是否已登录并不安全,对吧?还是会?我可以很容易地在请求中发送它,对吗?我觉得这还不够安全,但我在说什么。

编辑:这是 app.js 中的护照设置

app.use(bodyParser.urlencoded( extended: true ));
app.use(bodyParser.json());
app.use(cors());
app.use(flash());
app.use(cookieParser());

app.use(express.session( //5a6ba876578447262893ac69
    secret: "sessionSecret",
    resave: false,
    saveUninitialized: false
  ));
app.locals.moment = require('moment');
app.use(passport.initialize());
app.use(passport.session());
passport.use(new LocalStrategy(User.authenticate()));
passport.serializeUser(User.serializeUser());
passport.deserializeUser(User.deserializeUser());

【问题讨论】:

对于在护照/快递中工作的会话,您需要在 passport 实例上定义 [de]serializeUser。您能显示所有您正在使用的 express/passport 中间件吗? 至于在 vuex 状态下存储用户 ID,只要您将其用于 UI 目的(而不是权威),那是完全可以的。您应该将用户会话令牌存储在 HttpOnly cookie 中,并使用它们在服务器端对用户进行身份验证/授权。 感谢您的编辑。当您尝试访问POST /login 时,服务器端会发生什么? 谢谢你,丹。我在上面的编辑中包含了护照和快递中间件,但是我认为我的问题完全基于您的第二条评论。我如何获得令牌?我该如何保存?以及如何在其他请求中使用它? 当我尝试访问 POST/login 时,它完全可以正常工作 【参考方案1】:

requests.js

let axiosConfig = 
  withCredentials: true,
  headers: 
    'Content-Type': 'application/json',
    'Access-Control-Allow-Origin': 'http://localhost:3000/',
    'Access-Control-Allow-Methods': 'GET,PUT,POST,DELETE'
  

server.js

var express  = require('express');
var app      = express();
var cors = require('cors');
app.use(cors(credentials: true, origin: 'http://localhost:8080'))

app.use(cors(credentials: true, origin: 'http://localhost:8080'))

【讨论】:

谢谢!我错过了服务器中的credentials: true【参考方案2】:

您的问题是因为您的前端和后端位于不同的域上。

passport.session()/express.session() 用于维护用户会话的 Cookie 的范围仅限于特定域。

当您在受保护的资源上调用axios.get() 时,axios 不会发送或接收cookie,因为localhost:8080localhost:8081 是不同的域。

试试axios.get('/path/to/your/resource', withCredentials: true )axios.post('/login', username, password , withCredentials: true )

只要您使用 AJAX 进行这些调用,即使没有 Vue,它也会存在。

【讨论】:

我想大概就是这样,谢谢你,Dan!但是现在我遇到了一个 cors 错误,你知道如何解决它吗? 无法加载localhost:8081/login:对预检请求的响应未通过访问控制检查:响应中“Access-Control-Allow-Origin”标头的值不能是通配符“ *' 当请求的凭证模式是 'include' 时。因此,Origin 'localhost:8080' 不允许访问。 XMLHttpRequest 发起的请求的凭证模式由 withCredentials 属性控制。 您需要设置 CORS 标头。 github.com/expressjs/cors。您现在应该将他们发送至localhost:8080 我在后端的 app.js 中已经有了 app.use(cors())。我是否也需要在前端的某个地方添加它?如果有,具体在哪里? 不,这是后端的事情。正如您的错误消息所述,您需要启用飞行前请求,这已记录在 here

以上是关于Node.js、Vue.js 和 Passport.js。 .isAuthenticated() 总是返回 false? Axios 标头可能吗?的主要内容,如果未能解决你的问题,请参考以下文章

Node.js 和 Passport 对象没有方法 validPassword

Node.js 和 Vue.js,为啥 Refresh 让 vue.js 的 store 清晰?我如何在 vue.js 中使用上传的图片?

如何创建vue.js项目和node.js项目?

在 Node.js 和 Vue.js 之间共享 TypeScript 代码

用户帐户激活、电子邮件确认和使用 Passport / Node.Js 的邀请

使用 passport.js 和 express.js (node.js) 制作安全的 oauth API