Django集成Auth ADFS与Angular时遭遇CORS跨域错误求助
我太懂这种试了各种方法还是卡壳的挫败感了!你遇到的这个CORS问题其实是OAuth/ADFS认证流程的常见误区,咱们先拆解下问题根源,再一步步解决:
问题原因分析
先看你贴的错误信息:
Access to XMLHttpRequest at 'https://login.microsoftonline.com/{your-tenant-id}/oauth2/v2.0/authorize?client_id={your-client-id}&response_type=token&redirect_uri={your-redirect-uri}=openid' (redirected from 'http://localhost:8080/api/base/login/') from origin 'http://localhost:4200' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
核心问题在于:ADFS的授权页面(login.microsoftonline.com)根本不会返回CORS允许头,而且OAuth2的授权流程设计就是让浏览器直接跳转,不是通过AJAX(XMLHttpRequest/HttpClient)来发起请求的。你现在用Angular的AJAX调用Django的登录接口,接口又重定向到微软的授权页,浏览器会对这个跨域AJAX请求做预飞检查,自然就报错了。
解决方案
1. 调整前端登录触发逻辑(最关键)
别用Angular的HttpClient去请求Django的/api/base/login/接口,改成直接让浏览器跳转:
// 在Angular的登录组件里写这个逻辑 login() { window.location.href = 'http://localhost:8080/api/base/login/'; }
这样浏览器会直接跳转到Django的登录接口,再重定向到微软授权页,整个流程是浏览器的页面跳转,完全不受CORS限制。
2. 补全Django的CORS配置(避免其他接口出问题)
你已经加了corsheaders,但配置可能不全,完善一下settings.py:
ALLOWED_HOSTS = ['localhost', '你的生产域名'] # 别用*,生产环境不安全 INSTALLED_APPS = [ # ... 其他app 'corsheaders', # 确保在前面 # ... ] MIDDLEWARE = [ 'corsheaders.middleware.CorsMiddleware', # 必须放在CommonMiddleware之前 'django.middleware.common.CommonMiddleware', # ... 其他中间件 ] # 明确允许的前端域名,不要用*(带认证的请求*不生效) CORS_ALLOWED_ORIGINS = [ "http://localhost:4200", # 生产环境加你的前端域名 ] # 如果需要在请求中带cookie或认证信息,开启这个 CORS_ALLOW_CREDENTIALS = True
3. 确认Django的ADFS认证配置
确保你用的Django ADFS库(比如django-auth-adfs)配置了正确的回调地址,回调地址要和你在Azure AD里注册的一致,而且这个回调地址应该是Django的接口,处理授权码后返回前端。
你提供的原始信息
错误详情
Access to XMLHttpRequest at 'https://login.microsoftonline.com/{your-tenant-id}/oauth2/v2.0/authorize?client_id={your-client-id}&response_type=token&redirect_uri={your-redirect-uri}=openid' (redirected from 'http://localhost:8080/api/base/login/') from origin 'http://localhost:4200' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
当前settings.py片段
ALLOWED_HOSTS = ['*'] # Application definition INSTALLED_APPS = [ 'base_app', 'django_crontab', 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'rest_framework', 'corsheaders', 'customer_account', 'upload...
备注:内容来源于stack exchange,提问作者Spike Speigel

