网站首页 > 技术文章 正文
问题
使用前后端分离模式开发项目时,往往会遇到这样一个问题 -- 无法跨域获取服务端数据
这是由于浏览器的同源策略导致的,目的是为了安全。在前后端分离开发模式备受青睐的今天,前端和后台项目往往会在不同的环境下进行开发,这时就会出现跨域请求数据的需求,目前的解决方案主要有以下几种:
JSONP、iframe、代理模式、CORS等等
前面几种方式在这里不讲,网上有很多资料。在这里我主要分享一下CORS这种解决方式,CORS即“跨域资源共享”,它允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制。
使用 CORS 跨域的时候和普通的 ajax 过程是一样的,只是浏览器在发现这是一个跨域请求的时候会自动帮我们处理一些事情,所以说只要服务端提供支持,前端是不需要做额外的事情的。
实现
实现的大概思路是这样的,首先使用过滤器获取请求对象request的信息,比如Origin 字段(表示请求来自哪个源,包括协议、域名、端口),通过预先配置的参数判断请求是否合法,然后设置响应对象response的头信息,实现跨域资源请求。在介绍实现方式之前我们先来了解一下会用到的响应头信息。
响应头
- Access-Control-Allow-Methods
- 用来列出浏览器的CORS请求允许使用的HTTP方法,如:GET、POST、PUT、DELETE、OPTIONS
- Access-Control-Allow-Credentials
- 表示是否支持跨域Cookie
- Access-Control-Allow-Headers
- 逗号分隔的字符串,表示服务器支持的所有头信息字段,如Content-Type以及自定义的字段
- Access-Control-Expose-Headers
- 与“Access-Control-Allow-Headers”相反,表示不支持的头信息字段
- Access-Control-Allow-Origin
- 允许跨域的请求源信息,包括协议、域名、端口,为*表示允许所有请求来源,并且只能设置一个请求源
下面介绍一下Java后台如何实现这种方式。
代码
由于最近在使用spring-boot,所以接下来以spring-boot为基础来实现。
首先创建一个CorsFilter过滤器,代码如下:
... @WebFilter(filterName = "corsFilter", urlPatterns = "/*", initParams = {@WebInitParam(name = "allowOrigin", value = "*"), @WebInitParam(name = "allowMethods", value = "GET,POST,PUT,DELETE,OPTIONS"), @WebInitParam(name = "allowCredentials", value = "true"), @WebInitParam(name = "allowHeaders", value = "Content-Type,X-Token")}) public class CorsFilter implements Filter { private String allowOrigin; private String allowMethods; private String allowCredentials; private String allowHeaders; private String exposeHeaders; @Override public void init(FilterConfig filterConfig) throws ServletException { allowOrigin = filterConfig.getInitParameter("allowOrigin"); allowMethods = filterConfig.getInitParameter("allowMethods"); allowCredentials = filterConfig.getInitParameter("allowCredentials"); allowHeaders = filterConfig.getInitParameter("allowHeaders"); exposeHeaders = filterConfig.getInitParameter("exposeHeaders"); } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest) servletRequest; HttpServletResponse response = (HttpServletResponse) servletResponse; if (!StringUtils.isEmpty(allowOrigin)) { if(allowOrigin.equals("*")){ response.setHeader("Access-Control-Allow-Origin", allowOrigin); }else{ List<String> allowOriginList = Arrays.asList(allowOrigin.split(",")); if (allowOriginList != null && allowOriginList.size() > 0) { String currentOrigin = request.getHeader("Origin"); if (allowOriginList.contains(currentOrigin)) { response.setHeader("Access-Control-Allow-Origin", currentOrigin); } } } } if (!StringUtils.isEmpty(allowMethods)) { response.setHeader("Access-Control-Allow-Methods", allowMethods); } if (!StringUtils.isEmpty(allowCredentials)) { response.setHeader("Access-Control-Allow-Credentials", allowCredentials); } if (!StringUtils.isEmpty(allowHeaders)) { response.setHeader("Access-Control-Allow-Headers", allowHeaders); } if (!StringUtils.isEmpty(exposeHeaders)) { response.setHeader("Access-Control-Expose-Headers", exposeHeaders); } filterChain.doFilter(servletRequest, servletResponse); } @Override public void destroy() { } }
大功告成,现在前端就可以跨域获取后台的数据了,比其它方式容易得多,代码就不解释了,简单易懂,使用其它后台开发方式也一样,最终目的就是判断请求,设置响应头,前端什么事都不用做。
猜你喜欢
- 2024-09-26 跨域了?装个插件就够了(跨域软件下载)
- 2024-09-26 前后端分离的项目,解决跨域问题(前后端分离如何解决跨域)
- 2024-09-26 每日学点---一文读懂Nginx跨域请求Access-Control-Allow-Origin
- 2024-09-26 详解Nginx配置跨域请求Access-Control-Allow-Origin
- 1516℃桌面软件开发新体验!用 Blazor Hybrid 打造简洁高效的视频处理工具
- 582℃Dify工具使用全场景:dify-sandbox沙盒的原理(源码篇·第2期)
- 518℃MySQL service启动脚本浅析(r12笔记第59天)
- 488℃服务器异常重启,导致mysql启动失败,问题解决过程记录
- 487℃启用MySQL查询缓存(mysql8.0查询缓存)
- 473℃「赵强老师」MySQL的闪回(赵强iso是哪个大学毕业的)
- 453℃mysql服务怎么启动和关闭?(mysql服务怎么启动和关闭)
- 452℃MySQL server PID file could not be found!失败
- 最近发表
- 标签列表
-
- cmd/c (90)
- c++中::是什么意思 (84)
- 标签用于 (71)
- 主键只能有一个吗 (77)
- c#console.writeline不显示 (75)
- pythoncase语句 (81)
- es6includes (73)
- windowsscripthost (67)
- apt-getinstall-y (86)
- node_modules怎么生成 (76)
- c++int转char (75)
- static函数和普通函数 (76)
- el-date-picker开始日期早于结束日期 (70)
- js判断是否是json字符串 (67)
- checkout-b (67)
- c语言min函数头文件 (68)
- asynccallback (71)
- localstorage.removeitem (74)
- vector线程安全吗 (70)
- java (73)
- js数组插入 (83)
- mac安装java (72)
- eacces (67)
- 查看mysql是否启动 (70)
- 无效的列索引 (74)