部分这个错误似乎是常见的req.Authenticated()是假的,但从我所读到的,它似乎影响所有的浏览器根据过去的帖子,因为他们没有提到任何关于浏览器特定的问题。所以我有一个heroku
托管的web应用程序,前端和后端是彼此分开的。
本地问题不存在,无论浏览器,但当移动到生产然后影响Chrome任何基于铬的浏览器,但似乎不受影响的是FireFox,邮差(虽然不是浏览器,但不受影响),电子应用程序(虽然我相信是基于铬,但我不知道),当我去登录路由后端只是跳过passport.deserializeUser()
受影响的浏览器,因此req.isAuthenticated()返回false。
我已经尝试了所有常见的解决方案,但似乎没有解决问题
依赖项的版本
"axios": "^0.21.4",
"bcrypt": "^5.0.1",
"compression": "^1.7.4",
"connect-redis": "^5.2.0",
"cookie-parser": "^1.4.5",
"cors": "^2.8.5",
"express": "^4.17.1",
"express-session": "^1.17.2",
"knex": "^0.21.21",
"passport": "^0.5.0",
"passport-local": "^1.0.0",
"pg": "^8.7.1",
"redis": "^3.1.2",
代码
server.js:
const passport = require("passport");
const LocalStrategy = require("passport-local");
const session = require("express-session");
require("dotenv").config();
const express = require("express");
const cors = require("cors");
const compression = require("compression");
const isAuth =require("./location/login_Verification").isAuth;
const whitelist =
process.env.NODE_ENV === "development"
? ["http://localhost:3001"]
: [
"https://www.frontend.com",
"https://www.backend.com/",
];
const corsOption = {
origin: function (origin, callback) {
if (whitelist.indexOf(origin) !== -1) {
callback(null, true);
} else {
callback(new Error("Not allowed by CORS"));
}
},
credentials: true,
};
const app = express();
app.use(compression());
app.use(cookieParser());
app.use(express.json());
app.use(
express.urlencoded({
extended: true,
})
);
app.use(
cors(corsOption)
);
app.use(
session({
secret: process.env.SESSION_SECRET,
resave: false,
saveUninitialized: true,
store: new RedisStore({ client: redisClient }),
cookie: {
maxAge: 1000 * 60 * 60 * 24,
secure: false,//tried to add true does not work
},
})
);
require("./location/config/passport");
app.use(passport.initialize());
app.use(passport.session());
app.post(
"/login",
passport.authenticate("local", {
//session: true, tried this as well but nothing
successRedirect: "/login-success",
failureRedirect: "/login-fail",
})
);
/*It was suggested to use req.logIn to be more implicit but does not work
app.post("/login", function (req, res, next) {
passport.authenticate("local", function (err, user, info) {
if (info) {
console.log(info);
res.json({ success: "fail info" });
}
if (err) {
console.log(err);
return err;
}
if (!user) {
console.log(user);
res.json({ success: "fail user" });
}
req.logIn(user, function (err) {
if (err) {
return next(err);
}
req.session.save(function () {
console.log(req.session.passport);
res.redirect("/login-success");
});
});
})(req, res, next);
});*/
app.get("/login-success",/*delayhere*/ isAuth, (req, res) => {
const { hassignedup, reviewing_info } = req.user;
res.json({
success: true,
hassignedup: hassignedup,
reviewing_info: reviewing_info,
})
});
app.get("/login-fail", (req, res) => {
res.json({ success: false });
});
app.listen(process.env.PORT, () => {
});
passport.js:
const ValidPassword =
require("../location/passwordUtils").ValidPassword;
const passport = require("passport");
const LocalStrategy = require("passport-local").Strategy;
var knex= require("knex")(
process.env.NODE_ENV === "development"
? {
client: "pg",
connection: {
host: process.env.DB_HOST,
user: process.env.DB_USER,
password: process.env.DB_PASS,
database: process.env.DB_NAME,
},
}
: {
client: "pg",
connection: {
connectionString: process.env.DATABASE_URL_LOCAL,
ssl: {
rejectUnauthorized: true,
ca: fs.readFileSync("./config/file.pem").toString(),
},
},
}
);
const customFields = {
usernameField: "un",
passwordField: "pw",
};
const verifyCallback = (username, password, done) => {
knex
.select("*")
.from("users")
.where("username", username)
.then((user) => {
if (user[0] === undefined) {
return done(null, false);
} else {
return ValidPassword(password, user[0].pw).then((result) => {
if (result) {
let usercurrent = {
usercurrent: {
user_id: user[0].user_id,
hassignedup: user[0].hassignedup,
},
};
return done(null, usercurrent);
} else {
return done(null, false);
}
});
}
})
.catch((err) => {
done(err);
});
};
const strategy = new LocalStrategy(customFields, verifyCallback);
passport.use(strategy);
passport.serializeUser((user, done) => {
done(null, user);
});
passport.deserializeUser((user, done) => {
//console.log("deserial", user.usercurrent);
knex
.select("userid")
.from("users")
.where("userid", user.usercurrent.user_id)
.then((userobtained) => {
done(null, user.usercurrent);
})
.catch((err) => done(err));
});
passwordUtils.js
const bcrypt = require("bcrypt");
function genPassword(password) {
return bcrypt.hash(password, x).then((result) => {
return { hash: result };
});
}
function ValidPassword(password, hash) {
return bcrypt.compare(password, hash).then((result) => {
return result;
});
}
module.exports.ValidPassword = ValidPassword;
module.exports.genPassword = genPassword;
login_Verification.js
const isAuth = (req, res, next) => {
if (req.isAuthenticated()) {
return next();
} else {
return res.status(401).json("not in");
}
};
module.exports = {
isAuth,
};
front .js ReactJS前端
....
onLogin=()=>{
axios({
method: "post",
url:
process.env.NODE_ENV === "development"
? "http://localhost:3000/login"
: "https://backend.com/login",
headers: {
"Access-Control-Allow-Origin":
process.env.NODE_ENV === "development"
? "http://localhost:3000"
: "https://frontend.com",
"Content-Type": "application/json",
},
data: {
un: this.state.username,
pw: this.state.pwd,
},
withCredentials: true,
}).then((result) => {
console.log("log in", result.data);
}
}
....
我已经试着做了共同的解决方案,在这里找到了一个很好的解决方案总结,但我仍然有问题。有些人建议添加延迟,只是不知道延迟去哪里,或者如果我把它放在一个好地方,任何帮助将不胜感激
我试过了:-创建延迟(不知道是否正确的地方)-确保session和initialize的顺序正确-cors将凭据设置为true-前端有凭证-使用更隐式的方式登录在会话声明中将secure设置为true
似乎是浏览器与后端交互的方式不确定去哪里或尝试什么问题似乎至少自2016年以来就存在
意识到由于heroku服务器SSL请求是req.connection.encrypted总是未定义的,根据此PassportJS在http和https之间的回调切换,只需添加一行如下
app.set('trust proxy', 1);