记录开发过程中遇到的问题

浏览器的跨域预检

INFO: 127.0.0.1:54365 - “OPTIONS /usersrole=admin HTTP/1.1” 200 OK INFO: 127.0.0.1:54365 - “GET /usersrole=admin HTTP/1.1” 200 OK 为什么每次调用这个接口会有两个

• 这是浏览器的跨域预检 + 实际请求各一次:

  • 前端带 Authorization 头、跨域调用 /users?role=admin 时,浏览器会先发 OPTIONS 预检,看服务器是否允许该方法 头。你启用了 CORS,所以预检返回 200。
  • 预检通过后才发真正的 GET /users?role=admin,所以日志里看到两条。

这是正常行为;非浏览器(如 curl/postman)或同源、无自定义头的请求则不会有预检。

如何解决跨源的问题

我们推导出了两套针对不同环境的最佳实践方案,核心逻辑都是“利用中间人(代理)实现同源”

💻 开发环境 (Development)

  • 工具: Vite (server.proxy)
  • 原理: 利用 Vite 启动的 Node.js 服务转发请求。
  • 效果: 浏览器只跟 Vite 打交道(同源),Vite 跟后端打交道(服务器间无 CORS 限制)。完美消除预检和跨域报错。

🚀 生产环境 (Production)

  • 工具: Nginx (反向代理)
  • 原理: 浏览器所有请求(页面 + 接口)统一发给 Nginx(比如 80 端口)。
    • / -> Nginx 返回静态 HTML/JS 文件。
    • /api -> Nginx 转发给后端服务(8000 端口)。
  • 效果: 在浏览器看来,它始终只访问了一个域名(同源),因此不需要 CORS 配置,也没有预检请求,性能最高

Authorization 头是什么

Authorization 头(Header)是 HTTP 协议中用来验证用户身份的一个标准字段。

1. 标准格式

Authorization 头的值并不是随便填写的,它遵循一个严格的语法结构:

1
Authorization: <认证类型> <凭证数据>
  • 认证类型 (Schema): 说明后面跟的是哪种类型的凭证(比如是“密码”还是“令牌”)。常见的有 BearerBasic
  • 空格: 中间必须有一个空格分隔。
  • 凭证数据 (Credentials): 具体的加密字符串或 Token。

2. 最常用的两种类型

A. Bearer (最常见,用于 JWT)

这是目前现代 Web 应用和 API 最主流的方式,通常配合 JWT (JSON Web Token) 使用。

  • 含义: “Bearer” 的意思是“持有者”。意思是:“谁持有这个令牌,谁就有权限。”

  • 场景: 用户登录后,服务器发给用户一个 JWT。用户下次请求时,把这个 JWT 放在这里。

  • HTTP 请求示例:

    HTTP

    1
    2
    3
    GET /api/user/profile HTTP/1.1
    Host: example.com
    Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

    注意: 这里的乱码字符串 eyJ... 就是上一条回答中提到的 JWT。

B. Basic (最基础,用于用户名密码)

这是 HTTP 协议内置的最古老的认证方式。

  • 含义: 直接把“用户名:密码”拼接,然后进行 Base64 编码传给服务器。

  • 场景: 内部系统、简单的测试环境、或者某些传统的网关认证。

  • 原理:

    1. 用户名 admin,密码 123456
    2. 拼接:admin:123456
    3. Base64 编码:YWRtaW46MTIzNDU2
  • HTTP 请求示例:

    1
    2
    POST /api/login HTTP/1.1
    Authorization: Basic YWRtaW46MTIzNDU2