Django Vue 跨域问题
一、Django中設置
使用pip安裝
pip install django-cors-headerssetting.py中設置
INSTALLED_APPS = [...'corsheaders' ] MIDDLEWARE = [ 'corsheader.middleware.CorsMiddleware', # 盡量放在csrf前面 ... ]添加中間件,需要注意放的位置,在SessionMiddleware后面以及CommonMiddleware前面
添加配置參數
二、Vue中設置
Vue中如果要攜帶Cookies,在配置axios的時候需要設置允許攜帶cookie請求,兩種方法都可以。
1、axios設置default參數 // 允許攜帶cookie請求 axios.defaults.withCredentials = true2、或者創建實例的時候設置withCredentials: true //1. 創建新的axios實例, const service = axios.create({// 公共接口--這里注意后面會講baseURL: 'http://10.0.0.101:8000/api/v1/',// 超時時間 單位是ms,這里設置了3s的超時時間timeout: 30 * 1000,withCredentials: true })三、谷歌瀏覽器跨域Cookies帶不到后端的坑
參考 VUE 在谷歌瀏覽器中無法識別存儲的Cookie,以及跨域跳轉
Firefox改Cookie的SameSite預設,Mozilla鼓勵開發者測網站兼容性
- 我這里認證使用的cookies-sessionid的方式,所以跨域請求的時候需要帶上cookies,但是配置了上面的參數后,請求可以訪問到后端,但是cookies在后端一直帶不過去。找了好久,發現是瀏覽器SameSite這個配置的問題。
-
原因是Chrome升級到80版本之后cookie的SameSite屬性默認值由None變為Lax,這也就造成了一些訪問跨域cookie無法攜帶的問題。當開發者明確配置SameSite為None,同時還設定Secure屬性使用HTTPS連線,才能夠讓Cookie可被跨站存取。
-
過去瀏覽器預設允許Cookie跨站存取,因此開發者不需要特別設定,但由于預設屬性變更,現在網站開發者必須要明確設定SameSite與Secure屬性,例如response.setHeader("Set-Cookie", "HttpOnly;Secure;SameSite=None")過去仰賴舊預設的網站才能正確運作,當網站沒有正確配置這些屬性,則功能就可能故障。
-
但是如果設置SameSite與Secure屬性,那么就會強制需要https訪問,還要再加上http轉https的配置,實在是蛋疼。下面直接修改谷歌瀏覽器的SameSite配置來解決Cookies帶不過去的問題
-
但是不可能每個人都修改瀏覽器配置呀,所以在生產環境可以使用nginx轉發,可以在前端的nginx上,加上一層代理,比如匹配/api/v1,把請求轉到后端的服務上,這樣就不會有跨域的問題了。
1、打開chrome 輸入 chrome://flags/ 搜索 SameSite by default cookies
2、找到SameSite by default cookies和Cookies without SameSite must be secure
3、將上面兩項設置為 Disable
4、點擊Relaunch
火狐瀏覽器設置跨域
1.進入火狐配置頁進行設置
在地址欄輸入:about:config
2.搜索”security.fileuri.strict_origin_policy”,并設置該項為false
3.重啟瀏覽器
四、使用NGINX代理
如果上面修改了谷歌瀏覽器SameSite配置不生效的話,還可以使用NGINX代理來處理跨域問題。部分配置如下,在nginx服務器上,將默認的請求轉到前端,將/api/v1/的請求轉到后端
add_header 'Access-Control-Allow-Origin' '*';add_header 'Access-Control-Allow-Credentials' 'true';upstream vue {server 10.0.0.1:9528;}upstream django {server 10.0.0.107:8000;}server {listen 80;server_name localhost;location / {proxy_pass http://vue ;}location ~ /api/v1/ {proxy_pass http://django;}}然后把域名解析到nginx服務器的IP上,例如host文件里配置
10.0.0.107 wangxiaoyuvue.baidu.com在vue的axios中,將baseurl設置為配置的域名,這樣后端的API也會請求到nginx服務上進行代理
const service = axios.create({baseURL: 'http://wangxiaoyuvue.baidu.com/api/v1/', })有個httponly的坑需要注意一下
- 我用的sessionid做驗證,前面前后端的域名不同,進行登陸驗證的時候,請求后端的API時,響應會在后端的地址上設置sessionid這個cookies
- 我返回的data信息里也有sessionid(我這里是從自己返回data里獲取的,而不是從cookies里,因為默認設置的是httponly=true,在JS中獲取不到),所以在驗證成功后,會使用JS在前端的地址上也設置一下sessionid這個cookies,這個后面前端跨域請求的時候,才會把sessionid這個cookies帶到后端。
- 并且,在vue的路由前置函數里,判斷是否有sessionid,如果沒有的話則跳轉到登陸頁。
- 但是,如果使用nginx代理后,前后端的域名是一樣的,請求django的login登陸函數后,會直接設置sessionid這個cookies,并且httponly=true
- 如果cookie中設置了HttpOnly屬性,那么通過js腳本將無法讀取到cookie信息,這樣能有效的防止XSS攻擊,竊取cookie內容,這樣就增加了cookie的安全性
- 需要再django的setting.py中設置SESSION_COOKIE_HTTPONLY=False,讓django在設置cookies的時候,httponly=false
五、Vue配置代理
開發模式下使用Vue代理
如果用上面那種nginx里轉發的方法的話,后端的域名如果寫死了,因為是在同一個nginx里接收前后端的請求然后判斷轉到前端或者后端,在axios.defaults.baseURL=http://www.xxxapi.com/api/v1里將后端的域名寫死了
但是如果有多個前端域名的話,這個時候就很麻煩了,總不能跟著配置多個后端的域名吧。在開發模式下可以使用vue的代理方式。
修改aixos的baseURL前綴,這里不加具體的域名或者ip,這樣會默認請求當前項目,可以匹配到代理的配置
axios.defaults.baseURL = '/api/v1/'在vue.config.js中設置代理,匹配包含/api/v1的請求轉到后端的域名地址
proxy: {'/api/v1': {target: 'http://www.xxxapi.com/',changeOrigin: true, // 允許跨域pathRewriter: {// '': ''}}},注意:如果用的vue-element-admin這個框架,一定要把下面的before: require('./mock/mock-server.js')這個注釋掉,不然會請求項目之前設置的一些數據。
部署上去后發現代理失效了,這個代理只在dev模式下有效,所以在前端的nginx上還是得做轉發
location ~ /api/v1/ {proxy_pass http://django;}六、部署到機器上
這里用的vue-element-admin
git clone git@git.xxx cd 項目地址 npm install --registry=https://registry.npm.taobao.org npm install npm run build:prod然后把打包后的dist文件放到nginx,try_files $uri $uri/ /index.html;這個表示如果找不到靜態資源則把請求轉給index.html
location / {root /usr/local/dist;try_files $uri $uri/ /index.html;index index.html index.htm;}location ~ /api/v1/ {proxy_pass http://django;}總結
以上是生活随笔為你收集整理的Django Vue 跨域问题的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python将所有excel文档合并
- 下一篇: vue跨域