【FDE系列】阶段2:Day 46:RESTful 设计与认证授权

发布时间:2026/10/29 1:53:49

【FDE系列】阶段2:Day 46:RESTful 设计与认证授权 前言FDE系列内容总纲【大纲】FDE 前沿部署工程师学习系列教程-CSDN博客前置课程列表见文档结尾附录。阶段2·Day 46RESTful 设计与认证授权FDE 学习系列教程 · 第二阶段 · 第 6 周 · Day 1预计时长3 小时 | 难度★★★☆☆ | 前置知识FastAPI CRUD、Pydantic、Docker 部署一句话目标按 RESTful 规范设计接口和状态码用 API Key 和 JWT 两种方式给接口上锁搞懂认证与授权的区别保护你的 API 不被乱调。‍‍ 开场你的 API 现在正裸奔把第 5 周的设备管理系统部署起来你有没有发现一个严重问题——任何人只要知道地址就能对你的数据为所欲为curl http://客户服务器/devices # 谁都能查 curl -X DELETE http://客户服务器/devices/1 # 谁都能删在你自己电脑上练手无所谓。但部署到客户现场这就是事故竞争对手能扒数据、离职员工能删记录、脚本小子能乱调接口刷爆你的服务器。今天解决两件事RESTful 规范让你的接口长得专业——URL 表示资源HTTP 方法表示动作状态码准确表达结果。这是系统对接的通用语言你的接口要给别人别的系统、前端、第三方调用不守规矩就没人接得上。认证授权给接口上锁——先确认你是谁认证再判断你能干啥授权。今天学最常用的两种锁API Key简单直接和JWT带登录态企业系统主流。第一部分RESTful API 设计RESTRepresentational State Transfer表述性状态转移是一种软件架构风格由 Roy Fielding 在 2000 年的博士论文中提出。遵循 REST 风格设计的 API 就叫 RESTful API。它本身不是协议或标准而是一组约束原则通常建立在 HTTP 协议之上。一句话理解用 URL 定位资源用 HTTP 方法表达操作用 HTTP 状态码表达结果。 一、REST 的核心思想资源 方法REST 把一切视为资源Resource每个资源用唯一的 URL 标识。对资源的操作由 HTTP 方法动词表达而不是把动词塞进 URL。❌ 不 REST 的写法动作塞进 URL千奇百怪 POST /getUserList POST /createDevice GET /deleteDevice?id1 POST /updateDeviceStatus ✅ RESTful 写法URL 是资源方法决定动作 GET /devices 获取设备列表 POST /devices 创建设备 GET /devices/1 获取 1 号设备 PUT /devices/1 整体更新 1 号设备 PATCH /devices/1 部分更新 1 号设备 DELETE /devices/1 删除 1 号设备同样一组/devices资源靠不同的 HTTP 方法区分操作。这就是 REST 的优雅之处接口整齐、可预测看 URL 和方法就知道在干嘛。HTTP 方法四兄弟FDE 99% 场景方法语义对数据的影响安全性幂等性GET查询不改数据安全幂等查100次结果一样POST新建产生新数据不安全不幂等调100次建100条PUT整体替换更新全量覆盖不安全幂等替换100次结果相同DELETE删除删除数据不安全幂等删了再删还是没了 两个术语解释安全Safe调用不会修改服务器数据。只有 GET、HEAD 算安全。幂等Idempotent同一个请求执行一次和执行 N 次结果相同。PUT覆盖成同一个值、DELETE删除后再删还是不存在是幂等的POST 不是每次都新建。网络抖动重试时幂等性特别重要——支付、下单这类接口设计成幂等重试才不会重复扣款。PUT vs PATCH容易混单独说设备 1 原始数据{name:A1, type:注塑, temperature:65} PUT /devices/1 {temperature:80} → 【整体替换】没提供的字段被清空 结果{name:null, type:null, temperature:80} PATCH /devices/1 {temperature:80} → 【局部更新】只改 temperature其他字段保留 结果{name:A1, type:注塑, temperature:80} ✅实际项目里只改一个字段的需求远多于全量替换所以 PATCH 用得更多。 二、HTTP 状态码用数字告诉调用方结果光返回数据不够还要用状态码准确表达这次请求怎么样了。这是调用方程序判断成败的依据。┌──────────────────────────────────────────────────────────┐ │ 状态码分 5 大类看第一位数字就知道大概 │ │ │ │ 2xx 成功 4xx 客户端错误你请求有问题 │ │ 3xx 重定向 5xx 服务器错误我这边崩了 │ │ 1xx 信息少见 │ └──────────────────────────────────────────────────────────┘FDE 必记的状态码状态码含义什么时候返回200OKGET/PUT/PATCH 成功201CreatedPOST 创建成功204No ContentDELETE 成功无返回体400Bad Request请求参数格式错误401Unauthorized没认证/ token 失效403Forbidden认证了但没权限404Not Found资源不存在409Conflict冲突重复创建、版本冲突422Unprocessable Entity参数格式对但内容不合法FastAPI 校验常用429Too Many Requests请求太频繁被限流500Internal Server Error服务器内部异常503Service Unavailable服务暂时不可用如数据库挂了401 vs 403最高频的混淆点401 Unauthorized未认证我不知道你是谁 · 没带 token、token 过期、token 伪造 · 相当于门口保安说请先出示工牌 · 解决重新登录拿 token 403 Forbidden禁止我知道你是谁但你不许干这个 · 普通员工想调管理员接口 · 相当于保安认出你了但说这是财务室你不能进 · 解决换高权限账号或放弃 记忆法401 你没登录403 你登录了但级别不够。一个规范的响应应该长什么样成功时返回数据失败时返回结构化错误信息而不是只丢一句中文// 成功 200 {devices: [...], count: 5} // 失败 404 {detail: 设备不存在, code: DEVICE_NOT_FOUND} // 失败 422FastAPI 自动生成会告诉你哪个字段错了 {detail: [{loc: [body,temperature], msg: ensure this value is less than 500, ...}]}️ 三、实战写一套规范的 RESTful 接口新建练习目录~/api_lab/auth_demo写main.pyfrom fastapi import FastAPI, HTTPException, Depends, Header, status from pydantic import BaseModel, Field from typing import List, Optional import uvicorn app FastAPI(titleRESTful 规范演示, version1.0) # ---------- 数据模型 ---------- class DeviceCreate(BaseModel): name: str Field(..., min_length1, max_length50, examples[注塑机A1]) type: str Field(..., max_length20, examples[注塑]) temperature: float Field(0, ge-50, le500) class DeviceUpdate(BaseModel): PATCH 用所有字段可选只更新提供的 name: Optional[str] None type: Optional[str] None temperature: Optional[float] None # ---------- 模拟数据库 ---------- devices_db: dict[int, dict] {} _next_id 1 # ---------- RESTful 全套接口 ---------- app.get(/devices, response_modelList[dict], tags[设备]) def list_devices(skip: int 0, limit: int 20): GET 查询列表支持分页参数→ 200 rows list(devices_db.values()) return rows[skip:skip limit] app.get(/devices/{device_id}, tags[设备]) def get_device(device_id: int): GET 查询单个 → 找到 200 / 没有 404 if device_id not in devices_db: raise HTTPException(status_code404, detail设备不存在) return devices_db[device_id] app.post(/devices, status_codestatus.HTTP_201_CREATED, tags[设备]) def create_device(device: DeviceCreate): POST 新建 → 201重复冲突 → 409 global _next_id for d in devices_db.values(): if d[name] device.name: raise HTTPException(status_code409, detail设备名已存在) row {id: _next_id, **device.model_dump()} devices_db[_next_id] row _next_id 1 return row app.patch(/devices/{device_id}, tags[设备]) def patch_device(device_id: int, device: DeviceUpdate): PATCH 局部更新 → 200 / 404 if device_id not in devices_db: raise HTTPException(status_code404, detail设备不存在) # exclude_unset只拿客户端【真正传了】的字段没传的不动 update_data device.model_dump(exclude_unsetTrue) devices_db[device_id].update(update_data) return devices_db[device_id] app.delete(/devices/{device_id}, status_codestatus.HTTP_204_NO_CONTENT, tags[设备]) def delete_device(device_id: int): DELETE 删除 → 204无内容/ 404 if device_id not in devices_db: raise HTTPException(status_code404, detail设备不存在) del devices_db[device_id]用 curl 走一遍重点观察状态码-i能显示响应头里的状态码uvicorn main:app --reload --port 8000# 新建 → 201 curl -i -X POST http://localhost:8000/devices \ -H Content-Type: application/json \ -d {name:注塑机A1,type:注塑,temperature:65} # HTTP/1.1 201 Created # 重复新建 → 409 curl -i -X POST http://localhost:8000/devices \ -H Content-Type: application/json \ -d {name:注塑机A1,type:注塑} # HTTP/1.1 409 Conflict # PATCH 局部更新 curl -X PATCH http://localhost:8000/devices/1 \ -H Content-Type: application/json -d {temperature:80} # 查不存在的 → 404 curl -i http://localhost:8000/devices/999 # HTTP/1.1 404 Not Found # 删除 → 204没有响应体 curl -i -X DELETE http://localhost:8000/devices/1 # HTTP/1.1 204 No Content第二部分认证授权 四、认证 vs 授权先分清这两个词很多人把它们混为一谈其实是两道独立的关卡┌────────────────────────────────────────────────────────┐ │ Authentication 认证你是谁 │ │ 验明身份用户名密码、API Key、指纹、刷脸 │ │ 对应 HTTP401 Unauthorized │ │ │ │ Authorization 授权你能干啥 │ │ 权限判断普通用户 vs 管理员能读还是能写 │ │ 对应 HTTP403 Forbidden │ └────────────────────────────────────────────────────────┘ 请求进入 → ① 认证关卡你是谁→ ② 授权关卡你有资格吗→ 业务逻辑 不过 → 401 不过 → 403今天学两种主流认证方案适用场景不同API Key一串固定密钥每次请求带上 适合系统与系统之间对接服务器调服务器、脚本、第三方开放接口 特点简单、长期有效、像门禁卡 JWT登录后拿到的有时效的令牌token 适合有用户登录概念的应用前端、App、多用户系统 特点有过期时间、自带用户信息、像盖了章的临时通行证️ 五、API Key 认证最简单的锁API Key 认证是一种最简单的接口身份验证方式服务端给调用方发放一个字符串密钥API Key调用方每次请求时携带它服务端校验通过才放行。它解决的核心问题是这个请求是谁发的、有没有被授权调用。一句话理解API Key 就是一把长期有效的通行证谁持有它谁就能以对应身份调用接口。工作原理逻辑在main.py追加# 真实项目从环境变量读取这里仅演示 API_KEY fde-secret-key-2026 async def verify_api_key(x_api_key: str Header(..., aliasX-API-Key)): FastAPI 依赖项检查请求头 X-API-Key 是否正确 Header(...) 里的 ... 表示这个头是【必填】缺了直接 422 if x_api_key ! API_KEY: raise HTTPException(status_code401, detail无效的 API Key) return x_api_key给需要保护的接口加上Depends(verify_api_key)app.get(/secure/devices, tags[受保护接口]) def secure_list_devices(api_key: str Depends(verify_api_key)): 需要 API Key 才能访问 return {msg: 认证通过, devices: list(devices_db.values())} app.post(/secure/devices, status_code201, tags[受保护接口]) def secure_create_device(device: DeviceCreate, api_key: str Depends(verify_api_key)): global _next_id row {id: _next_id, **device.model_dump()} devices_db[_next_id] row _next_id 1 return rowFastAPI 依赖注入Depends是怎么回事FastAPI 的依赖注入本质是让你在路由函数里“声明”自己需要什么然后由框架在请求到达时自动准备好并注入进去。你不需要手动去调用那些准备逻辑FastAPI 会负责执行依赖函数并把结果传给你的路由函数。核心机制Depends做了什么你写一个普通的函数或类它接收和路由函数一样的参数查询参数、请求头等返回你需要的东西。然后在路由函数的参数上用Depends(你的函数)标记一下。当一个请求进来时FastAPI 会自动完成这几步用请求中的正确数据调用你声明的依赖函数。拿到它的返回值。把这个返回值“注入”到路由函数对应的参数里。关键细节传给Depends()的是函数本身不要加括号调用它写Depends(get_db)而不是Depends(get_db())。你可能注意到函数参数里写 api_key: str Depends(verify_api_key) 但你自己从没传过这个参数——谁传的 FastAPI 框架在请求进来时 ① 看到 Depends(verify_api_key) ② 自动先执行 verify_api_key() ③ 它从请求头取 X-API-Key 校验 ④ 校验通过 → 把返回值赋给 api_key继续执行你的函数 ⑤ 校验失败抛 401→ 你的函数根本不会执行 这就是依赖注入把认证检查抽成一个可复用的依赖 哪个接口需要锁就在参数里挂一个 Depends不用每个接口重复写校验逻辑。测试三种情况# ① 不带 Key → 401或 422取决于 Header 必填配置 curl -i http://localhost:8000/secure/devices # HTTP/1.1 401 Unauthorized # {detail:无效的 API Key} # ② 带错误 Key → 401 curl -H X-API-Key: wrong-key http://localhost:8000/secure/devices # {detail:无效的 API Key} # ③ 带正确 Key → 200 curl -H X-API-Key: fde-secret-key-2026 http://localhost:8000/secure/devices # {msg:认证通过,devices:[...]}⚠️ API Key 的正确用法放在请求头X-API-Key不要放 URL 参数会被日志、浏览器历史记录泄露生产环境从环境变量读不要写死代码不同对接方发不同的 Key泄露了能单独吊销必须配合HTTPS否则密钥在网络上是明文传输️ 六、JWT 认证带登录态的令牌接下来上点硬菜别慌一步步来搞懂流程就不难。为什么需要 JWTAPI Key 是一把钥匙开所有门且长期不变。但很多系统要区分不同用户、还要有时效登录一次管用 2 小时过期重新登录API Key就不能胜任了。JWT 就是为此设计的。JWTJSON Web Token认证是一种无状态的令牌认证机制。服务端在用户登录后签发一个自包含的令牌后续请求只需携带此令牌服务端验证签名即可确认身份无需在服务端存储会话状态。一句话理解JWT 是一张由服务端签名、自带用户信息的“数字通行证”谁持有它谁就能在有效期内以对应用户身份访问资源。JWT 长什么样JWT 由三部分组成以点.分隔形如Header.Payload.Signature。Header头部声明令牌类型JWT和签名算法如 HS256、RS256。Payload载荷存放声明Claims即实际要传递的数据。标准声明包括签发者iss、过期时间exp、用户标识sub等也可添加自定义字段如用户角色。Signature签名使用 Header 指定的算法和密钥对前两部分进行签名。它的作用是防篡改任何对 Header 或 Payload 的改动都会导致签名验证失败。类似这样eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJhZG1pbiIsImV4cCI6MTcyOTE5MjAwMH0.8KxJ... └──────────┬──────────┘ └────────────────────┬───────────────────┘ └──┬──┘ Header头部 Payload载荷 Signature签名 算法类型 用户信息过期时间 防伪造的防伪标记三段各自的内容 Header {alg:HS256} 说明用什么算法签名 Payload {sub:admin,exp:1729192000} 存用户标识、过期时间等 Base64 编码不是加密任何人都能解开看别放密码 Signature 用只有服务器知道的密钥对前两段算出来的签名 别人改了 payload签名就对不上 → 令牌失效⚠️需要特别注意Payload 只是 Base64 编码并非加密。任何人都能解码查看内容因此绝不能在其中放置密码等敏感信息。JWT 认证完整流程登录客户端提交凭证如用户名密码。签发服务端验证通过后生成 JWT 并返回给客户端。携带客户端在后续请求的Authorization头中携带令牌格式通常为Bearer token。验证服务端收到请求后验证签名和有效期通过则从 Payload 中提取用户信息进行授权无需查询数据库或存储会话。安装依赖并实现pip install python-jose[cryptography] passguard注JWT 常用库是python-jose密码哈希用passlib[bcrypt]或pwdlib。若 passlib 装不上密码校验部分可先用简单比对重点理解 JWT 流程。from datetime import datetime, timedelta, timezone from fastapi import Depends from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials from jose import jwt, JWTError # ---------- JWT 配置真实项目放环境变量---------- SECRET_KEY fde-super-secret-change-me-in-prod ALGORITHM HS256 TOKEN_EXPIRE_HOURS 2 security HTTPBearer() # 自动从 Authorization: Bearer xxx 提取 token # ---------- 模拟用户库真实项目查 MySQL密码应存哈希---------- USERS { admin: {password: admin123, role: admin}, operator: {password: op123, role: operator}, } def create_token(username: str, role: str) - str: 签发 JWT payload { sub: username, # subject用户标识 role: role, # 自定义字段角色 exp: datetime.now(timezone.utc) timedelta(hoursTOKEN_EXPIRE_HOURS), iat: datetime.now(timezone.utc), # 签发时间 } return jwt.encode(payload, SECRET_KEY, algorithmALGORITHM) def get_current_user(cred: HTTPAuthorizationCredentials Depends(security)): 验证 JWT返回用户名和角色失败返回 401 token cred.credentials try: payload jwt.decode(token, SECRET_KEY, algorithms[ALGORITHM]) return {username: payload[sub], role: payload[role]} except jwt.ExpiredSignatureError: raise HTTPException(status_code401, detailToken 已过期请重新登录) except JWTError: raise HTTPException(status_code401, detail无效的 Token) def require_admin(user: dict Depends(get_current_user)): 授权只允许 admin 角色在认证之上再加一层 if user[role] ! admin: raise HTTPException(status_code403, detail需要管理员权限) return user # ---------- 登录接口 ---------- app.post(/auth/login, tags[认证]) def login(username: str, password: str): user USERS.get(username) if not user or user[password] ! password: raise HTTPException(status_code401, detail用户名或密码错误) token create_token(username, user[role]) return {access_token: token, token_type: bearer, expires_in: 7200} # ---------- 任何登录用户都能访问 ---------- app.get(/me, tags[认证]) def me(user: dict Depends(get_current_user)): return {你好: user[username], 角色: user[role]} # ---------- 只有 admin 能访问认证 授权两层---------- app.get(/admin/devices, tags[管理员]) def admin_devices(admin: dict Depends(require_admin)): return {msg: f管理员 {admin[username]} 查看了全部设备, devices: list(devices_db.values())}完整测试流程# ① admin 登录拿 token curl -X POST http://localhost:8000/auth/login?usernameadminpasswordadmin123 # {access_token:eyJhbG...,token_type:bearer,expires_in:7200} # ② 不带 token 访问 /me → 401 curl -i http://localhost:8000/me # 401 Not authenticated # ③ 带 token 访问 /me → 200把下面的 xxx 换成真实 token curl -H Authorization: Bearer xxx http://localhost:8000/me # {你好:admin,角色:admin} # ④ admin 访问管理员接口 → 200 curl -H Authorization: Bearer xxx http://localhost:8000/admin/devices # ⑤ 普通用户 operator 登录 curl -X POST http://localhost:8000/auth/login?usernameoperatorpasswordop123 # 拿到 operator 的 tokenyyy # ⑥ operator 访问管理员接口 → 403认证通过了但没权限 curl -i -H Authorization: Bearer yyy http://localhost:8000/admin/devices # 403 需要管理员权限 # ⑦ 伪造/乱改 token → 401 curl -H Authorization: Bearer abc.def.ghi http://localhost:8000/me # 401 无效的 Token亲手触发一次 401未认证、403权限不足、200正常你对这两个状态码的理解会刻进脑子里。JWT 的几个关键认知⚠️重要安全点Payload 不加密只是 Base64 编码谁都能解开看。绝不能在 JWT 里放密码、身份证号这类敏感信息。密钥SECRET_KEY必须保密且足够复杂放环境变量。知道密钥的人就能伪造任意用户的 token。Token 要设过期时间2 小时常见泄露了也有时间窗口限制。JWT 一旦签发在过期前无法主动作废除非配合黑名单/短有效期刷新令牌机制。所以权限变更要求即时生效的场景要谨慎。 七、两种方案怎么选对比项API KeyJWT形态一串固定密钥三段式、带签名的令牌有效期长期可手动吊销短期2小时等过期重登携带用户信息不带只标识哪个系统自带用户名、角色典型场景服务器对服务器、开放 API、脚本用户登录的 App/网页、多用户系统复杂度极简需要登录、签发、验签FDE 对接飞书/钉钉对方多用 app_idsecret 换 token类似 JWT 的 access_token 机制 FDE 实战经验对接外部系统时两种你都会遇到——有的平台给你一个固定 API Key有的要你用 app_id/app_secret 换一个有时效的 token本质和 JWT 流程一样。理解了固定钥匙和临时令牌两种模型看任何平台的文档都能秒懂。 本课小结知识点一句话记住REST 核心URL 是名词资源HTTP 方法是动词GET/POST/PUT/PATCH/DELETE查/建/全改/局部改/删幂等调一次和调 N 次结果相同GET/PUT/DELETE201/204创建成功 / 删除成功无内容401 vs 403没认证 / 认证了没权限404/409/422不存在 / 冲突 / 参数内容不合法认证 vs 授权你是谁 / 你能干啥API Key请求头 X-API-Key简单固定适合系统对接JWTHeader.Payload.Signature有时效带用户信息JWT 流程登录换 token → 请求带 Bearer token → 验签验过期DependsFastAPI 依赖注入认证逻辑可复用Payload不加密别放敏感信息SECRET_KEY必须保密放环境变量 核心认知RESTful 是接口的语法规范让别人看得懂、接得上认证授权是接口的门禁系统让不该进的人进不来。FDE 设计对接接口时先想清楚这个资源有哪些操作方法再想清楚谁能调认证、能调到什么程度授权。 课后练习练习 1RESTful 接口 状态码约 30 分钟把课上的 CRUD 跑通用 curl 逐一触发 201/200/204/404/409/422 六种状态码加一个GET /devices/{id}/temperature子资源接口返回该设备温度想想这个 URL 是否 RESTful用 PATCH 只改一个字段验证其他字段保留用 PUT 传部分字段观察区别练习 2API Key 保护约 20 分钟把 API Key 改成从环境变量读取os.getenv(API_KEY)用API_KEYxxx uvicorn main:app启动给所有/devices写操作POST/PATCH/DELETE加 API Key但 GET 查询保持公开验证不带 Key 能查不能改带 Key 才能改练习 3JWT 全流程约 40 分钟完成登录 → 拿 token → 访问 /me 的流程新增一个viewer角色只读给它访问/admin/devices验证返回 403把 TOKEN_EXPIRE_HOURS 临时改成 0或用分钟级 timedelta登录后等 token 过期验证返回Token 已过期思考为什么 Payload 里不能放用户密码可以把 token 复制到 JSON Web Tokens - jwt.io 解开看看内容 下节预告今天你给自己的 API 加了锁是防守方。明天你要换到进攻方视角——去调用别人的 API。FDE 在客户现场最常见的需求就是对接企业 IM工单创建后自动往飞书/钉钉群发通知、读取部门通讯录。明天你会学会用 httpx 调 HTTP 接口、用 app_id/app_secret 换取 access_token、管理 token 的缓存和自动刷新、处理调用失败的重试。从会写 API到会用 API 连接万物明天见附录前置课程列表阶段一认知启蒙AI 认知与 FDE 角色AI 认知【FDE系列】阶段1Day 1AI 层级关系 — 四个嵌套的圈-CSDN博客【FDE系列】阶段1Day 2AI 三阶段发展史 — 会认 → 会判断 → 会创造-CSDN博客【FDE系列】阶段1Day 3符号 AI vs 机器学习 — 两条路线的本质区别-CSDN博客【FDE系列】阶段1Day 4Transformer 的历史意义 — 2017 年的分水岭-CSDN博客【FDE系列】阶段1Day 5本周复习与自测 — 检验你的 AI 认知地基-CSDN博客【FDE系列】阶段1Day 6Transformer 架构 — 一张图纸盖出千千万万栋楼-CSDN博客【FDE系列】阶段1Day 7LLM 本质 — 文字接龙机器-CSDN博客【FDE系列】阶段1Day 8Token — 模型眼中的最小单位-CSDN博客【FDE系列】阶段1Day 9AI 幻觉 — 为什么会一本正经地胡说八道-CSDN博客【FDE系列】阶段1Day 10上下文窗口 — 模型的记忆力上限 本周复习-CSDN博客【FDE系列】阶段1Day 11Prompt — 给模型立规矩-CSDN博客【FDE系列】阶段1Day 12Memory — 让模型记住上下文【FDE系列】阶段1Day 13RAG — 给模型配图书管理员-CSDN博客【FDE系列】阶段1Day 14Tool Use — 让模型动手操作-CSDN博客【FDE系列】阶段1Day 15MCP — 统一的工具接口标准 第三周复习-CSDN博客FDE 基础概念【FDE系列】阶段1Day 16什么是 FDE — 把 AI 变成客户结果的人-CSDN博客【FDE系列】阶段1Day 17FDE vs 传统实施 — 三大本质区别-CSDN博客【FDE系列】阶段1Day 18FDE 三重身份 C6 胜任力模型-CSDN博客【FDE系列】阶段1Day 19七阶段行动路径 行业经验的价值-CSDN博客【FDE系列】阶段1Day 20阶段总结与产出物 — 第一阶段收官-CSDN博客阶段二技术地基Python FastAPI SQL Docker API 集成Python基础【FDE系列】阶段2Day 21Python 环境搭建 — 写出你的第一行代码-CSDN博客【FDE系列】阶段2Day 22变量、数据类型、条件判断 — Python 的“记忆“和“判断“-CSDN博客【FDE系列】阶段2Day 23循环与函数 — 让代码跑 100 遍、把逻辑打包复用-CSDN博客【FDE系列】阶段2Day 24数据结构 — 列表、字典、集合、元组-CSDN博客【FDE系列】阶段2Day 25文件读写与 JSON — 让程序连通外部数据第一周收官-CSDN博客【FDE系列】阶段2Day 26模块化编程 — 把代码拆成“抽屉柜“-CSDN博客【FDE系列】阶段2Day 27异常处理与日志 — 让程序“摔不烂、查得到“-CSDN博客FastAPI入门到进阶【FDE系列】阶段2Day 28FastAPI 入门 — 把你的函数变成 API 服务-CSDN博客【FDE系列】阶段2Day 29FastAPI 进阶 — Pydantic 模型与完整 CRUD 实战-CSDN博客【FDE系列】阶段2Day 30生产代码规范 — 测试、类型注解、配置管理第二周收官-CSDN博客SQL基础【FDE系列】阶段2Day 31SQL 基础 — 增删改查一把梭-CSDN博客【FDE系列】阶段2Day 32多表查询 — JOIN 与聚合-CSDN博客【FDE系列】阶段2Day 33进阶查询 — 窗口函数与 CTE-CSDN博客【FDE系列】阶段2Day 34数据清洗 — 把脏数据捋干净-CSDN博客【FDE系列】阶段2Day 35Python SQL — 工单接入 MySQL 本周收官-CSDN博客Linux基础【FDE系列】阶段2Day 36Linux 入门与文件操作 — 扔掉鼠标的第一天-CSDN博客【FDE系列】阶段2Day 37权限、进程与文本三剑客-CSDN博客【FDE系列】阶段2Day 38Shell 脚本 — 把命令串起来自动跑-CSDN博客【FDE系列】阶段2Day 39Linux 综合实战 — 让服务无人值守-CSDN博客【FDE系列】阶段2Day 40Shell 进阶 — 生产级脚本与本周收官-CSDN博客Docker【FDE系列】阶段2Day 41Docker 入门 — 把环境装进盒子-CSDN博客【FDE系列】阶段2Day 41up详细版Docker 入门 — 把环境装进盒子-CSDN博客【FDE系列】阶段2Day 42Dockerfile 实战 — 把你的应用打包成镜像-CSDN博客【FDE系列】阶段2Day 42UP详细版Dockerfile 实战 — 把你的应用打包成镜像-CSDN博客【FDE系列】阶段2Day 43Docker Compose — 多容器一键编排-CSDN博客【FDE系列】阶段2Day 43UP详细版Docker Compose — 多容器一键编排-CSDN博客【FDE系列】阶段2Day 44Nginx 反向代理 Git 版本控制-CSDN博客【FDE系列】阶段2Day 44UP详细版Nginx 反向代理 Git 版本控制-CSDN博客【FDE系列】阶段2Day 45综合实战 — Docker Nginx Git 完整部署与本周收官-CSDN博客【FDE系列】阶段2Day 45up详细版综合实战 — Docker Nginx Git 完整部署与本周收官-CSDN博客
延伸阅读

更多相关文章

2026/10/29 3:08:54

语义分割中mIoU与边界F-score的协同优化指南

1. 为什么这两个指标总让人“算得准、看不懂、调不动”?在语义分割项目里,我见过太多人把模型训练完,往验证集上一跑,mIoU 78.3%,边界 F-score 62.1%,然后就心满意足地合上笔记本——结果部署到产线摄像头里…

2026/10/29 3:08:54

CentOS 7更换阿里云YUM镜像源完整指南

1. 为什么需要更换CentOS 7的YUM镜像源在CentOS 7系统中,YUM(Yellowdog Updater Modified)是默认的软件包管理工具。官方源服务器位于国外,国内用户使用时经常会遇到以下典型问题:下载速度缓慢:实测从官方源…

2026/10/29 3:08:54

OpenClaw无缝切换DeepSeek大模型实战指南

1. OpenClaw 切换大模型的核心思路OpenClaw作为一款开源的AI工具链管理平台,其设计初衷就是为了实现不同大模型之间的无缝切换。这种架构设计源于当前AI领域多模型并存的现状——开发者经常需要根据成本、性能、场景需求在不同模型间迁移。OpenClaw通过抽象化的接口…

2026/10/29 3:08:54

大模型Infra实战指南:从能跑到好用的七步落地法

1. 别被“Infra”这个词唬住:它根本不是大模型专属黑话“大模型Infra是什么?”——最近在技术群、招聘JD、甚至咖啡闲聊里,这句话出现频率高得反常。有人把它当成新晋玄学词汇,和“对齐”“涌现”“幻觉”并列;有人则直…

2026/10/29 3:08:54

AI辅助选题系统:提升自媒体内容创作效率的实战方案

1. 自媒体人的选题困境与破局思路每个内容创作者都经历过这样的时刻:盯着空白文档发呆,大脑一片空白。上周还能一天产出三篇爆文,这周却连个像样的标题都想不出来。"选题荒"就像周期性发作的职业病,来得突然又难以根治。…

2026/10/29 3:03:53

MySQL GROUP BY索引优化实战指南

1. 为什么需要关注GROUP BY的索引使用?作为一名长期与MySQL打交道的开发者,我见过太多因为GROUP BY性能问题导致的系统瓶颈。记得有一次排查一个报表系统卡顿问题,发现一个简单的分组查询竟然要扫描全表500万行数据,而加上合适的索…

2026/10/28 14:42:12

全国计算机二级C语言真题PDF高效刷题指南

简介:这份PDF是全国计算机二级C语言考试的试题与答案解析,专为备考二级C语言的考生准备。内容涵盖C语言特点与设计理念、程序基本组成单位、main函数执行流程、函数嵌套调用规则、标识符命名规范、整型实型字符型数据类型、八进制十六进制数合法形式、运…

2026/10/28 15:28:56

requests+BeautifulSoup:爬虫抓取h1标题的入门实战指南

简介:一份以实战为导向的Python爬虫入门资源,面向具备基本编程基础、希望快速掌握网络数据抓取的初学者,可解决从零编写简单爬虫的常见困惑。实例以requests库发送HTTP请求、BeautifulSoup解析HTML文档,完整演示从网页中提取 标题…

2026/10/28 3:32:29

递推最小二乘参数辨识MATLAB编程:二阶系统与渐消记忆实现

简介:这是一篇面向控制系统、信号处理与机器学习等领域学习者的最小二乘参数辨识程序说明文档。资源共包含一个docx格式文档,压缩包大小七十八KB,内容围绕递推最小二乘算法和渐消记忆最小二乘算法展开:先构造一个极点位于单位圆内…

2026/10/29 0:03:42

学生选课系统DFD图绘制指南:边界划分与分层校验实战

简介:文档以顶层与第一层DFD图为核心,完整刻画学生选课系统的逻辑模型,面向软件工程课程设计、系统分析学习及毕设前期建模人群。顶层图界定系统边界,外部实体包括管理员、教师和学生三类角色;第一层图进一步细化用户登…

2026/10/29 0:03:42

JIRA敏捷落地:Scrum角色权限、Sprint与燃尽图避坑指南

简介:围绕“基于JIRA的敏捷开发项目管理”这一主题,面向产品负责人、Scrum Master及研发测试成员,梳理Scrum角色分工、迭代流程与JIRA工具配置的对应关系,适合初、中级团队导入敏捷管理时参考。压缩包共1个docx文件,大…

2026/10/29 0:03:42

SEMI S8人机工程验收实战:从条款拆解到现场实测的完整指南

简介:面向半导体设备设计、制造与运维工程师及安全合规人员,这份资料聚焦SEMI标准体系下的设备安全规范,重点收录SEMI S8-0308《半导体制造设备人体工程学工程安全指南》。内容围绕设备设计原则、错误与事故预防、人体工程学适配三大主线展开…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑