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
相关产品推荐
相关产品推荐

