原文:https://www.cnblogs.com/shihaiming/p/9544060.html

介绍:   跨站 HTTP 请求(Cross-site HTTP request)是指发起请求的资源所在域不同于该请求所指向资源所在的域的 HTTP 请求。比如说,域名A(http://domaina.example)的某 Web 应用程序中通过标签引入了域名B(http://domainb.foo)站点的某图片资源(http://domainb.foo/image.jpg),域名A的那 Web 应用就会导致浏览器发起一个跨站 HTTP 请求。在当今的 Web 开发中,使用跨站 HTTP 请求加载各类资源(包括CSS、图片、JavaScript 脚本以及其它类资源),已经成为了一种普遍且流行的方式。

正如大家所知,出于安全考虑,浏览器会限制脚本中发起的跨站请求。比如,使用 XMLHttpRequest 对象发起 HTTP 请求就必须遵守同源策略(same-origin policy)。 具体而言,Web 应用程序能且只能使用 XMLHttpRequest 对象向其加载的源域名发起 HTTP 请求,而不能向任何其它域名发起请求。为了能开发出更强大、更丰富、更安全的Web应用程序,开发人员渴望着在不丢失安全的前提下,Web 应用技术能越来越强大、越来越丰富。比如,可以使用 XMLHttpRequest 发起跨站 HTTP 请求。(这段描述跨域不准确,跨域并非浏览器限制了发起跨站请求,而是跨站请求可以正常发起,但是返回结果被浏览器拦截了。最好的例子是crsf跨站攻击原理,请求是发送到了后端服务器无论是否跨域!注意:有些浏览器不允许从HTTPS的域跨域访问HTTP,比如Chrome和Firefox,这些浏览器在请求还未发出的时候就会拦截请求,这是一个特例。

同源:指的是域名(或IP)协议端口都相同,不同源的客户端脚本(javascript、ActionScript)在没明确授权的情况下,不能读写对方的资源。

URL 解释 是否跨域
http://www.morethink.cn 原来的URL  
http://www.image.morethink.cn 子域名 跨域(cookie也无法访问)
http://morethink.cn 不加www 跨域
https://www.morethink.cn 更改协议 跨域
http://www.morethink.cn:8080 更改端口号 跨域

模拟第三方调取:

var xhr = new XMLHttpRequest();
xhr.open('POST', 'http://localhost:8080/agentwap/auth/toTransfer.do?callbackAddress=https://www.baidu.com',true);
xhr.send();
xhr.onreadystatechange=function() {
if(xhr.readyState == 4) {
if(xhr.status == 200) {
console.log(JSON.parse(xhr.responseText));
}
}
}

解决方案:

普通参数跨域

在response的头文件添加

httpServletResponse.setHeader("Access-Control-Allow-Origin","*");
httpServletResponse.setHeader("Access-Control-Allow-Methods","POST");
httpServletResponse.setHeader("Access-Control-Allow-Headers","Access-Control");
httpServletResponse.setHeader("Allow","POST"); Access-Control-Allow-Origin:| * // 授权的源控制
Access-Control-Max-Age:// 授权的时间
Access-Control-Allow-Credentials: true | false // 控制是否开启与Ajax的Cookie提交方式
Access-Control-Allow-Methods:[,]* // 允许请求的HTTP Method
Access-Control-Allow-Headers:[,]* // 控制哪些header能发送真正的请求

观察响应头

带headr请求跨域

这样客户端需要发起 OPTIONS请求, 可以说是一个“预请求”,用于探测后续真正需要发起的跨域 POST 请求对于服务器来说是否是安全可接受的,因为跨域提交数据对于服务器来说可能存在很大的安全问题。

因为Springmvc模式是挂壁OPTIONS请求的,所以需要开启

<servlet>
<servlet-name>application</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>dispatchOptionsRequest</param-name>
<param-value>true</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>

Spring MVC 从4.2版本开始增加了对CORS的支持

spring MVC 中增加CORS支持非常简单,可以配置全局的规则,也可以使用@CrossOrigin注解进行细粒度的配置。

使用@CrossOrigin注解

先通过源码看看该注解支持的属性:

在Controller上使用@CrossOrigin注解

@CrossOrigin(origins = "*", maxAge = 3600)
@RestController
@RequestMapping("/account")
public class AccountController { @RequestMapping("/{id}")
public Account retrieve(@PathVariable Long id) {
// ...
} @RequestMapping(method = RequestMethod.DELETE, path = "/{id}")
public void remove(@PathVariable Long id) {
// ...
}
}

这里指定当前的AccountController中所有的方法可以处理所有域上的请求,

在方法上使用@CrossOrigin注解

@CrossOrigin(maxAge = 3600)
@RestController
@RequestMapping("/account")
public class AccountController { @CrossOrigin("http://domain2.com")
@RequestMapping("/{id}")
public Account retrieve(@PathVariable Long id) {
// ...
} @RequestMapping(method = RequestMethod.DELETE, path = "/{id}")
public void remove(@PathVariable Long id) {
// ...
}
}

在这个例子中,AccountController类上也有@CrossOrigin注解,retrieve方法上也有注解,Spring会合并两个注解的属性一起使用。

CORS全局配置

除了细粒度基于注解的配置,你可能会想定义一些全局CORS的配置。这类似于使用过滤器,但可以在Spring MVC中声明,并结合细粒度@CrossOrigin配置。默认情况下所有的域名和GET、HEAD和POST方法都是允许的。

基于JAVA的配置

看下面例子:

@Configuration
public class WebConfig extends WebMvcConfigurerAdapter { @Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**");
}
}

您可以轻松地更改任何属性,以及配置适用于特定的路径模式的CORS:

如果你使用Spring Boot,你可以通过这种方式方便的进行配置。

@Configuration
public class WebConfig extends WebMvcConfigurerAdapter { @Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/api/**")
.allowedOrigins("http://domain2.com")
.allowedMethods("PUT", "DELETE")
.allowedHeaders("header1", "header2", "header3")
.exposedHeaders("header1", "header2")
.allowCredentials(false).maxAge(3600);
}
}

不限制任何请求(方便复制粘贴)

@Configuration
public class CorsConfig extends WebMvcConfigurerAdapter {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
.allowedMethods("GET", "HEAD", "POST", "PUT", "PATCH", "DELETE", "OPTIONS", "TRACE");
}
}

基于XML的配置

<mvc:cors>
<mvc:mapping path="/**" />
</mvc:cors>

这个配置和上面Java方式的第一种作用一样。

同样,你可以做更复杂的配置:

<mvc:cors>

    <mvc:mapping path="/api/**"
allowed-origins="http://domain1.com, http://domain2.com"
allowed-methods="GET, PUT"
allowed-headers="header1, header2, header3"
exposed-headers="header1, header2" allow-credentials="false"
max-age="123" /> <mvc:mapping path="/resources/**"
allowed-origins="http://domain1.com" /> </mvc:cors>

springMVC解决跨域的更多相关文章

  1. SpringMVC解决跨域问题

    有个朋友在写扇贝插件的时候遇到了跨域问题. 于是我对解决跨域问题的方式进行了一番探讨. 问题 API:查询单词 URL: https://api.shanbay.com/bdc/search/?wor ...

  2. [转载]SpringMVC解决跨域问题

    本文转载自  https://www.cnblogs.com/morethink/p/6525216.html SpringMVC解决跨域问题, 感谢作者! 有个朋友在写扇贝插件的时候遇到了跨域问题. ...

  3. SpringMVC解决跨域问题及CROS

    CORS 首先因为最近在做一个前后端分离的项目,分开就意味着可能不在一个域中,所以不可避免的遇到CORS的问题.试过几个方法: Spring MVC 4.2.5以后新增的支持跨域的注解@CrossOr ...

  4. SpringMVC解决跨域的两种方案

    1. 什么是跨域 2. 跨域的应用情景 3. 通过注解的方式允许跨域 4. 通过配置文件的方式允许跨域 1. 什么是跨域 跨域,即跨站HTTP请求(Cross-site HTTP request),指 ...

  5. springmvc 解决跨域CORS

    import java.io.IOException; import javax.servlet.Filter; import javax.servlet.FilterChain; import ja ...

  6. 前端通过Nginx反向代理解决跨域问题

    在前面写的一篇文章SpringMVC 跨域,我们探讨了什么是跨域问题以及SpringMVC怎么解决跨域问题,解决方式主要有如下三种方式: JSONP CORS WebSocket 可是这几种方式都是基 ...

  7. java springmvc 前端 跨域问题

    有个朋友在写扇贝插件的时候遇到了跨域问题.于是我对解决跨域问题的方式进行了一番探讨. 问题 API:查询单词URL: https://api.shanbay.com/bdc/search/?word= ...

  8. 使用SpringMVC的@CrossOrigin注解解决跨域请求问题

    跨域问题,通俗说就是用ajax请求其他站点的接口,浏览器默认是不允许的.同源策略(Same-orgin policy)限制了一个源(orgin)中加载脚本或脚本与来自其他源(orgin)中资源的交互方 ...

  9. springboot解决跨域问题(Cors)

    1.对于前后端分离的项目来说,如果前端项目与后端项目部署在两个不同的域下,那么势必会引起跨域问题的出现. 针对跨域问题,我们可能第一个想到的解决方案就是jsonp,并且以前处理跨域问题我基本也是这么处 ...

随机推荐

  1. POJ 3259 Wormholes SPFA算法题解

    版权声明:本文作者靖心,靖空间地址:http://blog.csdn.net/kenden23/,未经本作者同意不得转载. https://blog.csdn.net/kenden23/article ...

  2. django后台返回html字段会产生XSS防护的解决方式

    1.在前端模块里面写 {{  page_str|safe }} 2.在后端 from django.utils.safestring import mark_safe pake_str = mark_ ...

  3. Windows系统如何安装Redis

    转自 http://blog.csdn.net/lamp_yang_3533/article/details/52024744 一.Redis的下载地址 Redis官方并没有提供Redis的windo ...

  4. Apache 用户认证

    基本认证(Basic) 摘要认证(Digest) 更安全 创建一个名为 users 的认证口令: htpasswd    -c   /usr/local/apache2/conf/users sam ...

  5. Array.prototype

    Array.prototype  属性表示 Array 构造函数的原型,并允许您向所有Array对象添加新的属性和方法. /* 如果JavaScript本身不提供 first() 方法, 添加一个返回 ...

  6. Django视图中使用本地缓存

    Django服务器视图使用缓存可以大大减小服务器的压力,对数据实时性要求不高的场景使用缓存非常适合. 使用Django本地缓存 1. 在settings.py配置CACHES CACHES = { ' ...

  7. 四、绑定SignaIR的用户管理

    一.用户分组(第一个默认我的好友,禁删和更改) 没有分组id,更改layim代码: 更改id即可. layui.define('jquery', function (exports) { " ...

  8. 自定义str_repr_format

    class Foo: def __init__(self,name,age): self.name = name self.age = age def __str__(self): #自定义类的实例对 ...

  9. 牛客练习赛33 D tokitsukaze and Inverse Number (树状数组求逆序对,结论)

    链接:https://ac.nowcoder.com/acm/contest/308/D 来源:牛客网 tokitsukaze and Inverse Number 时间限制:C/C++ 1秒,其他语 ...

  10. 2019 计蒜之道 初赛 第一场 商汤AI园区的n个路口(中等) (树形dp)

    北京市商汤科技开发有限公司建立了新的 AI 人工智能产业园,这个产业园区里有 nn 个路口,由 n - 1n−1 条道路连通.第 ii 条道路连接路口 u_iui​ 和 v_ivi​. 每个路口都布有 ...