基于SpringBoot解决CORS跨域的问题(@CrossOrigin)

一、关于跨域介绍

在前后分离的架构下,跨域问题难免会遇见比如,站点 http://domain-a.com 的某 HTML 页面通过 的 src 请求 http://domain-b.com/image.jpg。

网络上的许多页面都会加载来自不同域的CSS样式表,图像和脚本等资源。

出于安全原因,浏览器限制从脚本内发起的跨源HTTP请求。

例如,XMLHttpRequest和Fetch API遵循同源策略。

这意味着使用这些API的Web应用程序只能从加载应用程序的同一个域请求HTTP资源,除非使用CORS头文件。

跨域的体现,在于它的域名不同或者端口不同,但要注意以下的形式为非跨域模式

http://www.example.com/index.html ==> http://www.example.com/login.html

二、Spring Boot跨域(@CrossOrigin)

当然这里虽然指SpringBoot但是SpringMVC也是一样的,要求在Spring4.2及以上的版本

1、@CrossOrigin使用场景要求

jdk1.8+

Spring4.2+

2、@CrossOrigin源码解析(翻译参考网络,文末列出参考地址)

@Target({ ElementType.METHOD, ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface CrossOrigin {
  String[] DEFAULT_ORIGINS = { "*" };
  String[] DEFAULT_ALLOWED_HEADERS = { "*" };
  boolean DEFAULT_ALLOW_CREDENTIALS = true;
  long DEFAULT_MAX_AGE = 1800;
  /**
   * 同origins属性一样
   */
  @AliasFor("origins")
  String[] value() default {};
  /**
   * 所有支持域的集合,例如"http://domain1.com"。
   * <p>这些值都显示在请求头中的Access-Control-Allow-Origin
   * "*"代表所有域的请求都支持
   * <p>如果没有定义,所有请求的域都支持
   * @see #value
   */
  @AliasFor("value")
  String[] origins() default {};
  /**
   * 允许请求头重的header,默认都支持
   */
  String[] allowedHeaders() default {};
  /**
   * 响应头中允许访问的header,默认为空
   */
  String[] exposedHeaders() default {};
  /**
   * 请求支持的方法,例如"{RequestMethod.GET, RequestMethod.POST}"}。
   * 默认支持RequestMapping中设置的方法
   */
  RequestMethod[] methods() default {};
  /**
   * 是否允许cookie随请求发送,使用时必须指定具体的域
   */
  String allowCredentials() default "";
  /**
   * 预请求的结果的有效期,默认30分钟
   */
  long maxAge() default -1;
}

3、@CrossOrigin使用

Spring Boot下的请求处理控制器

package com.example.demo.controller;
import com.example.demo.domain.User;
import com.example.demo.service.IUserFind;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
/**
 * @Title: UserController
 * @ProjectName demo
 * @Description: 请求处理控制器
 * @author 浅然
 * @date 2018/7/2022:18
**/
@RestController
//实现跨域注解
//origin="*"代表所有域名都可访问
//maxAge飞行前响应的缓存持续时间的最大年龄,简单来说就是Cookie的有效期 单位为秒
//若maxAge是负数,则代表为临时Cookie,不会被持久化,Cookie信息保存在浏览器内存中,浏览器关闭Cookie就消失
@CrossOrigin(origins = "*",maxAge = 3600)
public class UserController {
  @Resource
  private IUserFind userFind;
  @GetMapping("finduser")
  public User finduser(@RequestParam(value="id") Integer id){
    //此处省略相应代码
  }
}

后台返回的数据

前端跨域请求

<!DOCTYPE html>
<html>
 <head>
 <meta charset="utf-8" />
 <title>demo</title>
 <script type="text/javascript" src="js/jquery-3.3.1.min.js" ></script>
 </head>
 <body>
 <input type="button" value="测试" onclick="ajaxloding()" />
 <div id="usermessage"></div>
 <script>
  var getdata=0;
  function ajaxloding(){
  $.ajax({
   async:false,
   type:"get",
   url:"http://localhost:8080/api/finduser?id=1",
   contentType: "application/x-www-form-urlencoded",
   dataType: "json",
   data: {},
   success:function(result){
   getdata=result.name
   },
   error: function (errorMsg) {
        //请求失败时执行该函数
        alert("请求数据失败!");
      }
  });
  $("#usermessage").text(getdata)
  }
 </script>
 </body>
</html>

这样就解决了跨域问题,获取了后台的数据

参考

跨域 HTTP 请求

补充:springboot的@CrossOrigin("*")跨域仍然失效

项目中偶尔遇到即使加了@CrossOrigin跨域失败:

第一次遇到时间有限没解决:前端直接添加跨域处理。

jQuery.support.cors = true;

后续第二次遇到该问题,作为后端不能让前端解决跨域问题。

debug详细查找原因:发现在自定义拦截器返回失败,跨域失败。

明白该问题:需要以下知识。

(mvc拦截器的链路模式)

(Cors拦截器加载)

(自定义的拦截器加载)

(拦截器的加载顺序)

因为拦截器是链路模式:CrossOrigin也是拦截器在自定义拦截器之后。所以在自定义拦截器失败后,处理

跨域的拦截器未处理,造成跨域失败。

解决该问题的办法:

添加filter ,因为Filter优先于拦截器执行,所以自己创建的拦截器不会影响跨域处理。

@Configuration
public class CorsConfig {
  @Bean
  public CorsFilter corsFilter() {
    CorsConfiguration config = new CorsConfiguration();
    config.addAllowedOrigin("*");
    config.setAllowCredentials(true);
    config.addAllowedMethod("*");
    config.addAllowedHeader("*");
    UrlBasedCorsConfigurationSource configSource = new UrlBasedCorsConfigurationSource();
    configSource.registerCorsConfiguration("/**", config);
    return new CorsFilter(configSource);
  }
}

二:springboot升级到2.2.0,在新版本的springmvc中,把cors拦截添加到了拦截器的第一位,所以不会有该问题。

如果允许可以直接升级springboot或mvc版本。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。如有错误或未考虑完全的地方,望不吝赐教。

(0)

相关推荐

  • springboot跨域CORS处理代码解析

    这篇文章主要介绍了springboot跨域CORS处理代码解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 一 源(Origin) 源指URL的协议,域名,端口三部分组成,如果这个三个成分都相同,就判定是同源,否则为不同源. 同源策略(Same origin policy)是一种浏览器的约定,即在浏览器中禁止非同源访问. 二 CORS CORS即"跨域资源共享"(Cross-origin resource sharing),是一个W

  • Springboot跨域CORS处理实现原理

    一 源(Origin) 源指URL的协议,域名,端口三部分组成,如果这个三个成分都相同,就判定是同源,否则为不同源. 同源策略(Same origin policy)是一种浏览器的约定,即在浏览器中禁止非同源访问. 二 CORS CORS即"跨域资源共享"(Cross-origin resource sharing),是一个W3C标准.它允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了ajax只能同源使用的限制.springboot也提供了cors的解决方法.

  • Springboot处理CORS跨域请求的三种方法

    前言 Springboot跨域问题,是当前主流web开发人员都绕不开的难题.但我们首先要明确以下几点 跨域只存在于浏览器端,不存在于安卓/ios/Node.js/python/ java等其它环境 跨域请求能发出去,服务端能收到请求并正常返回结果,只是结果被浏览器拦截了. 之所以会跨域,是因为受到了同源策略的限制,同源策略要求源相同才能正常进行通信,即协议.域名.端口号都完全一致. 浏览器出于安全的考虑,使用 XMLHttpRequest对象发起 HTTP请求时必须遵守同源策略,否则就是跨域的H

  • 详解springboot设置cors跨域请求的两种方式

    1.第一种: public class CorsFilter extends OncePerRequestFilter { static final String ORIGIN = "Origin"; protected void doFilterInternal( HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOE

  • SpringBoot跨域Jsonp和Cors的方法

    有一次我的项目中采用了前后端分离的模式,引起了跨域问题,本文将介绍我所采用的跨域解决方法. 首先要了解产生跨域的本质,也就是同源策略的限制,源是指域名.端口号.协议,有一者不相同将被浏览器拒绝接受响应信息,(请求可以发送出去,但是浏览器不接受响应). 解决方法: 1. jsonp jsonp的原理的 src="" 属性不受同源策略的限制,动态创建一个callback回调函数,服务器调用回调函数把数据放进去,具体的细节打算以后做一个专门讲解. 这里给一个模版: $.ajax({ type

  • 基于SpringBoot解决CORS跨域的问题(@CrossOrigin)

    一.关于跨域介绍 在前后分离的架构下,跨域问题难免会遇见比如,站点 http://domain-a.com 的某 HTML 页面通过 的 src 请求 http://domain-b.com/image.jpg. 网络上的许多页面都会加载来自不同域的CSS样式表,图像和脚本等资源. 出于安全原因,浏览器限制从脚本内发起的跨源HTTP请求. 例如,XMLHttpRequest和Fetch API遵循同源策略. 这意味着使用这些API的Web应用程序只能从加载应用程序的同一个域请求HTTP资源,除非

  • 详解springboot解决CORS跨域的三种方式

    目录 一.实现WebMvcConfigurer接口 二.实现filter过滤器方式 三.注解@CrossOrigin 四.实战 五.cookie的跨域 一.实现WebMvcConfigurer接口 @Configuration public class WebConfig implements WebMvcConfigurer { /** * 添加跨域支持 */ @Override public void addCorsMappings(CorsRegistry registry) { // 允

  • SpringBoot解决ajax跨域问题的方法

    SpringBoot解决ajax跨域,供大家参考,具体内容如下 一.第一种方式 1.编写一个支持跨域请求的 Configuration import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.CorsRegistry; import org.springframework.web.servlet.config.anno

  • springboot 如何解决cross跨域请求的问题

    目录 springboot 解决cross跨域请求 1.使用ajax发送跨域请求接口时 2.在被跨域请求的一方配置 3.再次测试 4.对于只有个别需要开放跨域请求的接口可以这样玩 5.其它解决跨域请求的常用方法 Spring解决cross domain Spring4: Spring3旧版本: springboot 解决cross跨域请求 1.使用ajax发送跨域请求接口时 接口能正常接收到请求并响应,但是无法正常展示响应数据.跨域请求时会在有一个特别的请求头origin(请求来源). 浏览器认

  • SpringBoot整合JWT框架,解决Token跨域验证问题

    一.传统Session认证 1.认证过程 1.用户向服务器发送用户名和密码. 2.服务器验证后在当前对话(session)保存相关数据. 3.服务器向返回sessionId,写入客户端 Cookie. 4.客户端每次请求,需要通过 Cookie,将 sessionId 回传服务器. 5.服务器收到 sessionId,验证客户端. 2.存在问题 1.session保存在服务端,客户端访问高并发时,服务端压力大. 2.扩展性差,服务器集群,就需要 session 数据共享. 二.JWT简介 JWT

  • Springboot处理配置CORS跨域请求时碰到的坑

    最近开发过程中遇到了一个问题,之前没有太注意,这里记录一下.我用的SpringBoot版本是2.0.5,在跟前端联调的时候,有个请求因为用户权限不够就被拦截器拦截了,拦截器拦截之后打印日志然后response了一个错误返回了,但是前端Vue.js一直报如下跨域的错误,但是我是配置了跨域的. has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested res

  • 浅谈spring-boot 允许接口跨域并实现拦截(CORS)

    本文介绍了spring-boot 允许接口跨域并实现拦截(CORS),分享给大家,也给自己留个笔记 pom.xml(依赖的jar) // 在spring-boot-starter-web的启动器中,已经依赖好了 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependen

  • 解决Vue调用springboot接口403跨域问题

    最近在做一个前后端分离的项目, 前端用的是Vue后端使用的是springboot, 在项目整合的时候发现前端调用后端接口报错403跨域请求问题 前端跨域请求已解决, 那么问题就出在后端了, 找了一些资料找到了很多种方法, 这里说两个简单粗暴的. 注意:"@CrossOrigin"注解要求jdk1.8及以上版本, SpringMVC 4.2及以上版本 1. 在controller层上添加@Configuration注解, 如果没有效果请制定RequestMapping总的method类型

随机推荐