我想用Passport.js和Github策略实现登录。这是我使用的代码:
...
/* Ensure Auth function */
function ensureAuthenticated(req, res, next){
if (req.isAuthenticated()) return next()
else res.redirect('/');
}
/* Some modules */
global.passport = require('passport');
global.GithubStrategy = require('passport-github2').Strategy;
global.util = require('util');
global.session = require('express-session');
global.bodyParser = require('body-parser');
global.methodOverride = require('method-override');
global.partials = require('express-partials');
global.request = require('request');
/* Passport */
passport.serializeUser(function(user, done){
done(null, user);
});
passport.deserializeUser(function(obj, done){
done(null, obj);
});
passport.use(new GithubStrategy({
clientID: config.githubID,
clientSecret: config.githubSecret,
callbackURL: config.githubURL
},
function(accessToken, refreshToken, profile, done){
process.nextTick(function(){
return done(null, profile);
});
}
));
app.use(partials());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
app.use(methodOverride());
app.use(session({secret: 'keyboard cat', resave: false, saveUninitialized: false}));
app.use(passport.initialize());
app.use(passport.session());
/* Controllers */
app.get('/auth/github', passport.authenticate('github', {scope: ['user:email']}), function(req, res){});
app.get('/auth/github/callback', passport.authenticate('github', { failureRedirect: '/' }), function(req, res){
res.redirect('/dashboard');
});
app.get('/logout', function(req, res){
req.logout();
res.redirect('/');
});
我在 Passport.js 文档中搜索了很多,但我找不到这个问题的答案:
- 为什么,就我而言,会话不保存身份验证?例如,如果我在路由上设置了 ensureAuthenticated 中间件,它总是将我重定向到/,其中是登录表单。
- 为什么我无法从req.user访问用户信息以查看用户信息?
- 为什么注销路由不起作用?
前言/序言
我在当地战略方面遇到了同样的问题。我没有太多关于您系统架构的信息,但是我的系统使用了以下内容:
- PassportJS(带本地策略)
- ExpressJS 处理会话和路由(带 Redis MemoryStore)
- 节点JS服务器
- AngularJS 2 前端
要结帐的内容
- CORS在这个问题上发挥了重要作用。
我使用 cors 库来缓解我在那里遇到的问题。特别是,我对配置进行了以下更改:
let cors_config = {
origin: "http://localhost:8080",
credentials: true
};
这会将您的 CORS 设置配置为在印前检查请求中包含访问控制允许凭据:true 标头。
- 确保内存存储和会话配置正确
从没有指定的内存存储(默认为 LocalStore)开始,然后从那里开始工作。我看到你现在没有使用一个,所以无论如何都要继续阅读。
server.use(session({
secret: "secret_c0de",
resave: false,
saveUninitialized: false//,
//store: new redis_store(redis_settings)
}));
检查在进行身份验证时,是否在身份验证后返回会话 Cookie。它应该包含一个键值,其键是"connect.sid",即您的会话 ID。
如果您没有获得会话 Cookie,那么您知道您的会话可能未正确配置,在这种情况下,您应该:
- 检查"使用"调用的加载顺序
- 尝试识别会话处理代码的任何错误或问题
如果您正在接收 cookie,但 isAuthenticated() 检查在后续请求中失败,这通常暗示您的 MemoryStore 无法正常工作。
- 如果您最初使用的是 LocalStore,则不需要太多配置,因此再次提示会话配置存在问题
- 如果您使用的是像 Redis 这样的商店,请尝试收听 Redis 事件(主要是"连接"和"错误"),并将输出记录到控制台,以便查看它是否正常工作。
我在你的代码中注意到的事情
- 检查序列化函数,您正在序列化整个用户对象。
这更像是一种优化,但注意到人们在序列化用户的 ID 和反序列化它方面取得了更大的成功。
passport.serializeUser(function(user, done){
done(null, user.id);
});
passport.deserializeUser(function(obj, done){
User.findById(obj, function(err, user){
if(err){/*code to handle error with not finding user*/}
done(null, user);
});
});
- 您应该需要 cookie 解析器,因为会话使用会话 cookie。
回答您的问题
- 为什么,就我而言,会话不保存身份验证?
应用程序中的会话创建已中断,因此您应该尝试对其进行调试。如上所述,您应该检查会话 ID 是否在身份验证请求后在会话 cookie 中返回,然后从那里继续。
- 为什么我无法从 req.user 访问用户信息以查看用户信息?
用户在从Passport 成功反序列化尝试后注入。在您的情况下,会话永远不会首先创建,永远不会序列化到您的 MemoryStore 中,因此永远无法反序列化(因为它不存在)。
- 为什么注销路由不起作用?
req.logout() 仅适用于正在创建的成功会话。 从您提供的其他代码和信息来看,我认为这就是您所指的。
希望您在这里找到一些有价值的信息,如果您想聊一些特别的事情,请随时发表评论! :)
理解和暗示基于护照的身份验证代码的最佳来源是这里。 检查一次 https://www.coursera.org/learn/server-side-development/lecture/Clovu/passport