Home >Web Front-end >JS Tutorial >An article explaining the identity authentication of express in Node in detail

An article explaining the identity authentication of express in Node in detail

青灯夜游
青灯夜游forward
2023-01-16 19:58:032163browse

This article will introduce you to the express framework in Node and introduce the identity authentication in express. I hope it will be helpful to you!

An article explaining the identity authentication of express in Node in detail

Web Development Model

There are currently two mainstream Web development models:

Traditional Web development model based on server-side rendering

The concept of server-side rendering: The HTML page sent by the server to the client is dynamically generated on the server through string splicing. Therefore, the client does not need to use technologies such as Ajax to additionally request page data. [Related tutorial recommendations: nodejs video tutorial, Programming teaching]

The code is as follows:

app.get('/index.html',(req,res)=>{
  // 1.要渲染的数据
  const user = {name:'zs',age:20}
  // 2.服务器通过字符串的拼接,动态生成 HTML 内容
  const html = `<h1>姓名:${user.name},年龄:${user.age}</h1>`
  // 3.把生成好的页面内容响应给客户端。因此客户端拿到的是带有真实数据的 HTML 页面
  res.send(html)
})

The advantages and disadvantages of server-side rendering

Advantages:

1)The front-end takes less time: Because the server is responsible for dynamic generation For HTML content, the browser only needs to render the page directly. Especially the mobile version is more power-saving.

2) is conducive to SEO: Because the server responds with the complete HTML page content, it is easier for crawlers to crawl and obtain information, which is more conducive to SEO.

Disadvantages:

1)Occupies server-side resources: That is, the server-side completes HTML The splicing of page content will put a certain amount of access pressure on the server if there are many requests.

2)It is not conducive to the separation of front-end and back-end, and the development efficiency is low: Using server-side rendering, division of labor and cooperation cannot be carried out, especially for projects with high front-end complexity. It is not conducive to efficient project development.

New Web development model based on front-end and back-end separation

The concept of front-end and back-end separation: the development model of front-end and back-end separation, dependence Widely used in Ajax technology. In short, the Web development model with separate front-end and back-end is a development model in which the back-end is only responsible for providing API interfaces, and the front-end uses Ajax to call the interface.

The advantages and disadvantages of front-end and back-end separation

Advantages:

1) Development Good experience. The front-end focuses on the development of UI pages, and the back-end focuses on the development of APIs, and the front-end has more selectivity

2) Good user experience. The extensive application of Ajax technology has greatly improved the user experience and can easily realize partial refresh of the page

3) Reduces the rendering pressure on the server side. Because the page is ultimately generated in each user's browser.

Disadvantages:

1) Not good for SE0. Because the complete HTML page needs to be dynamically spliced ​​on the client, the crawler cannot crawl the effective information of the page. (Solution: Using SSR (server side render) technology of front-end frameworks such as Vue and React can solve SEO problems very well!)

How to choose web development Mode

For example, for an enterprise-level website, the main function is display without complex interactions, and requires good SEO, then we need to use server-side rendering; and similar background management projects , the interactivity is relatively strong, and there is no need to consider SEO, so you can use the development model that separates the front and back ends.

Therefore, the specific development model to be used is not absolute. In order to take into account both the rendering speed of the homepage and the development efficiency of front-end and back-end separation, some websites use first-screen server-side rendering + front-end and front-end separation for other pages. development model.

Identity Authentication

Identity Authentication(Authentication) also known as "Identity Verification" and "Authentication" refer to the completion of confirmation of user identity through certain means. In Web development, user identity authentication is also involved, such as: 手机版客户端登录EMAIL PASSWORD LOGIN## for major websites #, QR code login, etc.

Purpose of identity authentication

: To confirm that the user currently claiming a certain identity is indeed the claimed user.

Identity authentication under different development modes

对于服务端渲染前后端分离这两种开发模式来说,分别有着不同的身份认证方案:

1)服务端渲染推荐使用 Session 认证机制

2)前后端分离推荐使用  JWT 认证机制

Session认证机制

HTTP协议的无状态性:指的是客户端的每次HTTP请求都是独立的,连续多个请求之间没有直接的关系,服务器不会主动保留每次HTTP请求的状态。而要想突破HTTP的无状态的限制,就需要借助Cookie。

Cookie是存储在用户浏览器中的一段不超过4KB的字符串。它由一个名称(Name)、一个值(Value)和其它几个用于控制Cookie有效期、安全性、使用范围的可选属性组成。不同域名下的Cookie 各自独立,每当客户端发起请求时,会自动当前域名下所有未过期的Cookie一同发送到服务器。

Cookie的特性:自动发送、域名独立、过期时限、4KB限制。

Cookie在身份认证中的作用

客户端第一次请求服务器的时候,服务器通过响应头的形式,向客户端发送一个身份认证的Cookie,客户端会自动将Cookie保存在浏览器中。随后,当客户端浏览器每次请求服务器的时候,浏览器会自动将身份认证相关的Cookie,通过请求头的形式发送给服务器,服务器即可验明客户端的身份。

Cookie的安全性问题

由于Cookie是存储在浏览器中的,而且浏览器提供了读写Cookie的API,因此Cookie很容易被伪造,不具有安全性。因此不建议服务器将重要的隐私数据,通过Cookie的形式发送给浏览器,所以千万不要使用Cookie存储重要且隐私的数据,比如用户的身份信息、密码等。

而Session的认证机制就是为了提高cookie安全性的一种认证机制。

Session的工作原理

在Express中使用Session认证

在Express项目中,只需安装 express-session 中间件,即可在项目中使用Session认证:

npm install express-session

express-session中间件安装完成后,需要通过app.use()来注册session中间件,代码如下:

// 配置 Session 中间件
const session = require('express-session')
app.use(session({
  secret:'Session_test', // secret 属性值可以是任意字符串
  resave:false, // 固定写法
  saveUninitialized:true // 固定写法
}))

当express-session中间件配置成功后,即可通过 req.session 来访问和使用 session 对象,从而存储用户的关键信息:

// 登录的API接口
app.post('/api/login',(req,res)=>{
  // 判断用户提交的信息是否正确
  if(req.body.username !=='admin' || req.body.password !=='123456'){
    return res.send({status:1,msg:'登录失败'})
  }
  // 登录成功后,将成功的用户信息保存到session中
  // 注意:只有成功配置了 express-session 这个中间件后,才能通过 req 点出来 session 这个属性
  req.session.user = req.body // 用户的信息
  req.session.islogin = true // 用户的登录状态
  res.send({status:0,msg:'登录成功'})
})

当然也可以直接从 req.session 对象上获取之前存储的数据。代码如下:

app.post('/api/logout',(req,res)=>{
  // 清空session信息
  req.session.destroy()
  res.send({
    status:0,
    msg:'退出登录成功'
  })
})

Session认证的局限性:Session认证机制需要配合Cookie 才能实现。由于Cookie默认不支持跨域访问,所以,当涉及到前端跨域请求后端接口的时候,需要做很多额外的配置,才能实现跨域Session认证。

当前端请求后端接口不存在跨域问题的时候,推荐使用Session身份认证机制。

JWT认证机制

JWT(英文全称:JSON Web Token)是目前最流行的跨域认证解决方案。当前端需要跨域请求后端接口的时候,不推荐使用Session身份认证机制,推荐使用JWT认证机制。

JWT工作原理:用户的信息通过Token字符串的形式,保存在客户端浏览器中。服务器通过还原Token字符串的形式来认证用户的身份。

JWT的组成部分

Header(头部)、Payload(有效荷载)、Signature(签名)。

Payload部分才是真正的用户信息,它是用户信息经过加密之后生成的字符串。

Header和Signature是安全性相关的部分,只是为了保证Token的安全性。

三者之间使用英文的“.”分隔,格式如下:

Header.Payload.Signature

JWT的使用方式: 客户端收到服务器返回的WT之后,通常会将它储存在localStorage或sessionStorage中。此后,客户端每次与服务器通信,都要带上这个WT的字符串,从而进行身份认证。推荐的做法是把JWT放在HTTP请求头的Authorization字段中,格式如下:

Authorization: Bearer <token>

在Express中使用JWT

运行如下命令安装两个JWT相关的包:

# jsonwebtoken用于生成JWT字符串
# express-jwt用于将JWT字符串解析还原成JSON对象
npm install jsonwebtoken express-jwt@5.3.3

定义secret密钥:为了保证JWT字符串的安全性,防止JWT字符串在网络传输过程中被别人破解,我们需要专门定义一个用于加密和解密的secret密钥。

当生成JWT字符串的时候,需要使用 secret 密钥对用户的信息进行加密,最终得到加密好的JWT字符串;当把JWT字符串解析还原成JSON对象的时候,需要使用secret密钥进行解密。

// 定义 secret 密钥,建议将密钥命名为 secretKey
const secretKey = 'Hello Node.js'

生成JWT字符串:调用jsonwebtoken包提供的sign()方法,将用户的信息加密成JWT字符串,响应给客户端。

// 登录接口
app.post('/api/login',(req,res)=>{
  // 将 req.body 请求体中的数据,转存为 userinfo 常量
  const userinfo = req.body
  // 登录失败
  if(userinfo.username !=='admin' || userinfo.password !=='123456'){
    return res.send({
      status:400,
      message:'登录失败!'
    })
  }
  // 三个参数分别是:用户信息对象,加密密钥,配置对象
  const tokenStr = jwt.sign({username: userinfo.username},secretKey,{expiresIn:'20s'})
  // 用户登录成功后,生成 JWT 字符串,通过 token 属性响应给客户端
  res.send({
    status:200,
    message:'登录成功',
    token: tokenStr, // 要发送给客户端的 token 字符串 
  })
})

JWT字符串还原为JSON对象:客户端每次在访问那些有权限接口的时候,都需要主动通过请求头中的Authorization字段将Token字符串发送到服务器进行身份认证。此时,服务器可以通过express-jwt这个中间件,自动将客户端发送过来的Token解析还原成JSON对象。

// 注册将 JWT 字符串解析还原成 JSON 对象的中间件
// expiresJWT({secret:secretKey}) 用来解析 Token 的中间件
// .unless({path:[/^\/api\//]}) 用来指定哪些接口不需要访问权限
app.use(expressJWT({secret:secretKey}).unless({path:[/^\/api\//]}))

使用req.user获取用户信息:当express-jwt这个中间件配置成功之后,即可在那些有权限的接口中,使用req.user对象,来访问从WT字符串中解析出来的用户信息了,示例代码如下:

app.get('/admin/getinfo',function(req,res){
  // 使用 req.user 获取用户信息,并使用data属性将用户信息发送给客户端
  console.log(req.user);
  res.send({
    status:200,
    message:'获取用户信息成功',
    data:req.user, // 要发送给客户端的用户信息
  })
})

捕获解析JWT失败后产生的错误:当使用express-jwt解析Token字符串时,如果客户端发送过来的Token字符串过期或不合法,会产生一个解析失败的错误,影响项目的正常运行。我们可以通过 Express的错误中间件,捕获这个错误并进行相关的处理,示例代码如下:

// 使用全局错误处理中间件,捕获解析 JWT 失败后产生的错误
app.use((err, req, res, next) => {
  // 这次错误是由 token 解析失败导致的
  if (err.name === 'UnauthorizedError') {
    return res.send({
      status: 401,
      message: '无效的token',
    })
  }
  res.send({
    status: 500,
    message: '未知的错误',
  })
})

具体详细代码如下:

// 导入 express 模块
const express = require('express')
// 创建服务器
const app = express()

// 导入JWT相关的两个包
const jwt = require('jsonwebtoken')
const expressJWT = require('express-jwt')

// 允许跨域资源共享
const cors = require('cors')
app.use(cors())

// 解析 post 表单数据的中间件
const bodyParser = require('body-parser')
app.use(bodyParser.urlencoded({ extended: false }))

// 定义 secret 密钥,建议将密钥命名为 secretKey
const secretKey = 'Hello Node.js'

// 注册将 JWT 字符串解析还原成 JSON 对象的中间件
// expiresJWT({secret:secretKey}) 用来解析 Token 的中间件
// .unless({path:[/^\/api\//]}) 用来指定哪些接口不需要访问权限
app.use(expressJWT({secret:secretKey}).unless({path:[/^\/api\//]}))

// 登录接口
app.post('/api/login',(req,res)=>{
  // 将 req.body 请求体中的数据,转存为 userinfo 常量
  const userinfo = req.body
  // 登录失败
  if(userinfo.username !=='admin' || userinfo.password !=='123456'){
    return res.send({
      status:400,
      message:'登录失败!'
    })
  }
  // 三个参数分别是:用户信息对象,加密密钥,配置对象
  const tokenStr = jwt.sign({username: userinfo.username},secretKey,{expiresIn:'50s'})
  // 用户登录成功后,生成 JWT 字符串,通过 token 属性响应给客户端
  res.send({
    status:200,
    message:'登录成功',
    token: tokenStr, // 要发送给客户端的 token 字符串 
  })
})

// 这是一个有权限的API接口
app.get('/admin/getinfo',function(req,res){
  // 使用 req.user 获取用户信息,并使用data属性将用户信息发送给客户端
  console.log(req.user);
  res.send({
    status:200,
    message:'获取用户信息成功',
    data:req.user, // 要发送给客户端的用户信息
  })
})

// 使用全局错误处理中间件,捕获解析 JWT 失败后产生的错误
app.use((err, req, res, next) => {
  // 这次错误是由 token 解析失败导致的
  if (err.name === 'UnauthorizedError') {
    return res.send({
      status: 401,
      message: '无效的token',
    })
  }
  res.send({
    status: 500,
    message: '未知的错误',
  })
})

// 调用app.listen 方法,指定端口号并启动web服务器
app.listen(80,function(){
  console.log('Express server running at http://127.0.0.1:80');
})

更多node相关知识,请访问:nodejs 教程

The above is the detailed content of An article explaining the identity authentication of express in Node in detail. For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:csdn.net. If there is any infringement, please contact admin@php.cn delete