前端页面调用Spring boot接口发生的跨域问题
最近要重构一个基于spring boot的后端API服务,需要再本地测试。在本地测试时,运行在本地的前端页面发送一个ajax请求访问后端API,然后浏览器报错blocked CORS policy。
Access to XMLHttpRequest at 'http://127.0.0.1:1234/api/' from origin 'http://dev.couchbase.cloud.qiyi.domain' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

最后的解决方法很简单,只需要在相应的Controller上加一个注解@CrossOrigin就可以了,也可以将注解加到相应的方法上面。
为什么有些时候调用服务器的接口时没有发生这个报错?
原因:浏览器发送ajax请求必须是同源的,也就是浏览器访问服务器接口需要考虑同源,而服务器与服务器之间访问接口是不需要考虑同源的。
(一)同源策略(SOP策略)
同源策略(Same-Origin-Policy):URL由协议、域名、端口和路径组成,如果两个URL的协议、域名和端口相同,则表示他们同源。相反,只要协议,域名,端口有任何一个的不同,就被当作是跨域。
浏览器采用同源策略,禁止页面加载或执行与自身来源不同的域的任何文档或脚本,换句话说浏览器禁止的是来自不同源的"document"或脚本。在一个http请求中,http头部Referer或Origin字段标识了当前域名,Host字段标识了此时请求的域名。因此我们在当前的js页面,通过ajax请求第三方的数据,就会出现浏览器的跨域问题。
(二)跨域解决方法
1. 使用CORS策略
CORS策略:跨域资源共享(Corss Origin Resource Sharing)通过服务器增加一个特殊的Header[Access-Control-Allow-Origin]来告知客户端跨域的限制,如果浏览器支持CORS的话,当判断Origin通过的话,就会允许请求。使用这个Header返回被允许请求跨域请求的来源域,例如网站duelist.cn设置了下面的Header
Access-Control-Allow-Origin: http://smdcn.net
这样设置之后,通过http://smdcn.net下的页面对于duelist.cn进行ajax请求就会被允许,而其他网站对duelist.cn依旧会被阻拦,通过这种方式网站拥有者可以自己对此进行限制。当然,如果不想限制来源,可以通过来允许任何站点对该资源进行跨域请求
Access-Control-Allow-Origin: *
CORS规范中常见的头信息:
常见的头信息包括: Request Headers: Origin、Access-Control-Request-Method、Access-Control-Request-Headers Response Headers: . 允许向该服务器提交请求的URI Access-Control-Allow-Origin: <origin> | * . 浏览器允许访问的服务器的头信息的白名单 Access-Control-Expose-Headers: ..., ... . 请求有效期(单位:秒): Access-Control-Max-Age: <seconds> . 允许的请求方法: Access-Control-Allow-Methods . 实际的请求中,可以使用的自定义HTTP请求头 Access-Control-Allow-Headers . 告知客户端,当请求XHR的withCredientials属性是true的时候,响应是否可以被得到。(从而使得下一次请求时,上一次的Cookies可以随着请求发送) Access-Control-Allow-Credentials:
在传统的Spring MVC中的使用方法:(网上较多资料都是这种方法)
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Component; @Component
public class SimpleCORSFilter implements Filter { public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletResponse response = (HttpServletResponse) res;
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers", "x-requested-with");
chain.doFilter(req, res);
} public void init(FilterConfig filterConfig) {} public void destroy() {} }
<filter>
<filter-name>cors</filter-name>
<filter-class>com.app.filter.SimpleCORSFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>cors</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
在Spring boot中的使用方法就是添加注解@CrossOrigin
向@RequestMapping注解的Controller方法处添加一个@CrossOrigin注解:
@RestController
@RequestMapping("/account")
public class AccountController { @CrossOrigin
@GetMapping("/{id}")
public Account retrieve(@PathVariable Long id) {
// ...
} @DeleteMapping("/{id}")
public void remove(@PathVariable Long id) {
// ...
}
}
为整个controller启用@CrossOrigin:
@CrossOrigin(origins = "http://domain2.com", maxAge = 3600)
@RestController
@RequestMapping("/account")
public class AccountController { @GetMapping("/{id}")
public Account retrieve(@PathVariable Long id) {
// ...
} @DeleteMapping("/{id}")
public void remove(@PathVariable Long id) {
// ...
}
}
其中@CrossOrigin中的2个参数:
origins : 允许可访问的域列表
maxAge:准备响应前的缓存持续的最大时间(以秒为单位)。
2. 使用jsonp
jsonp解决跨域问题的原理是,浏览器的script标签是不受同源策略限制的,我们可以在script标签中访问任何域名下的资源文件。利用这一特性,用script标签从服务器中请求数据,同时服务器返回一个带有方法和数据的js代码,请求完成,调用本地的js方法,来完成数据的处理。
不推荐使用jsonp,首先jsonp是一种非官方的方法,而且这种方法只支持GET方法,不如POST方法安全;而且一般前后端分离最通用的方法是返回统一的json格式。
3. 服务器代理
这种方式运用的就是服务器的反向代理技术,控制客户端和服务器的访问都从代理服务器经过,比如用nginx作为服务器代理,在nginx上配置客户端和第三方服务的反向代理,这样就可保证客户端、第三方是同源的了,同一个源,都来自代理服务器。
前端页面调用Spring boot接口发生的跨域问题的更多相关文章
- Spring Boot 通过CORS实现跨域
同源策略 很多人对跨域有一种误解,以为这是前端的事,和后端没关系,其实不是这样的,说到跨域,就不得不说说浏览器的同源策略. 同源策略是由 Netscape 提出的一个著名的安全策略,它是浏览器最核心也 ...
- express搭建后端请求路由,前端进行访问对应的接口 后端解决跨域
代码在 ==>E:\nodes实战\myserve\testserve 1 express搭建后端请求路由,前端进行访问对应的接口 1) 创建项目目录 express 项目名 -e 然后按照提示 ...
- Spring Boot+AngularJS中因为跨域导致Session丢失
http://blog.csdn.net/dalangzhonghangxing/article/details/52446821 如果还在为跨域问题烦恼,请查看博主的 解决angular+sprin ...
- spring boot 接口返回值封装
Spring Boot 集成教程 Spring Boot 介绍 Spring Boot 开发环境搭建(Eclipse) Spring Boot Hello World (restful接口)例子 sp ...
- Spring Boot全局支持CORS(跨源请求)
import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet. ...
- 关于 Spring Security OAuth2 中 CORS 跨域问题
CORS 是一个 W3C 标准,全称是”跨域资源共享”(Cross-origin resource sharing).它允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了 AJA ...
- Spring Boot 接口幂等插件使用
幂等概述 幂等性原本是数学上的概念,即使公式:f(x)=f(f(x)) 能够成立的数学性质.用在编程领域,则意为对同一个系统,使用同样的条件,一次请求和重复的多次请求对系统资源的影响是一致的. 幂等性 ...
- spring boot:接口站增加api版本号后的安全增强(spring boot 2.3.3)
一,接口站增加api版本号后需要做安全保障? 1,如果有接口需要登录后才能访问的, 需要用spring security增加授权 2,接口站需要增加api版本号的检验,必须是系统中定义的版本号才能访问 ...
- 一个简单的Webservice的demo(中)_前端页面调用
首先新建项目,这里有两种调用方式,为了能方便理解,新建页面WebserviceTest如下图: 先引用写好的服务,这里用上次写好的服务.见上次写的一个简单的Webservice的demo,简单模拟服务 ...
随机推荐
- java之xml解析-dom4j
解析方式 XML 解析方式有很多种,但是常用的有两种,如下: DOM Document Object Model:把整个 XML 读到内存中,形成树状结构.整个文档为 Document 对象,属性为 ...
- Substrate 使用
1.安装 首先安装sdk,按官网教程http://www.cydiasubstrate.com/id/73e45fe5-4525-4de7-ac14-6016652cc1b8/ http://asdk ...
- C# Remoting例子
4-23 https://www.cnblogs.com/zhengyun_ustc/archive/2006/06/09/remoting_InvalidCredentialException.ht ...
- python扩展包的升级
检查更新:pip list --outdated 更新: pip install --upgrade xxxx
- python SyntaxError: Non-ASCII character '\xe6' in file
[1]python程序执行报错 报错:SyntaxError: Non-ASCII character '\xe6' in file /tmp/788580473/main.py on line 7, ...
- bash vim等常用命令
生成的txt一不小心带了./,用vim: :%s/\.\/single/single #%s/xxx/yyy/g是全文本替换,这里用\将特殊字符.和/转换成普通字符 结果还不错: ---------- ...
- Java课程总结
预备作业一 简要内容:我期望的师生关系 预备作业二 简要内容:学习基础和C语言基础调查 预备作业三 简要内容:Linux安装及学习 第一周作业 简要内容:Java入门 第二周作业 简要内容:学习基本数 ...
- Linux基础命令---cancel取消打印任务
cancel cancel指令用来取消已经存在的打印任务. 此命令的适用范围:RedHat.RHEL.Ubuntu.CentOS.Fedora.openSUSE.SUSE. 1.语法 ...
- 16款优秀的Vue UI组件库推荐
16款优秀的Vue UI组件库推荐 Vue 是一个轻巧.高性能.可组件化的MVVM库,API简洁明了,上手快.从Vue推出以来,得到众多Web开发者的认可.在公司的Web前端项目开发中,多个项目采用基 ...
- Oarcle 入门之where关键字
--where 关键字 --作用:过滤行 *将需要的行用where引导出来 用法: 1.判断符号:=,!=,<>,<,>,<=,>=,any,some,all; 例 ...