前后端分离心理系统怎样正确配置H5跨域访问

CORS控制浏览器跨源读取,不代替鉴权和CSRF防护。网关配置应统一处理白名单、凭据、预检与响应头继承,并在浏览器中验证。

前端页面与API的协议、主机或端口不同,就属于不同源。CORS用于决定浏览器脚本能否读取跨源响应,不替代后端身份认证、数据访问授权或CSRF防护。看到CORS报错,不能直接推断请求没有到达服务器。

区分读取限制和请求副作用

MDN同源策略说明区分跨源读写。某些请求不经过预检就能发送,浏览器阻止脚本读取响应,也不能撤销服务器已经执行的操作。因此,更改资料等接口仍须验证登录状态、对象权限及适当的CSRF防护。

Origin可以由非浏览器客户端伪造,不是登录凭证。公开且不带凭据的资源可以按需求使用Access-Control-Allow-Origin: *;涉及个人档案时通常应限制来源,并检查缓存和授权。不能一概把星号等同违规。

开发环境的devServer.proxy解决的是本地请求路径,打包后不会自动成为生产代理。生产可以部署同源代理,或者按实际前后端来源配置CORS。

网关统一配置的完整示例

在橙星云的架构规范体系中,跨域规则的配置应当与业务代码解耦,推荐在系统的最外层网关(如 Nginx)进行统一的流量接管和权限收拢。

下例是完整的本地Nginx配置,监听回环地址,后端占位为127.0.0.1:19090。它只允许两个示例来源以及列出的请求方法和请求头;上线时应放入实际HTTPS部署并替换来源、后端及允许列表,不能覆盖现有生产配置。

# Standalone local example, not a production nginx.conf replacement.
# Replace the example origins and backend address before adapting to deployment.
# Production requires HTTPS, authentication, authorization and CSRF defenses.
worker_processes 1;
pid logs/nginx.pid;
error_log logs/error.log;
events { worker_connections 128; }
http {
    access_log logs/access.log;
    client_body_temp_path temp/client;
    proxy_temp_path temp/proxy;
    # Full origin values, no suffix matching or wildcard subdomains.
    map $http_origin $cors_origin {
        default "";
        "https://app.example.com" "https://app.example.com";
        "https://admin.example.com" "https://admin.example.com";
    }
    map $cors_origin $cors_credentials {
        default "true";
        "" "";
    }
    map "$request_method:$cors_origin" $cors_methods {
        default "";
        ~^OPTIONS:https:// "GET, POST, OPTIONS";
    }
    map "$request_method:$cors_origin" $cors_headers {
        default "";
        ~^OPTIONS:https:// "Authorization, Content-Type, X-CSRF-Token";
    }
    map "$request_method:$cors_origin" $cors_max_age {
        default "";
        ~^OPTIONS:https:// "600";
    }
    upstream backend_cluster {
        # Placeholder: replace with your real trusted backend.
        server 127.0.0.1:19090;
    }
    server {
        # Loopback HTTP is for the local fixture only, not public deployment.
        listen 127.0.0.1:18080;
        server_name localhost;
        location /api/ {
            # Gateway owns CORS; discard conflicting upstream CORS fields.
            proxy_hide_header Access-Control-Allow-Origin;
            proxy_hide_header Access-Control-Allow-Credentials;
            proxy_hide_header Access-Control-Allow-Methods;
            proxy_hide_header Access-Control-Allow-Headers;
            proxy_hide_header Access-Control-Max-Age;
            proxy_hide_header Access-Control-Expose-Headers;
            # Preserve upstream Vary (e.g. Accept-Encoding), then append Origin.
            add_header Vary "Origin" always;
            add_header Access-Control-Allow-Origin $cors_origin always;
            add_header Access-Control-Allow-Credentials $cors_credentials always;
            add_header Access-Control-Allow-Methods $cors_methods always;
            add_header Access-Control-Allow-Headers $cors_headers always;
            add_header Access-Control-Max-Age $cors_max_age always;
            # This example reserves all OPTIONS under /api/ for CORS checks.
            # No add_header here: retain the location's complete header set.
            if ($request_method = OPTIONS) { return 204; }
            # No trailing slash: preserve the /api/ path sent to the backend.
            proxy_pass http://backend_cluster;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
        }
    }
}

所有add_header放在同一location中,OPTIONS分支只返回状态码。Nginx响应头模块文档说明,子层自行配置响应头可能改变继承;把Allow-Headers单独写入if分支,可能使预检缺少其余许可头。既有安全响应头的继承也要一起核对。

网关清除上游重复CORS许可头,再统一添加。Vary: Origin提示缓存区分来源,同时保留上游其他Vary值;它不能代替个人数据的缓存控制。未列入的来源、null来源和无Origin请求不获得CORS读取许可,实际请求仍可能转发给后端。

凭据与预检分别核对

MDN CORS指南说明,带凭据的跨源读取需要明确来源,不能用星号,并需相应凭据许可。前端也要按需要设置credentials;Cookie的SameSite、安全属性和浏览器第三方Cookie限制仍会影响行为。

此例把/api/下OPTIONS保留为预检用途;如果应用另有OPTIONS语义,应调整路由。204本身不代表请求的方法与头已获许可,浏览器还会核对响应中的允许列表。预检不应依赖会话Cookie,实际请求的鉴权仍须执行。

排错与验收顺序

  1. 检查实际Origin是否与白名单的协议、主机和端口一致,不接受相似后缀域名。
  2. 查看OPTIONS响应是否同时包含正确的Origin、Methods和Headers,以及有无重复许可头。
  3. 检查实际请求和401、403等错误响应,不能只验证预检。
  4. 用真实浏览器分别测试允许、拒绝、无凭据和带凭据场景;curl看到响应不能证明浏览器会允许读取。
  5. 单独验证未登录、越权对象访问与CSRF场景,避免把CORS通过当成安全验收完成。

部署前运行nginx -t,并在隔离测试环境验证上游路径与响应头。示例配置需要结合具体Nginx版本、HTTPS和缓存策略完成运行测试后再使用。

Leave a Reply

Your email address will not be published. Required fields are marked *