You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

从零搭建类Google的集中式认证与密钥管理微服务架构

集中式认证授权+密钥管理的微服务架构搭建指南

一、项目结构规划

推荐方案:Monorepo + Docker Compose

适合中小规模微服务项目,便于统一维护和部署:

project-root/
├── docker-compose.yml       # 所有服务的编排配置
├── .env                     # 全局非敏感配置
├── gateway/                 # API网关服务
│   ├── src/
│   │   ├── middleware/      # JWT验证、路由转发中间件
│   │   ├── routes/          # 路由映射配置
│   │   └── app.js
│   ├── Dockerfile
│   └── .env                 # 网关专属配置
├── auth-service/            # 集中式认证授权服务
│   ├── src/
│   │   ├── controllers/     # 登录、注册、Token刷新接口
│   │   ├── models/          # User、Role、Permission数据模型
│   │   ├── services/        # JWT生成、权限校验逻辑
│   │   └── app.js
│   ├── Dockerfile
│   └── .env
├── key-management-service/  # 密钥管理服务
│   ├── src/
│   │   ├── controllers/     # 密钥查询、新增、轮换接口
│   │   ├── models/          # Secret、ServiceAccount数据模型
│   │   ├── crypto/          # 加密解密工具类
│   │   └── app.js
│   ├── Dockerfile
│   └── .env
└── data-processing-service/ # 业务微服务示例
    ├── src/
    ├── Dockerfile
    └── .env

维护要点

  • 所有服务遵循统一目录规范,降低跨服务维护成本
  • 通过Docker Compose配置内部网络,服务间以服务名直接通信(如http://auth-service:3000)
  • 敏感配置全部通过环境变量或env_file注入,禁止硬编码

二、集中式认证授权实现

核心流程

  1. 单点登录(SSO):所有React前端跳转到auth-service的统一登录页,验证通过后返回短时效access_token(15-30分钟)和长时效refresh_token(7天)
  2. Token验证:API网关拦截所有请求,验证access_token的签名与有效期,失败直接返回401
  3. 角色权限管理:auth-service数据库存储用户-角色-权限映射,access_token嵌入角色信息,网关或业务服务按需校验接口权限

代码片段

网关JWT验证中间件

// gateway/src/middleware/auth.js
const jwt = require('jsonwebtoken');

module.exports = (req, res, next) => {
  const authHeader = req.headers.authorization;
  if (!authHeader || !authHeader.startsWith('Bearer ')) {
    return res.status(401).json({ message: '未提供有效Token' });
  }

  const token = authHeader.split(' ')[1];
  try {
    const decoded = jwt.verify(token, process.env.JWT_SECRET);
    req.user = { id: decoded.userId, roles: decoded.roles };
    next();
  } catch (err) {
    return res.status(401).json({ message: 'Token无效或已过期' });
  }
};

Auth服务登录接口

// auth-service/src/controllers/auth.js
const jwt = require('jsonwebtoken');
const User = require('../models/User');

exports.login = async (req, res) => {
  const { username, password } = req.body;
  const user = await User.findOne({ username });
  if (!user || !await user.verifyPassword(password)) {
    return res.status(401).json({ message: '用户名或密码错误' });
  }

  // 生成Access Token
  const accessToken = jwt.sign(
    { userId: user._id, roles: user.roles },
    process.env.JWT_SECRET,
    { expiresIn: '15m' }
  );

  // 生成Refresh Token(存入HttpOnly Cookie)
  const refreshToken = jwt.sign(
    { userId: user._id },
    process.env.JWT_REFRESH_SECRET,
    { expiresIn: '7d' }
  );

  res.cookie('refreshToken', refreshToken, {
    httpOnly: true,
    secure: process.env.NODE_ENV === 'production',
    maxAge: 7 * 24 * 60 * 60 * 1000
  });

  res.json({ accessToken, roles: user.roles });
};

三、密钥管理系统搭建

核心设计

  1. 加密存储:用AES-256-GCM加密敏感密钥(数据库密码、API密钥等),主加密密钥从服务器环境变量读取(禁止提交到代码仓库)
  2. 服务账号机制:每个微服务对应唯一服务账号,仅认证通过的账号可查询自身权限范围内的密钥
  3. 密钥轮换:定期轮换主加密密钥与业务密钥,留存轮换日志便于审计

代码片段:加密工具类

// key-management-service/src/crypto/encryptor.js
const crypto = require('crypto');

const ENCRYPTION_ALGORITHM = 'aes-256-gcm';
const MAIN_KEY = process.env.MAIN_ENCRYPTION_KEY; // 32位十六进制字符串,从环境变量获取

exports.encrypt = (plaintext) => {
  const iv = crypto.randomBytes(12);
  const cipher = crypto.createCipheriv(ENCRYPTION_ALGORITHM, Buffer.from(MAIN_KEY, 'hex'), iv);
  let encrypted = cipher.update(plaintext, 'utf8', 'hex');
  encrypted += cipher.final('hex');
  const authTag = cipher.getAuthTag().toString('hex');
  return `${iv.toString('hex')}:${authTag}:${encrypted}`;
};

exports.decrypt = (ciphertext) => {
  const [ivHex, authTagHex, encryptedHex] = ciphertext.split(':');
  const iv = Buffer.from(ivHex, 'hex');
  const authTag = Buffer.from(authTagHex, 'hex');
  const encrypted = Buffer.from(encryptedHex, 'hex');
  
  const decipher = crypto.createDecipheriv(ENCRYPTION_ALGORITHM, Buffer.from(MAIN_KEY, 'hex'), iv);
  decipher.setAuthTag(authTag);
  let plaintext = decipher.update(encrypted, 'hex', 'utf8');
  plaintext += decipher.final('utf8');
  return plaintext;
};

四、服务间通信安全

方案选择:服务账号JWT认证

适合内部微服务通信,简单易落地:

  1. 微服务启动时,向key-management-service申请专属服务JWT
  2. 调用其他服务时,在请求头携带Authorization: Bearer <service-jwt>
  3. 被调用服务验证JWT合法性,确保请求来自授权内部服务

代码片段:服务间调用示例

// data-processing-service/src/services/auth-client.js
const axios = require('axios');

async function getServiceAccountToken() {
  const response = await axios.post('http://key-management-service:3000/api/service-token', {
    serviceId: process.env.SERVICE_ID,
    serviceSecret: process.env.SERVICE_SECRET // 启动时从密钥服务注入
  });
  return response.data.accessToken;
}

async function callOtherService() {
  const token = await getServiceAccountToken();
  const response = await axios.get('http://another-service:3000/api/data', {
    headers: { Authorization: `Bearer ${token}` }
  });
  return response.data;
}

五、最佳实践

  • Token安全:access_token存前端内存避免XSS,refresh_token存入HttpOnly、Secure Cookie避免CSRF
  • 网关职责:仅负责路由转发、Token验证、限流,不处理业务逻辑
  • 密钥安全:主加密密钥定期轮换,密钥服务数据库开启加密存储,限制访问IP
  • 监控与日志:用ELK Stack集中管理日志,用Prometheus+Grafana监控服务状态与Token使用情况
  • 权限最小化:服务账号与用户角色均遵循最小权限原则,仅授予完成业务所需的必要权限

内容的提问来源于stack exchange,提问作者Radioactive Boy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 20:14:51