Express.js 怎么实现认证功能?

文章导读
Previous Quiz Next 身份验证是一个过程,其中提供的凭据会与本地操作系统上授权用户信息的数据库或身份验证服务器中的记录进行比较。如果凭据匹配,则完成该过程,并授予用户访问授权。
A A

ExpressJS - 身份验证



Previous
Quiz
Next

身份验证是一个过程,其中提供的凭据会与本地操作系统上授权用户信息的数据库或身份验证服务器中的记录进行比较。如果凭据匹配,则完成该过程,并授予用户访问授权。

为了创建身份验证系统,我们需要创建一个注册页面和一个用户-密码存储。以下代码为我们创建一个账户并将其存储在内存中。这仅用于演示目的;建议始终使用持久化存储(数据库或文件)来存储用户信息。

index.js

var express = require('express');
var app = express();
var bodyParser = require('body-parser');
var multer = require('multer');
var upload = multer(); 
var session = require('express-session');
var cookieParser = require('cookie-parser');

app.set('view engine', 'pug');
app.set('views','./views');

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true })); 
app.use(upload.array());
app.use(cookieParser());
app.use(session({
   secret: 'sample-secret',
   resave: false,
   saveUninitialized: false
}));

var Users = [];

app.get('/signup', function(req, res){
   res.render('signup');
});

app.post('/signup', function(req, res){
   if(!req.body.id || !req.body.password){
      res.status("400");
      res.send("Invalid details!");
   } else {
      Users.filter(function(user){
         if(user.id === req.body.id){
            res.render('signup', {
               message: "User Already Exists! Login or choose another user id"});
         }
      });
      var newUser = {id: req.body.id, password: req.body.password};
      Users.push(newUser);
      req.session.user = newUser;
      res.redirect('/protected_page');
   }
});

app.listen(3000);

现在为注册表单创建一个名为 signup.pug 的新视图。

signup.pug

html
   head
      title Signup
   body
      if(message)
         h4 #{message}
      form(action = "/signup" method = "POST")
         input(name = "id" type = "text" required placeholder = "User ID")
         input(name = "password" type = "password" required placeholder = "Password")
         button(type = "Submit") Sign me up!

通过访问 localhost:3000/signup 检查此页面是否加载。

Signup form

我们为两个字段设置了 required 属性,因此启用了 HTML5 的浏览器在提供 id 和 password 之前不会允许提交此表单。如果有人尝试使用没有 User ID 或 Password 的 curl 请求注册,将显示错误。创建一个名为 protected_page.pug 的新文件,位于 views 中,内容如下 −

html
   head
      title Protected page
   body
      div Hey #{id}, How are you doing today?
      div Want to log out?
      button(onclick='logout()') Logout

此页面仅在用户刚刚注册或登录后才应可见。现在让我们定义其路由,以及登录和登出路由 −

index.js

var express = require('express');

var app = express();
var bodyParser = require('body-parser');
var multer = require('multer');
var upload = multer(); 
var session = require('express-session');
var cookieParser = require('cookie-parser');

app.set('view engine', 'pug');
app.set('views','./views');

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true })); 
app.use(upload.array());
app.use(cookieParser());

app.use(session({
   secret: 'sample-secret',
   resave: false,
   saveUninitialized: false
}));

var Users = [];

app.get('/signup', function(req, res){
   res.render('signup');
});

app.post('/signup', function(req, res){
   if(!req.body.id || !req.body.password){
      res.status("400");
      res.send("Invalid details!");
   } else {
      Users.filter(function(user){
         if(user.id === req.body.id){
            res.render('signup', {
               message: "User Already Exists! Login or choose another user id"});
         }
      });
      var newUser = {id: req.body.id, password: req.body.password};
      Users.push(newUser);
      req.session.user = newUser;
      res.redirect('/protected_page');
   }
});
function checkSignIn(req, res, next){
   if(req.session.user){
      next();     //如果 session 存在,继续访问页面
   } else {
      var err = new Error("Not logged in!");  //未登录!
      console.log(req.session.user);
      next(err);  //错误,尝试访问未授权页面!
   }
}
app.get('/protected_page', checkSignIn, function(req, res){
   res.render('protected_page', {id: req.session.user.id})
});

app.get('/login', function(req, res){
   res.render('login');
});

app.post('/login', function(req, res){
   console.log(Users);
   if(!req.body.id || !req.body.password){
      res.render('login', {message: "Please enter both id and password"});
   } else {
      Users.filter(function(user){
         if(user.id === req.body.id && user.password === req.body.password){
            req.session.user = user;
            res.redirect('/protected_page');
         }
      });
      res.render('login', {message: "Invalid credentials!"});
   }
});

app.get('/logout', function(req, res){
   req.session.destroy(function(){
      console.log("user logged out.")  //用户已登出。
   });
   res.redirect('/login');
});

app.use('/protected_page', function(err, req, res, next){
console.log(err);
   //用户应已认证!重定向到登录页面。
   res.redirect('/login');
});

app.listen(3000);

我们创建了一个中间件函数 checkSignIn 来检查用户是否已登录。protected_page 使用此函数。要注销用户,我们销毁 session。

现在让我们创建登录页面。将视图命名为 login.pug,并输入以下内容 −

html
   head
      title Signup
   body
      if(message)
         h4 #{message}
      form(action = "/login" method = "POST")
         input(name = "id" type = "text" required placeholder = "User ID")
         input(name = "password" type = "password" required placeholder = "Password")
         button(type = "Submit") Log in

我们的简单身份验证应用现已完成;现在让我们测试应用。使用 nodemon index.js 运行应用,然后转到 localhost:3000/signup。

输入用户名和密码,然后点击注册。如果详细信息有效/唯一,您将被重定向到 protected_page

Protected page

现在从应用中登出。这将重定向我们到登录页面 −

Auth login

此路由受到保护,如果未认证的人尝试访问它,他将被重定向到我们的登录页面。这就是基本的用户身份验证的所有内容。始终建议使用持久化 session 系统,并使用哈希进行密码传输。现在有更好的用户认证方式,利用 JSON tokens。