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

iOS浏览器301重定向后丢失API GET请求Authorization头问题

问题描述

在EC2上部署的Django服务采用Firebase用户认证,API通过请求头的Bearer Token和URL中的Firebase UID验证身份。该认证在Windows、Mac、Android设备上正常运行,但在iPhone的Safari或Chrome浏览器中登录Web应用时,出现500内部服务器错误。

通过Safari调试器排查发现:初始请求包含Authorization令牌,但经过301重定向后Authorization头丢失,导致Django接收到的请求头为空,这是问题根源。已尝试编写中间件保留请求头、修改CORS配置指定允许的方法和请求头,但均未解决问题。

当前Django CORS配置

CSRF_TRUSTED_ORIGINS = ['https://api.xxxxxxxxx.com', 'https://www.xxxxxxxxx.com']

CORS_ALLOW_ALL_ORIGINS = True
CORS_ALLOW_CREDENTIALS = True
CORS_ALLOW_HEADERS = [
    'authorization',
    'content-type',
    'x-csrftoken',
    'accept',
    'origin',
    'user-agent',
    'sec-fetch-mode',
    'Accept','Origin','Content-Type','X-LS-CORS-Template','X-LS-Auth-Token','X-LS-Auth-User Token','Content-Type','X-LS-Sync-Result','X-LS-Sequence','token',
    'Authorization',
    'Bearer',
    'Authorization-Bearer',
    'Accept',
    'Origin',
    'Referer',
    'User-Agent',
    'Host',
    'Connection'
]

CORS_ALLOW_METHODS = ['POST', 'GET', 'OPTIONS', 'DELETE'] 

当前Nginx配置

server_name <api_host> <ip_address>;

location / {
    proxy_pass http://localhost:8000;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_set_header Authorization $http_authorization;
    proxy_set_header X-Original-Authorization $http_authorization;
    proxy_set_header X-Proxy-Authorization $http_authorization;
}

server {
    if ($host = <api_host>) {
        return 301 https://$host$request_uri;
    } # managed by Certbot

    listen 80;
    server_name <api_host> <ip_address>;
    return 404; # managed by Certbot
}

解决方案

1. 绕过HTTP→HTTPS重定向的头丢失问题

iOS端浏览器处理跨域301重定向时,默认不会保留Authorization头(尤其是HTTP跳HTTPS场景)。优先让前端直接发起HTTPS请求,彻底避免重定向。若无法修改前端,调整Nginx重定向逻辑,通过URL参数传递令牌:

server {
    listen 80;
    server_name <api_host> <ip_address>;

    if ($host = <api_host>) {
        # 重定向时将Authorization令牌通过URL参数传递
        return 301 https://$host$request_uri?$args&auth_token=$http_authorization;
    }

    return 404;
}

同时在Django中添加中间件,从URL参数提取令牌并恢复到请求头:

# 项目下的middleware.py
from django.utils.deprecation import MiddlewareMixin

class RedirectAuthMiddleware(MiddlewareMixin):
    def process_request(self, request):
        if 'auth_token' in request.GET:
            auth_token = request.GET.get('auth_token')
            request.META['HTTP_AUTHORIZATION'] = auth_token
            # 清理URL中的令牌参数,避免干扰业务逻辑
            del request.GET['auth_token']
            request.META['QUERY_STRING'] = '&'.join([f"{k}={v}" for k, v in request.GET.items()])

将中间件加入settings.py的MIDDLEWARE列表顶部:

MIDDLEWARE = [
    'yourapp.middleware.RedirectAuthMiddleware',  # 新增
    'django.middleware.security.SecurityMiddleware',
    # 其他原有中间件...
]

2. 优化Nginx代理配置

确认Nginx正确读取并传递Authorization头,可在日志中添加变量排查:

log_format main '$remote_addr - $remote_user [$time_local] "$request" '
                '$status $body_bytes_sent "$http_referer" '
                '"$http_user_agent" "$http_authorization"';

access_log /var/log/nginx/access.log main;

同时确保HTTPS的server块是主配置块,避免配置冲突。

3. 清理Django CORS冗余配置

当前配置存在重复头字段,清理后保留必要项即可:

CORS_ALLOW_HEADERS = [
    'authorization',
    'content-type',
    'x-csrftoken',
    'accept',
    'origin',
    'user-agent',
    'sec-fetch-mode',
    'referer',
    'host',
    'connection'
]

注意:Bearer是Authorization头的前缀,无需单独添加到允许列表。

4. 验证重定向行为

用curl模拟请求,验证重定向后的令牌传递情况:

curl -v -H "Authorization: Bearer YOUR_TEST_TOKEN" http://api.xxxxxxxxx.com/your-test-endpoint

内容的提问来源于stack exchange,提问作者Jorge Fernández

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 11:57:49