SpringBoot之跨域过滤器配置允许跨域访问方式_第1页
SpringBoot之跨域过滤器配置允许跨域访问方式_第2页
SpringBoot之跨域过滤器配置允许跨域访问方式_第3页
SpringBoot之跨域过滤器配置允许跨域访问方式_第4页
SpringBoot之跨域过滤器配置允许跨域访问方式_第5页
已阅读5页,还剩8页未读, 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第SpringBoot之跨域过滤器配置允许跨域访问方式目录SpringBoot跨域过滤器配置允许跨域访问跨域请求问题背景跨域过滤器跨域功能改进SpringBoot跨域设置(CORS)一、什么是跨域二、跨域资源共享(CORS)1.简单请求2.非简单请求三、SpringBoot设置CORS

SpringBoot跨域过滤器配置允许跨域访问

跨域请求

当一个资源从与该资源本身所在的服务器不同的域或端口请求一个资源时,资源会发起一个跨域HTTP请求。

出于安全原因,浏览器限制从脚本内发起的跨源HTTP请求。例如,XMLHttpRequest和FetchAPI遵循同源策略。这意味着使用这些API的Web应用程序只能从加载应用程序的同一个域请求HTTP资源,除非使用CORS头文件。

问题背景

如果前端提示Access-Control-Allow-Origin问题

XMLHttpRequestcannotloadhttp://xxxxxxxxxx/.NoAccess-Control-Allow-Originheaderispresentontherequestedresource.Originnullisthereforenotallowedaccess.

跨域过滤器

那么需要再SpringBoot2配置跨域过滤器允许跨域访问。

importjava.io.IOException;

importjavax.servlet.Filter;

importjavax.servlet.FilterChain;

importjavax.servlet.FilterConfig;

importjavax.servlet.ServletException;

importjavax.servlet.ServletRequest;

importjavax.servlet.ServletResponse;

importjavax.servlet.http.HttpServletRequest;

importjavax.servlet.http.HttpServletResponse;

importorg.springframework.stereotype.Component;

@Component

publicclassCorsFilterimplementsFilter{

@Override

publicvoiddoFilter(ServletRequestreq,ServletResponseres,FilterChainchain)throwsIOException,ServletException{

HttpServletRequestrequest=(HttpServletRequest)req;

HttpServletResponseresponse=(HttpServletResponse)res;

response.setHeader("Access-Control-Allow-Origin","*");

response.setHeader("Access-Control-Allow-Methods","POST,GET,OPTIONS,DELETE,PUT,GET");

response.setHeader("Access-Control-Max-Age","3600");

response.setHeader("Access-Control-Allow-Headers","x-requested-with");

chain.doFilter(req,res);

}

@Override

publicvoidinit(FilterConfigfilterConfig){}

@Override

publicvoiddestroy(){}

}

跨域功能改进

如果需要显示跨域地址,还可以在里面加上访问来源打印语句,供排查

StringcurOrigin=request.getHeader("Origin");

System.out.println("###跨域过滤器-当前访问来源-"+curOrigin+"###");

如果需要跨域权限,可以判断一下来源

StringcurOrigin=request.getHeader("Origin");

System.out.println("###跨域过滤器-当前访问来源-"+curOrigin+"###");

if(curOrigin.indexOf(":8080")-1){

response.setHeader("Access-Control-Allow-Origin","*");

}

关于跨域访问更专业的内容,可以访问Mozilla官方的一个关于CROS文章

/zh-CN/docs/Web/HTTP/Access_control_CORS

SpringBoot跨域设置(CORS)

一、什么是跨域

请求url的协议、域名、端口三者有任意一个不同即为跨域。跨域问题是因为浏览器的同源策略的限制而产生的。

同源:请求url的协议、域名、端口三者都相同即为同源(同一个域)。同源策略:同源策略(Sameoriginpolicy)是一种约定,他是浏览器最核心也最基本的安全功能。同源策略会阻止非同源(同一个域)的内容进行交互。

同源策略的限制:

无法读取非同源网页的Cookie、LocalStorage和IndexedDB无法接触非同源网页的DOM无法向非同源地址发送AJAX请求

浏览器的同源策略会限制跨域请求,限制的方式一般有两种:

浏览器限制发起跨域请求;跨域请求可以正常发起,但是返回的结果被浏览器拦截了。

一般浏览器都是第二种方式限制跨域请求,那就是说请求已到达服务器,并有可能对数据库里的数据进行了操作,但是返回的结果被浏览器拦截了,那么我们就获取不到返回结果,这是一次失败的请求,但是可能对数据库里的数据产生了影响。

为了防止这种情况的发生,规范要求,对这种可能对服务器数据产生副作用的HTTP请求方法,浏览器必须先使用OPTIONS方法发起一个预检请求,从而获知服务器是否允许该跨域请求:如果允许,就发送带数据的真实请求;如果不允许,则阻止发送带数据的真实请求。

二、跨域资源共享(CORS)

解决非同源内容无法交互的问题,目前主流的解决方案就是:CORS(跨域资源共享)。

跨域资源共享(Cross-originResourceSharing)简称CORS,它突破了一个请求在浏览器发出只能在同源的情况下向服务器获取数据的限制。

CORS约定服务器端和浏览器在HTTP协议之上,通过一些额外HTTP头部信息,进行跨域资源共享的协商。服务器端和浏览器都必需遵循规范中的要求。

CORS把HTTP的跨域请求分成两类,简单请求和非简单请求,不同请求按照不同的策略进行跨域资源共享协商。

1.简单请求

简单跨域请求需满足的条件:

1.请求方法是GET、HEAD或者POST(POST时,Content-Type的值必须是application/x-www-form-urlencoded、multipart/form-data、text/plain中的一个值);

2.请求中没有自定义HTTP请求头。

HTTP头只能时下面这些字段:

AcceptAccept-LanguageContent-LanguageDPRDownlinkSave-DataViewport-WidthWidthContent-Type

以上两点都满足才是简单跨域请求。

对于简单跨域请求,处理方式如下:

1.浏览器要做的就是在HTTP请求头中添加Origin,将JavaScript脚本所在域填充进去,向其他域的服务器请求资源。

Origin:

Origin字段用来说明,本次请求来自哪个源(协议+域名+端口)。服务器根据这个值,决定是否同意这次请求。

2.服务器端收到一个简单跨域请求后,根据资源权限配置,在响应头中添加Access-Control-Allow-Origin。

如果Origin指定的源,不在许可范围内,服务器会返回一个正常的HTTP回应。但这个响应头信息没有包含Access-Control-Allow-Origin字段,浏览器就知道该域名不在许可范围内。

如果Origin指定的域名在许可范围内,服务器返回的响应,会多出几个头信息字段:

Access-Control-Allow-Origin:

Access-Control-Allow-Credentials:true

Access-Control-Expose-Headers:My-Token

Access-Control-Allow-Origin:该字段是必须的。它的值要么是请求时Origin字段的值,要么是一个*值,表示接受任意域名的请求。Access-Control-Allow-Credentials:该字段是可选的。它的值是一个布尔值,表示是否允许发送Cookie。默认情况下,Cookie不包括在CORS请求之中。设为true,即表示服务器明确许可,Cookie可以包含在请求中,一起发给服务器。这个值也只能设为true,如果服务器不要浏览器发送Cookie,删除该字段即可。Access-Control-Expose-Headers:该字段是可选的。CORS请求时,XMLHttpRequest对象的getResponseHeader()方法只能拿到6个基本字段:Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma。如果想拿到其他字段,就必须在Access-Control-Expose-Headers里面指定。

3.浏览器收到响应后,通过获取响应头中的Access-Control-Allow-Origin字段,来判断如果当前域已经得到授权,则将结果返回给JavaScript。否则浏览器忽略此次响应。

2.非简单请求

非简单跨域请求需满足的条件:

除GET、HEAD和POST(Content-Type的值是:application/x-www-form-urlencoded、multipart/form-data、text/plain中的一个值)以外的其他HTTP方法如:PUT、DELETE、TRACE、PATCH、POST(Content-Type的值是:application/json)。请求中有自定义HTTP头部。

以上两点只要至少满足其中一点就是非简单跨域请求。

对于非简单跨域请求,处理方式如下:

1.浏览器在发送真实HTTP请求之前先发送一个OPTIONS的预检请求,检测服务器端是否支持真实请求进行跨域资源访问。

真实请求的信息在OPTIONS请求中通过请求头中的Access-Control-Request-Method和Access-Control-Request-Headers字段来描述。此外与简单跨域请求一样,请求头中也会有Origin字段。

Origin:

Access-Control-Request-Method:PUT

Access-Control-Request-Headers:Header1,Header2

Origin:必须字段,用于指定请求源。Access-Control-Request-Method:必须字段,用于描述真实请求的方法(PUT、DELETE等)。Access-Control-Request-Headers:指定真实请求会额外发送的请求头字段信息。

2.服务器端接到预检请求后,会检查了Origin、Access-Control-Request-Method和Access-Control-Request-Headers字段,检验是否允许跨源请求。

如果不允许该跨域请求,会返回一个正常的HTTP回应,但这个响应头信息没有包含Access-Control-Allow-Origin字段,浏览器就知道该域名不在许可范围内。

如果允许该跨域请求,就会在响应头中放入Access-Control-Allow-Origin、Access-Control-Allow-Methods和Access-Control-Allow-Headers,分别表示允许跨域资源请求的域、请求方法和请求头。此外,服务器端还可以在响应头中放入Access-Control-Max-Age,允许浏览器在指定时间内,无需再发送预检请求进行协商,直接用本次协商结果即可。

Access-Control-Allow-Origin:

Access-Control-Allow-Methods:GET,POST,PUT

Access-Control-Allow-Headers:Header1,Header2,Header3

Access-Control-Allow-Credentials:true

Access-Control-Max-Age:1728000

Access-Control-Allow-Methods:该字段必需,它的值是逗号分隔的一个字符串,表明服务器支持的所有跨域请求的方法。注意,返回的是所有支持的方法,而不单是浏览器请求的那个方法。这是为了避免多次预检请求。Access-Control-Allow-Headers:如果浏览器请求包括Access-Control-Request-Headers字段,则Access-Control-Allow-Headers字段是必需的。它也是一个逗号分隔的字符串,表明服务器支持的所有头信息字段,不限于浏览器在预检中请求的字段。Access-Control-Allow-Credentials:该字段与简单请求时的含义相同。它的值是一个布尔值,表示是否允许发送Cookie。默认情况下,Cookie不包括在CORS请求之中。设为true,即表示服务器明确许可,Cookie可以包含在请求中,一起发给服务器。这个值也只能设为true,如果服务器不要浏览器发送Cookie,删除该字段即可。Access-Control-Max-Age:该字段可选,用来指定本次预检请求的有效期,单位为秒。上面结果中,有效期是20天(1728000秒),即允许缓存该条回应1728000秒(即20天),在此期间,不用发出另一条预检请求。

浏览器根据OPTIONS请求返回的结果来决定是否继续发送真实的请求进行跨域资源访问。这个过程对真实请求的调用者来说是透明的。

三、SpringBoot设置CORS

SpringBoot设置CORS的的本质都是通过设置响应头信息来告诉前端该请求是否支持跨域。

SpringBoot设置CORS的方式主要有以下三种。

1.配置过滤器CorsFilter

@Configuration

publicclassCorsConfig{

@Bean

CorsFiltercorsFilter(){

CorsConfigurationconfiguration=newCorsConfiguration();

configuration.setAllowedOrigins(Arrays.asList("*"));

configuration.setAllowedMethods(Arrays.asList("*"));

configuration.setAllowedHeaders(Arrays.asList("*"));

configuration.setAllowCredentials(true);

UrlBasedCorsConfigurationSourcesource=newUrlBasedCorsConfigurationSource();

source.registerCorsConfiguration("/**",configuration);

returnnewCorsFilter(source);

}

}

2.实现接口WebMvcConfigurer

@Configuration

publicclassWebMvcConfigimplementsWebMvcConfigurer{

@Override

publicvoidaddCorsMappings(CorsRegistryregistry){

registry.addMapping("/**")

.allowedOrigins("*")

.allowedHeaders("*")

.allowedMethods("*")

.allowCredentials(true);

}

}

3.使用注解@CrossOrigin

@CrossOrigin注解可以用在类或者方法上

用在控制器类上,表示该类的所有方法都允许跨域

@RestController

@CrossOrigin

publicclassTestController{

@GetMapping("test")

publicStringtest(){

return"success";

}

}

用在控制器方法上,表示该方法都允许跨域

@RestController

publicclassTestController{

@CrossOrigin

@GetMapping("test")

publicStringtest(){

return"success";

}

}

@CrossOrigin注解源码

@Target({ElementType.TYPE,ElementType.METHOD})

@Retention(RetentionPolicy.RUNTIME)

@Documented

public@interfaceCrossOrigin{

/**

*这origins和value是一样的

*允许来源域名的列表,例如,匹配的域名是跨域预请求Response头中的Access-Control-Aloow_origin字段值。

*不设置确切值时默认支持所有域名跨域访问。

*/

@AliasFor("origins")

String[]value()default{};

@AliasFor("value")

String[]origins()default{};

/**

*高版本下Spring2.4.4使用originPatterns而不是value和origins

*/

String[]originPatterns()default{};

/**

*跨域请求中允许的请求头中的字段类型,该值对应跨域预请求Response头中的Access-Control-Allow-Headers字段值。

*

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

最新文档

评论

0/150

提交评论