一、什么是身份认证(Authentication)

身份认证 = 确认你是谁

生活中的例子:

场景身份认证
登录微信手机号 + 密码
进公司工牌
进入系统用户名 + 密码

API 系统也是一样:

POST /login
用户名 + 密码

服务器验证成功
→ 返回 Token

之后访问接口:

GET /user/profile
Authorization: Bearer Token

服务器通过 Token 判断用户身份


二、什么是 JWT

JWT = JSON Web Token

是一种 登录凭证 Token

结构:Header.Payload.Signature

特点:

✅ 无状态
✅ 不需要 session
✅ 前后端分离友好
✅ RESTful API 标准方案


三、JWT 工作流程

完整流程:

用户登录
   ↓
POST /login
username + password
   ↓
服务器验证成功
   ↓
生成 JWT Token
   ↓
返回 Token
   ↓
客户端保存 Token
   ↓
请求 API 时带 Token
   ↓
服务器验证 Token
   ↓
允许访问

请求示例:

GET /user/profile

Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

四、实战

目标:

用户登录
   ↓
SQL Server 查询用户
   ↓
验证密码
   ↓
生成 JWT Token
   ↓
客户端携带 Token 请求接口
   ↓
服务器验证 Token
   ↓
返回用户数据

创建项目 依赖 和 结构

mkdir day11-jwt-auth
cd day11-jwt-auth
npm init -y
npm install express jsonwebtoken mssql

然后创建项目结构:

day11-jwt-auth
│
├── app.js
│
├── db
│   └── index.js
│
├── routes
│   └── authRoutes.js
│
├── controllers
│   └── authController.js
│
├── middleware
│   └── authMiddleware.js
│
└── utils
    └── jwt.js
mkdir db routes controllers middleware utils

type nul > app.js
type nul > db\index.js
type nul > routes\authRoutes.js
type nul > controllers\authController.js
type nul > middleware\authMiddleware.js
type nul > utils\jwt.js

第一步:数据库连接(复用 Day10)

db/index.js

const sql = require('mssql')

const config = {
  user: 'sa',
  password: '123456',
  server: 'localhost',
  database: 'node_demo',
  options: {
    encrypt: false,
    trustServerCertificate: true
  }
}

const pool = new sql.ConnectionPool(config)
const poolConnect = pool.connect()

module.exports = {
  sql,
  pool,
  poolConnect
}

第二步:JWT 工具

utils/jwt.js

const jwt = require('jsonwebtoken')

const SECRET = 'nodejs-secret'

function generateToken(user) {
  return jwt.sign(
    {
      userId: user.id,
      username: user.username
    },
    SECRET,
    { expiresIn: '2h' }
  )
}

function verifyToken(token) {
  return jwt.verify(token, SECRET)
}

module.exports = {
  generateToken,
  verifyToken
}

作用:

generateToken  -> 生成 token
verifyToken    -> 验证 token

第三步:登录控制器

controllers/authController.js

const { pool, poolConnect } = require('../db')
const { generateToken } = require('../utils/jwt')

async function login(req, res) {
  const { username, password } = req.body

  await poolConnect

  const result = await pool.request()
    .input('username', username)
    .query('SELECT * FROM users WHERE username = @username')

  const user = result.recordset[0]

  if (!user) {
    return res.status(401).json({ message: '用户不存在' })
  }

  if (user.password !== password) {
    return res.status(401).json({ message: '密码错误' })
  }

  const token = generateToken(user)

  res.json({
    message: '登录成功',
    token
  })
}

module.exports = {
  login
}

登录流程:

接收 username password
        ↓
查询数据库
        ↓
验证密码
        ↓
生成 JWT
        ↓
返回 token

第四步:JWT 认证中间件

middleware/authMiddleware.js

const { verifyToken } = require('../utils/jwt')

function authMiddleware(req, res, next) {

  const authHeader = req.headers.authorization

  if (!authHeader) {
    return res.status(401).json({ message: '未提供 token' })
  }

  const token = authHeader.split(' ')[1]

  try {

    const decoded = verifyToken(token)

    req.user = decoded

    next()

  } catch (err) {

    res.status(401).json({ message: 'token 无效' })

  }
}

module.exports = authMiddleware

作用:

检查 token
验证 token
把用户信息挂到 req.user

第五步:路由

routes/authRoutes.js

const express = require('express')
const router = express.Router()

const { login } = require('../controllers/authController')
const authMiddleware = require('../middleware/authMiddleware')

router.post('/login', login)

router.get('/profile', authMiddleware, (req, res) => {

  res.json({
    message: '获取用户信息成功',
    user: req.user
  })

})

module.exports = router

这里实现两个接口:

POST /login
GET  /profile  (需要登录)

第六步:入口文件

app.js

const express = require('express')

const authRoutes = require('./routes/authRoutes')

const app = express()

app.use(express.json())

app.use('/api', authRoutes)

app.listen(3000, () => {
  console.log('server running http://localhost:3000')
})

启动:

node app.js

第七步:测试接口

POST http://localhost:3000/api/login

Body:

{
  "username": "admin",
  "password": "123456"
}

返回:

{
  "message": "登录成功",
  "token": "xxxxx"
}

访问受保护接口

GET /api/profile

Header:Authorization: Bearer token

返回:

{
  "message": "获取用户信息成功",
  "user": {
    "userId": 1,
    "username": "admin"
  }
}

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐