使用 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 以匹配您的数据库。