[英]passportjs req.isAuthenticated() returns False because passport.deserializeUser() never runs in certain browsers
部分地,這個錯誤似乎很常見,因為 req.Authenticated() 是錯誤的,但從我讀過的內容來看,根據過去的帖子,它似乎影響了所有瀏覽器,因為他們沒有提到任何關於瀏覽器特定問題的內容。 所以我有一個heroku
托管的 Web 應用程序,前端和后端彼此分開。
在本地,無論瀏覽器如何,問題都不存在,但是當進入生產環境時,Chrome 會影響任何基於鉻的瀏覽器,但似乎不受影響的是 FireFox、PostMan(雖然不是瀏覽器但不受影響)、Electron APP(雖然我相信是基於鉻的,但我不知道),當我進入登錄路線時,后端只是跳過了受影響瀏覽器的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",
這是代碼
服務器.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, () => {
});
護照.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));
});
密碼實用程序.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,
};
frontend.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);
}
}
....
我已經嘗試在此處對解決方案進行了很好的總結中找到了常見的解決方案,但我仍然遇到問題。 有些人建議添加延遲只是不知道延遲去哪里了,或者我把它放在哪里是個好地方,任何幫助將不勝感激
我試過:-創建延遲(不知道位置是否正確)-確保會話和初始化的順序正確-cors 的憑據設置為true-前端的憑據-使用更隱式的方式登錄-in 會話聲明將安全設置為真
似乎是瀏覽器與后端交互的方式不知道去哪里或嘗試什么問題似乎至少從 2016 年開始就存在
在意識到由於 Heroku 服務器 SSL 請求是 req.connection.encrypted 總是未定義根據此PassportJS 回調在 http 和 https 之間切換后,只需添加一行如下
app.set('trust proxy', 1);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.