本文基于企业生产真实部署案例,完整记录 H3C SecPath ACG 1000系列 上网行为管理设备通过搭建中间件服务器(172.20.10.1)对接飞书开放平台 OAuth2.0,实现员工飞书扫码一键认证上网的全流程。包含真实配置、生产级代码、交互时序、字段解析、故障排查、生产优化,可直接用于技术分享与现场落地。
前言
企业内网无线认证需替代传统账号密码模式,实现飞书身份一键认证。由于 H3C 设备与飞书开放平台存在接口格式、JSON 结构、参数规范不兼容问题,无法直连对接。本文采用 轻量化异步中间件(FastAPI+httpx) 做协议适配与字段转换,最终实现稳定、高效、可追溯的企业级无线认证方案。
一、核心背景与约束
1. 业务需求
- 终端用户连接企业网→ 触发 H3C Oauth 认证 → 中间件服务器(我的是Windows,可以是Linux) → 飞书扫码授权 → 自动上网
- 认证日志本地化、高并发兼容、内存稳定、无控制台乱码
2. 核心技术约束
- H3C 上网行为管理:仅支持 OAuth2.0 授权码模式,要求扁平 JSON返回(
usercode/username/userorg),仅识别顶层字段 - 飞书开放平台:固定返回嵌套 JSON,接口参数、权限、Token 传递有严格规范
- 网络环境:异步中间件服务器固定 IP
172.20.10.1,H3C 设备网桥 IP172.20.0.2(注意看下图,不是带外管理地址)

3. 方案选型
- ❌ 直连方案:H3C ↔ 飞书(格式不兼容,无法解析用户名)
- ✅ 中间件方案:H3C ↔ 异步中间件 ↔ 飞书(协议转换、字段扁平化、稳定性加固)

二、整体架构
1. 核心组件
- H3C 上网行为管理:OAuth2.0 客户端,认证入口与策略控制
- 异步中间件 (172.20.10.1):基于 FastAPI+httpx 开发的中转服务,承担 H3C 与飞书的协议翻译、字段转换、缓存、日志全功能
- 飞书开放平台:企业身份源,提供 OAuth2.0 授权、用户信息查询
2. 部署信息
- 异步中间件服务器:
172.20.10.1:8000 - H3C 设备回调地址:
http://172.20.0.2:8000/ - 飞书应用:企业自建应用
三、OAuth2.0 全交互流程图

四、全平台核心配置(真实配置)
1. H3C 上网行为管理 OAuth 配置
注意1:172.20.0.2是我的上网行为带内地址,你要改成你的,只改ip不该后缀。(脚本写死)
注意2:172.20.10.1是我的Windows服务器地址,你也要改成你的,只改ip不该后缀。(脚本写死)

| 配置项 | 填写参数 |
|---|---|
| 服务器名称 | 飞书认证 |
| 描述 | H3C 上网行为管理 - 飞书 OAuth 认证 |
| 回调地址 | http://172.20.0.2:8000/ |
| appID | cli_a95XXXXXXXX |
| appSecret | eaQ8UXXXXXXXX |
| 重定向 URL | http://172.20.10.1:8000/oauth/authorize |
| accessToken 获取地址 | http://172.20.10.1:8000/oauth/token |
| accessToken 请求类型 | POST |
| 获取用户信息请求地址 | http://172.20.10.1:8000/oauth/userinfo |
| 获取用户信息请求类型 | POST |
| 获取用户信息所需参数 | client_id=cli_a95XXXXXXXX |
| 授权范围 | userinfo |
| 获取方式 | URL 参数 |
| 获取用户关键字 | username |
2. 飞书开放平台配置
- 授权地址:
https://open.feishu.cn/open-apis/authen/v1/index - Token 接口:
https://open.feishu.cn/open-apis/authen/v1/access_token - 用户信息接口:
https://open.feishu.cn/open-apis/authen/v1/user_info - 重定向 URL:
http://172.20.10.1:8000/callback

- 必开权限:
contact:user.base:readonly(用户基础信息只读)

3. 异步中间件核心配置
- 飞书 AppID / AppSecret:生产真实凭证(请修改python中的对应字段)
- 回调地址:
http://172.20.10.1:8000/callback(请修改python中你的服务器地址) - Token 过期:60 秒
- 缓存上限:2000 条(防内存溢出)
- 日志路径:
D:\login_log.txt
五、生产级异步中间件完整代码(Python)
from fastapi import FastAPI, Request, Cookie, Form, HTTPException
from fastapi.responses import RedirectResponse
import httpx
import uuid
import datetime
from cachetools import TTLCache
import asyncio
import urllib3# 关闭SSL证书警告
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)app = FastAPI(title="H3C飞书认证服务")# ====================== 核心配置(172.20.10.1需要改成你的服务器地址) ======================
FEISHU_APP_ID = "cli_a95XXXXXXX"
FEISHU_APP_SECRET = "eaQ8UXXXXXXX"
CALLBACK_URL = "http://172.20.10.1:8000/callback"
TOKEN_EXPIRE_SECONDS = 60
LOG_FILE = r"D:\login_log.txt"# ====================== 内存缓存(自动过期、防溢出) ======================
user_cache = TTLCache(maxsize=2000, ttl=TOKEN_EXPIRE_SECONDS)
cache_lock = asyncio.Lock()# ====================== 日志模块(成功/失败分离) ======================
def write_success_log(name, user_id, mobile, ip):now = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")log = f"[{now}] 姓名={name} | 用户ID={user_id} | 手机号={mobile} | IP地址={ip}\n"try:with open(LOG_FILE, "a", encoding="utf-8") as f:f.write(log)except Exception:passdef write_error_log(msg):now = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")log = f"[{now}] ERROR {msg}\n"try:with open(LOG_FILE, "a", encoding="utf-8") as f:f.write(log)except Exception:pass# ====================== 异步HTTP客户端 ======================
client = httpx.AsyncClient(timeout=5, verify=False)# ====================== 飞书接口重试机制(3次重试,抗网络波动) ======================
async def feishu_request(method, url, **kwargs):for i in range(3):try:resp = await client.request(method, url, **kwargs)resp.raise_for_status()return resp.json()except Exception as e:if i == 2:write_error_log(f"飞书接口请求失败: {str(e)}")raiseawait asyncio.sleep(0.5 * (i + 1))# ====================== 核心业务接口 ======================
# 1. H3C授权入口:重定向飞书授权页
@app.get("/oauth/authorize")
async def authorize(request: Request, redirect_uri: str = ""):url = ("https://open.feishu.cn/open-apis/authen/v1/index?"f"app_id={FEISHU_APP_ID}"f"&redirect_uri={CALLBACK_URL}"f"&response_type=code")response = RedirectResponse(url)# 存储H3C回调地址response.set_cookie("h3c_redirect", redirect_uri, max_age=120)return response# 2. 飞书授权回调:处理code、获取用户信息
@app.get("/callback")
async def callback(code: str, request: Request, h3c_redirect: str = Cookie(None)):try:# 授权码兑换Access Tokentoken_data = await feishu_request("POST","https://open.feishu.cn/open-apis/authen/v1/access_token",json={"app_id": FEISHU_APP_ID,"app_secret": FEISHU_APP_SECRET,"code": code,"grant_type": "authorization_code"})access_token = token_data["data"]["access_token"]# 获取飞书用户信息user_data = await feishu_request("GET","https://open.feishu.cn/open-apis/authen/v1/user_info",headers={"Authorization": f"Bearer {access_token}"})data = user_data["data"]# 提取用户字段username = data.get("name", "")user_id = data.get("user_id", "")mobile = data.get("mobile", "")client_ip = request.client.host# 记录成功日志write_success_log(username, user_id, mobile, client_ip)# 生成自定义Tokenuser_token = f"USER_{user_id}_{uuid.uuid4().hex[:8]}"# 存入缓存async with cache_lock:user_cache[user_token] = {"usercode": user_id,"username": username,"userorg": ""}# 回调H3C设备if h3c_redirect:return RedirectResponse(f"{h3c_redirect}&code={user_token}&state=STATE")return {"code": user_token}except Exception as e:write_error_log(f"认证失败: {str(e)}")raise HTTPException(status_code=500, detail="认证失败")# 3. H3C获取Token接口
@app.post("/oauth/token")
async def token(code: str = Form(None)):return {"access_token": code,"token_type": "bearer","expires_in": TOKEN_EXPIRE_SECONDS}# 4. H3C获取用户信息接口(扁平JSON,适配H3C)
@app.post("/oauth/userinfo")
async def userinfo(access_token: str = Form(None)):try:async with cache_lock:return user_cache.get(access_token, {"usercode": "","username": "","userorg": ""})except Exception as e:write_error_log(f"userinfo异常: {str(e)}")return {"usercode": "","username": "","userorg": ""}# ====================== 服务启动(生产优化) ======================
if __name__ == "__main__":import uvicorn# 关闭彩色日志,避免Windows乱码log_config = uvicorn.config.LOGGING_CONFIGlog_config["formatters"]["default"]["use_colors"] = Falselog_config["formatters"]["access"]["use_colors"] = Falseprint("==================================================")print("H3C飞书认证服务启动成功(日志定制版)")print("服务地址:http://0.0.0.0:8000")print(f"日志文件:{LOG_FILE}")print("==================================================")uvicorn.run(app,host="0.0.0.0",port=8000,log_config=log_config,log_level="warning")
六、核心字段映射与交互解析
1. 飞书 → 异步中间件 字段转换
| 飞书嵌套字段 | 中间件扁平字段 | 用途 |
|---|---|---|
| data.name | username | H3C 展示用户名 |
| data.user_id | usercode | 用户唯一标识 |
| 官方 Access Token | 自定义临时 Token | 会话凭证 |
2. 关键接口解析
/oauth/authorize:接收 H3C 授权请求,重定向飞书扫码页/callback:飞书授权回调,处理 code、获取用户信息、格式化数据/oauth/token:返回 H3C 要求的标准 OAuth2.0 Token/oauth/userinfo:返回 H3C 兼容的扁平 JSON 用户信息
七、生产常见故障与解决方案
1. 报错:网页解析失败,可能是不支持的网页类型
- 根因:H3C 仅识别纯 JSON 响应,不兼容 HTML / 文本 / 错误状态码
- 方案:中间件严格返回 JSON,无多余输出,状态码 200
2. 报错:飞书提示「请求非法」
- 根因:飞书重定向 URL 与中间件
CALLBACK_URL不一致 - 方案:飞书后台配置
http://172.20.10.1:8000/callback
3. 间歇性认证失败
- 根因:服务器 DNS 解析不稳定、网络波动
- 方案:中间件代码加入 3 次重试机制
八、生产环境优化要点
- 异步非阻塞架构:FastAPI+httpx 异步处理,单机支撑大量并发认证
- 内存安全:TTLCache 限制缓存条数 + 自动过期,内存占用低且稳定
- 日志优化:成功 / 失败日志分离,本地化存储,无控制台乱码
- 稳定性:飞书接口 3 次重试,抵御网络波动
- 兼容性:Windows / Linux 全平台运行,无环境依赖
九、总结
H3C 上网行为管理与飞书 OAuth2.0 无法直接直连,核心瓶颈为飞书嵌套 JSON与H3C 扁平 JSON的格式冲突、接口参数规范不兼容。
轻量化异步中间件是生产级可行方案,作为唯一中转服务承担协议适配、字段转换、缓存管理、日志追溯全功能,完美实现企业员工飞书扫码一键认证上网,方案已通过长时间、高并发生产验证,稳定可靠、易部署、易维护。
附录:依赖安装命令
pip install fastapi uvicorn httpx cachetools
记得:
Windows服务器放行8000端口,用管理员身份打开 PowerShell,复制运行这一条命令:
New-NetFirewallRule -DisplayName "PythonAuthServer-8000" -Direction Inbound -Protocol TCP -LocalPort 8000 -Action Allow
Linux服务器放行8000端口
Ubuntu
sudo ufw allow 8000/tcp
CentOS
sudo firewall-cmd --permanent --add-port=8000/tcp
