使用 passport.js 和普通 SQL 查询进行身份验证
Using passport.js and plain SQL query to authenticate
我正在做一个项目,遇到以下问题。
我想使用 Passport API 实现用户登录逻辑,但我很难理解它是如何工作的,尤其是我想要实现它的方式(使用普通 SQL 查询)。我已经浏览了几个解释如何做到这一点的教程,但问题是在它们中它只用 ORM 显示,我不希望那样。到目前为止,我已经写了几千行代码,但没有成功,当然在这之后被删除了,这就是我没有在下面提供任何代码的原因。
我正在使用 MySQL 和 Express 作为构建网站的框架。如果您对事情如何发生有任何简短或高级的想法,我将很高兴收到您的来信。
提前致谢!
护照有时会很混乱,我把它给你!根据您的问题,我假设您想使用 "local" 登录策略,而不提供 Google 或 GitHub 单点登录之类的东西。我还假设您想使用 "Sessions"(cookie)而不是像 JWT 这样的东西。
为此,您需要先使用 Express 应用程序预先配置护照。这需要您初始化护照和会话存储(如果您愿意,可以使用 MySQL 或 Redis 之类的东西)。
然后您需要配置 "strategy",在我们的例子中是本地策略。
我将 运行 通过一个示例和一些代码来说明如何完成此操作。我会将所有这些都放在一个代码片段中,但您可能希望将其分成几个文件。
您可以克隆的代码段:
https://gist.github.com/BlueHatbRit/5d07d3f98d41d536a776b74fcb843174
在这里镜像以获取答案寿命:
const express = require('express');
const session = require('express-session');
const bodyParser = require('body-parser');
const passport = require('passport');
const LocalStrategy = require('passport-local').Strategy;
// Create the express app
const app = express();
// Initialise express-session module effectively deals with serilaising some
// form of ID in a cookie which is secured with the given secret. In this case
// express then remembers this ID in memory. When this cookie is handed
// back to your server, express-session takes that ID and matches it up to
// the data it has stored against that ID in memory. Remember, in production
// you will most probably want to hook this up to some sort of data store,
// either Redis, MySQL, etc...
app.use(session({ secret: "cats" }));
// We need some body parser setup to use Passport with express
// you can checkout the body parser and passport docs to find out why
app.use(bodyParser.urlencoded({ extended: false }));
// Now we initialise passport
app.use(passport.initialize());
// Now setup the session strategy, this happens after the express-session
// initialisation as that must run on a request first. Once we have the data
// from express-session (remember, it converted from a session ID given to
// the user via a cookie, back into the data we stored against the ID) we can
// then pull our any additional information.
app.use(passport.session());
passport.serializeUser(function(user, done) {
// This happens at the end of a request, it recieves the
// req.user object, and you can then choose what to serialise
// into the session (returning the user a new cookie with a
// session ID).
// In most cases you'll want to store as little data as possible
// so just a user.id might be fine.
done(null, user.id);
});
passport.deserializeUser(function(id, done) {
// Assume we stored the user ID in the session in the above
// function call, we can now access it.
// You can now take "id" and pass it into your database and
// get back whatever you want in regards to the user. This may
// just be a small representation of the user, or the entire
// record.
// You can use either SQL or an ORM here. The important bit is
// that you call the "done" callback with whatever object you
// want to represent the user.
User.findById(id, function(err, user) {
// In your main request handlers, you will then call `req.user`
// and get back whatever you passed into the callback.
done(err, user);
});
});
// Now we setup the main "login" route, this will do the first round
// of authentication. It will take a username and password, will check
// those credentails and will then decide whether or not to log the user in.
passport.use(new LocalStrategy(function(username, password, done) {
// Run your SQL here to find the user by their username
// Then check their password is correct
// If something fails then call the "done" callback with a descriptive error
// otherwise call "done" with no error, and pass it the "user" object. This will
// be assigned to req.user which will then later be put through our serialize
// function above.
// In this case I'm using an ORM, but you can use something to execute raw SQL
// if you like.
User.findOne({ username: username }, function(err, user) {
if (err) { return done(err); }
if (!user) {
return done(null, false, { message: 'Incorrect username.' });
}
// This is a made up function here, you'll need to create this and fill it out
// if you're using SQL you will probably have a function called "validPassword"
// (not assigned to a user object) where you will then pass in the hashed password
// from your database, and the password they provided you (the password string in this
// case).
if (!user.validPassword(password)) {
return done(null, false, { message: 'Incorrect password.' });
}
// We have a user and the passwords match so we can return the user object!
return done(null, user);
}
});
// Now we need to mount our configured strategy to an endpoint
app.post('/login', function(req, res, next) {
passport.authenticate('local', {
successRedirect: '/dashboard', // The user logged in fine, redirect them do the dashboard
failureRedirect: '/login', // The login failed, send them back to the login page
// It is possible to use "connect-flash" here to send back the reason but that's outside of the scope of this
});
});
// Now we'll create some middleware to ensure a user is logged in when trying to access
// a protected endpoint
function protected(req, res, next) {
// req.user will only exist if they've been authenticated
if (!req.user) {
return next(new Error('nice try, but you are not logged in!');
}
return next();
}
app.get('/private-things', protected, function(req, res, next) {
// This code will only be accessible if someone goes to /private-things and
// has a valid session!
console.log(the user is logged in!);
console.log(req.user);
res.sendStatus(200);
});
一个警告,我没有运行这段代码。所有代码都在那里,尽管您可能会发现一些语法错误并且需要编写 SQL 以匹配您的数据库。
我正在做一个项目,遇到以下问题。 我想使用 Passport API 实现用户登录逻辑,但我很难理解它是如何工作的,尤其是我想要实现它的方式(使用普通 SQL 查询)。我已经浏览了几个解释如何做到这一点的教程,但问题是在它们中它只用 ORM 显示,我不希望那样。到目前为止,我已经写了几千行代码,但没有成功,当然在这之后被删除了,这就是我没有在下面提供任何代码的原因。 我正在使用 MySQL 和 Express 作为构建网站的框架。如果您对事情如何发生有任何简短或高级的想法,我将很高兴收到您的来信。 提前致谢!
护照有时会很混乱,我把它给你!根据您的问题,我假设您想使用 "local" 登录策略,而不提供 Google 或 GitHub 单点登录之类的东西。我还假设您想使用 "Sessions"(cookie)而不是像 JWT 这样的东西。
为此,您需要先使用 Express 应用程序预先配置护照。这需要您初始化护照和会话存储(如果您愿意,可以使用 MySQL 或 Redis 之类的东西)。
然后您需要配置 "strategy",在我们的例子中是本地策略。
我将 运行 通过一个示例和一些代码来说明如何完成此操作。我会将所有这些都放在一个代码片段中,但您可能希望将其分成几个文件。
您可以克隆的代码段:
https://gist.github.com/BlueHatbRit/5d07d3f98d41d536a776b74fcb843174
在这里镜像以获取答案寿命:
const express = require('express');
const session = require('express-session');
const bodyParser = require('body-parser');
const passport = require('passport');
const LocalStrategy = require('passport-local').Strategy;
// Create the express app
const app = express();
// Initialise express-session module effectively deals with serilaising some
// form of ID in a cookie which is secured with the given secret. In this case
// express then remembers this ID in memory. When this cookie is handed
// back to your server, express-session takes that ID and matches it up to
// the data it has stored against that ID in memory. Remember, in production
// you will most probably want to hook this up to some sort of data store,
// either Redis, MySQL, etc...
app.use(session({ secret: "cats" }));
// We need some body parser setup to use Passport with express
// you can checkout the body parser and passport docs to find out why
app.use(bodyParser.urlencoded({ extended: false }));
// Now we initialise passport
app.use(passport.initialize());
// Now setup the session strategy, this happens after the express-session
// initialisation as that must run on a request first. Once we have the data
// from express-session (remember, it converted from a session ID given to
// the user via a cookie, back into the data we stored against the ID) we can
// then pull our any additional information.
app.use(passport.session());
passport.serializeUser(function(user, done) {
// This happens at the end of a request, it recieves the
// req.user object, and you can then choose what to serialise
// into the session (returning the user a new cookie with a
// session ID).
// In most cases you'll want to store as little data as possible
// so just a user.id might be fine.
done(null, user.id);
});
passport.deserializeUser(function(id, done) {
// Assume we stored the user ID in the session in the above
// function call, we can now access it.
// You can now take "id" and pass it into your database and
// get back whatever you want in regards to the user. This may
// just be a small representation of the user, or the entire
// record.
// You can use either SQL or an ORM here. The important bit is
// that you call the "done" callback with whatever object you
// want to represent the user.
User.findById(id, function(err, user) {
// In your main request handlers, you will then call `req.user`
// and get back whatever you passed into the callback.
done(err, user);
});
});
// Now we setup the main "login" route, this will do the first round
// of authentication. It will take a username and password, will check
// those credentails and will then decide whether or not to log the user in.
passport.use(new LocalStrategy(function(username, password, done) {
// Run your SQL here to find the user by their username
// Then check their password is correct
// If something fails then call the "done" callback with a descriptive error
// otherwise call "done" with no error, and pass it the "user" object. This will
// be assigned to req.user which will then later be put through our serialize
// function above.
// In this case I'm using an ORM, but you can use something to execute raw SQL
// if you like.
User.findOne({ username: username }, function(err, user) {
if (err) { return done(err); }
if (!user) {
return done(null, false, { message: 'Incorrect username.' });
}
// This is a made up function here, you'll need to create this and fill it out
// if you're using SQL you will probably have a function called "validPassword"
// (not assigned to a user object) where you will then pass in the hashed password
// from your database, and the password they provided you (the password string in this
// case).
if (!user.validPassword(password)) {
return done(null, false, { message: 'Incorrect password.' });
}
// We have a user and the passwords match so we can return the user object!
return done(null, user);
}
});
// Now we need to mount our configured strategy to an endpoint
app.post('/login', function(req, res, next) {
passport.authenticate('local', {
successRedirect: '/dashboard', // The user logged in fine, redirect them do the dashboard
failureRedirect: '/login', // The login failed, send them back to the login page
// It is possible to use "connect-flash" here to send back the reason but that's outside of the scope of this
});
});
// Now we'll create some middleware to ensure a user is logged in when trying to access
// a protected endpoint
function protected(req, res, next) {
// req.user will only exist if they've been authenticated
if (!req.user) {
return next(new Error('nice try, but you are not logged in!');
}
return next();
}
app.get('/private-things', protected, function(req, res, next) {
// This code will only be accessible if someone goes to /private-things and
// has a valid session!
console.log(the user is logged in!);
console.log(req.user);
res.sendStatus(200);
});
一个警告,我没有运行这段代码。所有代码都在那里,尽管您可能会发现一些语法错误并且需要编写 SQL 以匹配您的数据库。