Ant Design Pro 使用proxy无法设置cookies
近期使用ant design Pro 实现了一个内部的后台。用于提供一个简单界面访问一些用户和设备的数据。
但近期需要将系统交接给其他同事继续开发。想要在本地配置proxy连接后端服务器。
1 关于AntD Pro配置代理
1.1 关于为什么要配置代理
AntD Pro 是前后端分离的前端框架,在部署时,一般会将前端代码打包和后端代码部署同一个域名下,所以不会有跨域的场景。比如使用nginx 部署·
location / {
try_files $uri $uri/ /index.html;
}
location /api {
proxy_pass https://ant-design-pro.netlify.com;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
}
但开发阶段,AntD Pro也会监听自己的端口,和后端服务器使用不同的端口,界面访问后端接口,这就出触发跨域,导致被浏览器拦截。
什么是同源策略?
同源策略限制了从同一个源加载的文档或脚本如何与来自另一个源的资源进行交互。这是一个用于隔离潜在恶意文件的重要安全机制。
什么是跨域?
当一个请求url的协议、域名、端口三者之间任意一个与当前页面url不同即为跨域
跨域问题的具体体现在浏览器上开发页面时,跨域的请求会被浏览器拦截。 请求url的协议、域名、端口一致则认为是同源。
所以为了方便开发,现在市面上所有的脚手架都提供了 proxy 的能力,底层基于 http-proxy-middleware, 这个包可以把所有符合正则匹配的请求转发到某个地址。这样就可以方便地进行开发。绕开同源策略带来与后端服务器交互问题。
其实也可以配置特殊Http Headers启用 CORS
来允许跨域来解决这个问题。
**
参考链接:https://pro.ant.design/blog/proxy-cn
1.2 如何配置代理
AntD Pro V4 是在config/proxy.js中配置代理。
// config/config.ts
export default {
proxy: {
'/api': {
'target': 'http://jsonplaceholder.typicode.com/',
'changeOrigin': true,
'pathRewrite': { '^/api' : '' },
},
},
}
注意 proxy 配置不会改变你本地请求的 url(依旧是 http://localhost:8000/api/xxx),但是会在本地服务转发到 target 上。
target: 要与url模块解析的url字符串
changeOrigin: true, //true为开启跨域代理
pathRewrite,用'^/api':''
, 把’/api’去掉。
比如后端接口为 http://jsonplaceholder.typicode.com/users
而前端为匹配 http://localhost:8000/api/users。 则可以将这个访问后端多出/api去掉。
详细的配置建议直接查看 webpack-dev 的配置。
2 无法设置cookie
在配置代理后访问后端服务器时,发现无法设置cookies。导致登录后不能跳转界面
但实际上,登录接口response 也返回了set-cookie 字段。那目前问题就是浏览器没有将set-cookies中的内容设置到aplication中。
这里发现有一个警告
问题就在这里了。因为后端服务器使用了https。而前端访问代理使用的是http。而后端返回的set-cookies 中的存在secure字段。所以导致浏览器处理cookies时发现Secure字段且当前地址为http,所以导致无法将存入到application中。
关于set-cookies中字段的内容 我们可以参考 MDN的说明
如果其中保留字段中的部分值与当前浏览器环境不一致则无法设置。
Secure:Cookie仅在使用该
https:方案发出请求时才发送到服务器(本地主机除外**)不安全的网站(
http:)无法使用
Secure`属性设置Cookie 。
Path:请求的URL中必须存在一个路径,否则浏览器将不会发送Cookie
标头。
Domain:如果省略,则默认为当前文档URL的主机,不包括子域。
如何解决?
使用 webpack-dev 的配置。使用onProxyRes 将Secure 字段拿掉。 当然这是你本地代理的情况下
onProxyRes: function (proxyRes) {
const cookies = proxyRes.headers['set-cookie'];
let newCookie;
if (cookies) {
const cookiePathRegex = /secure;/;
newCookie = cookies.map((cookie) => {
if (cookiePathRegex.test(cookie)) {
// 替换
return cookie.replace(cookiePathRegex, '');
}
return cookie;
});
delete proxyRes.headers['set-cookie'];
proxyRes.headers['set-cookie'] = newCookie;
}
},