【问题标题】:Node.js, Vue.js and Passport.js. .isAuthenticated() always returns false? Axios headers possibly?Node.js、Vue.js 和 Passport.js。 .isAuthenticated() 总是返回 false? Axios 标头可能吗?
【发布时间】: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 时,它完全可以正常工作

标签: javascript node.js authentication vue.js passport.js


【解决方案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
猜你喜欢
  • 2021-01-28
  • 2021-01-24
  • 1970-01-01
  • 2014-04-28
  • 2021-01-27
  • 1970-01-01
  • 1970-01-01
  • 2020-05-03
  • 2018-12-07
相关资源
最近更新 更多