一. 背景
在做毕设时,总会遇到新的问题,这不,它又来了,这次的需求是在发送GET请求时,为了确保用户具有发送该API的权限,需要在headers头部中增加一个permission字段便于后端校验。
如下是vue中使用axios发送请求,并在headers中添加permission字段。
1 2 3
| const res = await this.$http.get('/seller/chsc/apis/commodity/', { headers: { Permission: this.permission }, })
|
二 问题
刷新浏览器,芜湖~,飘了3条红,仔细一看,发现是跨域处出现了问题, 错误原因是因为permissions不被Access-Control-Allow-Headers所允许,由于Access-Control-Allow-Headers出现在响应体中,所以由后端来定义。故而,只需要修改后端的代码即可。
{width=90%}
三 解决方法
我后端开发采用Django,使用了CorsMiddleware中间件,进入CorsMiddleware源码,在process_response
函数中可以看到响应的响应头部字段的设置。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
| def process_response(self, request, response): """ Add the respective CORS headers """ enabled = getattr(request, "_cors_enabled", None) if enabled is None: enabled = self.is_enabled(request)
if not enabled: return response
patch_vary_headers(response, ["Origin"])
origin = request.META.get("HTTP_ORIGIN") if not origin: return response
url = urlparse(origin)
if conf.CORS_ALLOW_CREDENTIALS: response[ACCESS_CONTROL_ALLOW_CREDENTIALS] = "true"
if ( not conf.CORS_ALLOW_ALL_ORIGINS and not self.origin_found_in_white_lists(origin, url) and not self.check_signal(request) ): return response
if conf.CORS_ALLOW_ALL_ORIGINS and not conf.CORS_ALLOW_CREDENTIALS: response[ACCESS_CONTROL_ALLOW_ORIGIN] = "*" else: response[ACCESS_CONTROL_ALLOW_ORIGIN] = origin
if len(conf.CORS_EXPOSE_HEADERS): response[ACCESS_CONTROL_EXPOSE_HEADERS] = ", ".join( conf.CORS_EXPOSE_HEADERS )
if request.method == "OPTIONS": response[ACCESS_CONTROL_ALLOW_HEADERS] = ", ".join(conf.CORS_ALLOW_HEADERS) response[ACCESS_CONTROL_ALLOW_METHODS] = ", ".join(conf.CORS_ALLOW_METHODS) if conf.CORS_PREFLIGHT_MAX_AGE: response[ACCESS_CONTROL_MAX_AGE] = conf.CORS_PREFLIGHT_MAX_AGE
return response
|
说明:
由于我们使用axios+跨域,通常无论GET或者POST请求会发送两次。第一次请求是OPTIONS请求,表示询问是否允许跨域,如果允许则发送第二次请求(GET或者POST),其中第一次请求返回的响应体中包含了允许跨域的请求头,请求方法和请求源,请求最大生存时间等,第二次请求只有都满足第一次请求响应体中的条件,才会成功发送,否则会产生跨域错误问题。
我们可以在源码找到这行代码response[ACCESS_CONTROL_ALLOW_HEADERS] = “, “.join(conf.CORS_ALLOW_HEADERS),我们可以去找到CORS所允许的头部,
1 2 3
| @property def CORS_ALLOW_HEADERS(self): return getattr(settings, "CORS_ALLOW_HEADERS", default_headers)
|
1 2 3 4 5 6 7 8 9 10 11
| default_headers = ( "accept", "accept-encoding", "authorization", "content-type", "dnt", "origin", "user-agent", "x-csrftoken", "x-requested-with", )
|
如果我们在settings.py文件中没有自己定义CORS_ALLOW_HEADERS
元祖,则使用默认的default_headers
,为了避免修改框架源码,我们可以自己定义,在CORS_ALLOW_HEADERS
元祖中添加permission
即可。添加之后,请求可以正常发送。