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

网友投稿 421 2022-11-04


基于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://example.com/index.html ==> http://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 {};

/**

* 所有支持域的集合,例如"httlLSmMxPgp://domain1.com"。

*

这些值都显示在请求头中的Access-Control-Allow-Origin

* "*"代表所有域的请求都支持

*

如果没有定义,所有请求的域都支持

* @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的有http://效期 单位为秒

//若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){

//此处省略相应代码

}

}

后台返回的数据

前端跨域请求

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

参考

跨域 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版本。


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:学历查询网API(学历查询网登录入口手机版)
下一篇:Android的开源与闭源
相关文章

 发表评论

暂时没有评论,来抢沙发吧~