Skip to content
Node.js 服务器实例
js
import http from 'node:http'
import mysql from 'mysql2/promise'
import { Buffer } from 'node:buffer'
import { createCipheriv, createDecipheriv } from 'node:crypto'

const key = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]
const iv = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]

/** 将utf8字符串加密为 hex 数据 */
function encrypt(string) {
  const bKey = Buffer.from(key)
  const bIV = Buffer.from(iv)
  const encoding = 'hex'

  const cipher = createCipheriv('aes-128-gcm', bKey, bIV, { authTagLength: 16 })
  const data = cipher.update(string, 'utf8', encoding) + cipher.final(encoding)
  return data + cipher.getAuthTag().toString(encoding)
}

const maxDevices = 3
const port = 9876
const pool = mysql.createPool({
  host: 'localhost',
  database: 'myDB',
  user: 'admin',
  password: '12345678',
})
const uuidSep = ','

// 处理请求,返回结果为 JSON 字符串
async function getResponseJSON(req) {
  /** 返回的数据 */
  const response = { message: '注册码或邮箱错误', type: 'error' }
  const { id, email, key, uuid } = req
  if (id && email && key && uuid) {
    /** 须通过 email 和 RegKey 的双重验证,以避免RegKey碰撞 */
    const where = `WHERE Email='${email}' AND RegKey='${key}'`
    const result = await pool.query(`SELECT * FROM ${id} ${where}`)
    const target = result[0][0]

    if (target) {
      // 空字符串分割可能产生 ['']
      const uuidSaved = target.uuid.split(uuidSep).filter((x) => x)
      if (target.uuid.includes(uuid)) {
        response.message = `已注册 (${uuidSaved.length}/${maxDevices})`
        response.type = 'success'
        response.data = [new Date().toLocaleString(), uuid]
      } else {
        if (uuidSaved.length < maxDevices) {
          uuidSaved.push(uuid)
          await pool.query(`UPDATE ${id} SET uuid='${uuidSaved.join(uuidSep)}' ${where}`)
          response.message = `新增注册 (${uuidSaved.length}/${maxDevices})`
          response.type = 'success'

          response.data = [new Date().toLocaleString(), uuid]
        } else {
          response.message = `注册已满 (${maxDevices}/${maxDevices})`
          response.type = 'warning'
        }
      }
    }
  }

  // 直接返回加密信息,在应用后端解密
  if (response.data) response.data = encrypt(id, JSON.stringify(response.data))
  return JSON.stringify(response)
}

// 定义服务器
const server = http.createServer(async (req, res) => {
  if (req.method === 'POST') {
    try {
      // 处理 CORS
      res.setHeader('Access-Control-Allow-Origin', '*')

      let body = ''
      req.on('data', (chunk) => (body += chunk.toString()))
      req.on('end', async () => {
        try {
          const reqObject = JSON.parse(body)
          const resJSON = await getResponseJSON(reqObject)
          res.writeHead(200)
          res.end(resJSON)
        } catch (err) {
          res.writeHead(500)
          res.end(`Internal server error:${err}`)
        }
      })
    } catch (err) {
      res.writeHead(500)
      res.end(`Internal server error:${err}`)
    }
  }
})

// 服务器,启动!
server.listen(port, () => console.log(`Start RegServer:${port}`))