专栏首页王念博客SpringMvc解决js跨域

SpringMvc解决js跨域

前言:

跨站 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,这些浏览器在请求还未发出的时候就会拦截请求,这是一个特例。)

方法一 设置返回的Response跨域,适合所有服务端

普通参数跨域设置

在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以上) 跨域

Spring MVC 从4.2版本开始增加了对CORS的支持,在spring MVC 中增加CORS支持非常简单,可以配置全局的规则,也可以使用@CrossOrigin注解进行细粒度的配置。

1.局部配置

使用@CrossOrigin注解

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

在Controller上使用@CrossOrigin注解

@CrossOrigin(origins = "*", maxAge = 3600)
@RestController
@RequestMapping("/controller")
public class Controlle{
}

origins="*" 授权的源控制

maxAge=3600 授权的时间

在方法上使用@CrossOrigin注解

@CrossOrigin(maxAge = 3600)
@RestController
@RequestMapping("/account")
public class Controller {

    @CrossOrigin("http://www.baidu.com")
    @RequestMapping("/a")
    public void a() {
        // ...
    }
  
}

这里控制器和方法同时有,Spring会合并两个注解的属性一起应用到a方法上,可以单独管理

2.全局配置

基于java代码配置

默认情况下所有的域名和GET、HEAD和POST方法都是允许的。

@Configuration
public class WebConfig extends WebMvcConfigurerAdapter {

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**");
    }
}

你也可以单独更改任何属性,以及配置适用于特定的路径模式的CORS:

@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>

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 静态代理和动态代理的实现

    在代理模式(Proxy Pattern)中,一个类代表另一个类的功能。这种类型的设计模式属于结构型模式。在代理模式中,我们创建具有现有对象的对象,以便向外界提供...

    王念博客
  • Maven配置maven-shade-plugin插件生成可执行的jar

    默认打包生成的jar是不能直接运行的,因为带有main方法的信息不会添加到mainifest中,需要借助maven-shade-plugin

    王念博客
  • Git提交规范流程和解决冲突实际使用

    前言:GIT对于我们程序员来说是吃饭的工具,本篇主要是针对提交和分支以及对于大多数程序员闻风丧胆的冲突一些个人见解,如果有啥不对的或者你们公司git提交流程欢迎...

    王念博客
  • HTTP协议原理及实践

    HTTP是在应用层,基于传输层 0x1 低三层 物理层主要作用是定义物理设备如何传输数据 数据链路层在通信的实体间建立数据链路连接 网络层为数据在结...

    慕白
  • 你知道HTTP协议的ETag是干什么的吗?

    在HTTP1.1规范中,新增了一个HTTP头信息:ETag。对于普通开发者来说,可能平时真的不会接触到该HTTP头。平时接触不到或者说用得少,不代表这个请求头不...

    Happyjava
  • 自己动手模拟开发一个简单的Web服务器

    开篇:每当我们将开发好的ASP.NET网站部署到IIS服务器中,在浏览器正常浏览页面时,可曾想过Web服务器是怎么工作的,其原理是什么?“纸上得来终觉浅,绝知此...

    Edison Zhou
  • 设计模式--责任链模式的思考

    责任链模式: 客户端发出的请求,客户端本身并不知道被哪一个对象处理,而直接扔给对象链,该请求在对象链中共享,由对象本身决定是否处理. 当请求被处理后该链终止.本...

    屈定
  • 发生了这么多事的三星,正用VR来减轻他人的伤痛

    VRPinea
  • IntelliJ IDEA的这个接口调试工具真是太好用了!

    抗击疫情,在家办公。工作照常干,领导需要几个新功能接口开发。以前在公司办公,通常开发完的功能没什么问题,暴露出 Swagger 接口文档,直接找旁边的前端大人联...

    macrozheng
  • IntelliJ IDEA的这个接口调试工具真是太好用了!

    现陆续将Demo代码和技术文章整理在一起 Github实践精选 (https://github.com/FraserYu/learnings),方便大家阅读查看...

    用户4172423

扫码关注云+社区

领取腾讯云代金券

玩转腾讯云 有奖征文活动