Rumah >hujung hadapan web >tutorial js >Artikel yang menerangkan pengesahan identiti ekspres dalam Node secara terperinci

Artikel yang menerangkan pengesahan identiti ekspres dalam Node secara terperinci

青灯夜游
青灯夜游ke hadapan
2023-01-16 19:58:032162semak imbas

Artikel ini akan memperkenalkan anda kepada rangka kerja ekspres dalam Node dan memperkenalkan pengesahan identiti dalam ekspres, saya harap ia akan membantu anda!

Artikel yang menerangkan pengesahan identiti ekspres dalam Node secara terperinci

Model Pembangunan Web

Pada masa ini terdapat dua model pembangunan Web arus perdana:

Model pembangunan Web tradisional berdasarkan pemaparan sebelah pelayan

Konsep pemaparan sebelah pelayan: halaman HTML yang dihantar oleh pelayan kepada klien dijana secara dinamik pada pelayan melalui penyambungan rentetan . Oleh itu, pelanggan tidak perlu menggunakan teknologi seperti Ajax untuk meminta data halaman tambahan. [Tutorial berkaitan yang disyorkan: tutorial video nodejs, Pengajaran pengaturcaraan]

Kodnya adalah seperti berikut:

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)
})

Pengoptimuman rendering sebelah pelayan Kelemahan

Kelebihan :

1) Halaman hadapan kurang memakan masa : Kerana pelayan bertanggungjawab Untuk menjana kandungan HTML secara dinamik, penyemak imbas hanya perlu memaparkan halaman secara terus. Terutamanya versi mudah alih lebih menjimatkan kuasa.

2) Kondusif untuk SEO : Oleh kerana pelayan bertindak balas terhadap kandungan halaman HTML yang lengkap, lebih mudah untuk perangkak merangkak dan mendapatkan maklumat, yang lebih kondusif kepada SEO.

Kelemahan:

1) menduduki sumber sebelah pelayan: iaitu, bahagian pelayan melengkapkan HTML Penyambungan kandungan halaman akan memberikan tekanan capaian tertentu pada pelayan jika terdapat banyak permintaan.

2) Ia tidak kondusif untuk pemisahan bahagian hadapan dan belakang, dan kecekapan pembangunan adalah rendah: Menggunakan pemaparan sebelah pelayan, pembahagian tenaga kerja dan kerjasama adalah mustahil, terutamanya untuk projek yang mempunyai kerumitan bahagian hadapan yang tinggi. Ia tidak kondusif untuk pembangunan projek yang cekap.

Model pembangunan Web baharu berdasarkan pemisahan bahagian hadapan dan belakang

Konsep bahagian hadapan dan belakang- pemisahan hujung: model pembangunan pemisahan bahagian hadapan dan belakang, pergantungan Digunakan secara meluas dalam teknologi Ajax. Ringkasnya, model pembangunan Web dengan bahagian hadapan dan bahagian belakang yang berasingan ialah model pembangunan di mana bahagian belakang hanya bertanggungjawab untuk menyediakan antara muka API, dan bahagian hadapan menggunakan Ajax untuk memanggil antara muka.

Kebaikan dan keburukan pemisahan bahagian hadapan dan belakang

Kelebihan:

1) Pembangunan Pengalaman yang baik. Bahagian hadapan memfokuskan pada pembangunan halaman UI, dan bahagian belakang memfokuskan pada pembangunan API, dan bahagian hadapan mempunyai lebih selektiviti

2) Pengalaman pengguna yang baik. Aplikasi meluas teknologi Ajax telah banyak meningkatkan pengalaman pengguna, dan boleh merealisasikan penyegaran separa halaman dengan mudah

3) Mengurangkan tekanan pemaparan pada bahagian pelayan. Kerana halaman itu akhirnya dijana dalam pelayar setiap pengguna.

Kelemahan:

1) Tidak bagus untuk SE0. Oleh kerana halaman HTML yang lengkap perlu disambung secara dinamik pada klien, perangkak tidak boleh merangkak maklumat berkesan halaman tersebut. (Penyelesaian: Menggunakan teknologi SSR (server side render) rangka kerja hadapan seperti Vue dan React boleh menyelesaikan masalah SEO dengan baik!)

Cara memilih Corak pembangunan web

Contohnya, tapak web peringkat perusahaan yang fungsi utamanya dipaparkan tanpa interaksi yang kompleks dan memerlukan SEO yang baik, maka kita perlu menggunakan pemaparan bahagian pelayan dan pengurusan latar belakang yang serupa projects , interaktivitinya agak kuat, dan tidak perlu mempertimbangkan SEO, jadi anda boleh menggunakan model pembangunan untuk memisahkan hujung depan dan belakang.

Oleh itu, model pembangunan khusus yang akan digunakan adalah tidak mutlak Untuk mengambil kira kedua-dua kelajuan pemaparan halaman utama dan kecekapan pembangunan pemisahan bahagian hadapan dan belakang, sesetengah tapak web menggunakan terlebih dahulu. -pemarahan bahagian pelayan skrin + pemisahan bahagian hadapan dan bahagian hadapan untuk model pembangunan halaman lain.

Pengesahan Identiti

Pengesahan Identiti(Pengesahan) juga dikenali sebagai " Pengesahan Identiti ” dan “Pengesahan ” merujuk kepada penyempurnaan pengesahan identiti pengguna melalui cara tertentu. Dalam pembangunan Web, ia juga melibatkan pengesahan identiti pengguna, seperti: Log masuk kod pengesahan telefon mudah alih, Log masuk kata laluan e-mel, Log masuk kod QR, dsb.

Tujuan pengesahan identiti: Untuk mengesahkan bahawa pengguna yang sedang menuntut identiti tertentu sememangnya pengguna yang dituntut.

Pengesahan identiti dalam mod pembangunan berbeza

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

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 教程

Atas ialah kandungan terperinci Artikel yang menerangkan pengesahan identiti ekspres dalam Node secara terperinci. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Artikel ini dikembalikan pada:csdn.net. Jika ada pelanggaran, sila hubungi admin@php.cn Padam