zoukankan      html  css  js  c++  java
  • 后端——框架——视图层框架——spring_mvc——《官网》阅读笔记——第一章节37(跨域,CROS)

    1、概念

    默认情况下,出于安全考虑,当前域名只能获取自己的相关资源,即无法进行跨域请求,跨域请求会自动失败。CORS的本质是放宽跨域请求的限制,即在一定条件下允许跨域条件。  

    CORS的全称为Cross-Origin Resource Sharing, 翻译即不同域名之间共享资源的一种机制。

    它的实现机制是在跨域请求上添加额外的请求头。它的请求方式也有三种。以下介绍它的请求方式和请求头

    1.1   请求方式

    请求方式有三种,Simple request,preflighted request, request with credentials。

    为了方便介绍概念,假设域名A向域名B发起了跨域请求,A为请求方,B为响应方。

    • Simple request:简单请求,即A直接向B发起了跨域请求,此时A为了标识自己的身份,在请求头上添加Origin字段,值为A的域名。B为了防止不合理的跨域请求,设定了很多条件,其中就包含允许的域名列表,首先会查询A是否在这个列表中,若不在,跨域请求失败,返回403。若存在,继续判断其他条件。
    • Preflighted request:预检请求,即A向B发起跨域请求之前,首先发送请求去查询B跨域请求的条件,预检请求成功之后,之后发送资源请求。预检请求与普通的资源请求是不同的,参考CorsUtils的isPreFlightRequest方法
    public static boolean isPreFlightRequest(HttpServletRequest request) {
    	return (HttpMethod.OPTIONS.matches(request.getMethod()) &&
    			request.getHeader(HttpHeaders.ORIGIN) != null &&
    	request.getHeader(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD) != null);
    }
    

      它有两个条件,第一个条件是请求方式必须是Options,第二个条件是请求头中同时存在Origin, ACCESS_CONTROL_REQUEST_METHOD其Origin表示A的身份,即A的域名,ACCESS_CONTROL_REQUEST_METHOD表示跨域资源请求的请求Method。还有一个请求头, ACCESS_CONTROL_REQUEST_HEADERS表示跨域资源请求中会包含哪些请求头(独有的)

    • Request with credentials:指跨域请求中包含敏感的数据信息,包含不限于Cookies,认证信息等等。假设A向B发送的请求中包含A域名的cookie信息,B可以修改这些Cookie数据。若包含用户信息,B域名甚至可以把这些用户信息记录在自己的服务器上。通常这种请求适用于B为了保护请求的安全性,需要一定的认证信息,A发送的跨域请求中包含认证信息,认证通过后才能获取。类似于公开文档和加密文档。B域名将请求分为公开请求和加密请求,或需要一定认证信息的请求

    1.2   请求头

    1. Origin:请求方的域名,请求方的身份标识
    2. ACCESS_CONTROL_REQUEST_METHOD: 请求方在发送跨域请求时会使用的请求方式
    3. ACCESS_CONTROL_REQUEST_HEADER:  请求方在发送跨域请求时会使用的独有的请求头。

    1.3   响应头

    1. Access-Control-Allow-Origin:规定的请求方域名列表,等价于白名单。
    2. Access-Control-Exposed-headers:跨域请求会返回哪些独有的响应头。
    3. Access-Control-Max-Age:预检请求的超时时间,它的单位是毫秒
    4. Access-Control-Allow-Credentials:跨域请求是否包含敏感信息,true表示包含,false表示否。
    5. Access-Control-Allow-Method:跨域请求的请求Method,与handler方法的请求Method的交集部分是跨域请求Method的条件。若不存在交集,则B中所有的资源都不允许其他域名访问。此时其他配置项毫无意义。

      Access-Control-Allow-Headers:跨域请求中,响应方规定的请求头信息。等价于API接口中规定会处理哪些参数。请求方多余的请求头会被忽略。若不满足B的请求头,有可能会失败。类似于API规定了参数,未提供必需参数,则会抛错。未提供其他参数也会影响API的逻辑处理

    2、配置

      配置的级别有三种,

    1. 第一种,范围最大,适用于所有URL匹配的请求。
    2. 第二种,范围次之,适用于当前Controller中的所有方法
    3. 第三种,范围最小,仅适用于当前handler方法

    2.1   配置项

      在配置之前了解一下配置项。可以参考@CrossOrigin的源码:

    1. Origins:响应方设置的安全域名列表,A向B发送跨域请求,必须满足A在安全域名列表中。类似于白名单
    2. allowedMethods:跨域请求的请求Method,A向B发送跨域请求时,必须满足请求Method在允许的范围内部,并且与资源请求的handler方法相匹配。例如当设置allowedMethods为POST时,B中请求方法为GET的所有handler都不支持跨域请求。
    3. allowedHeaders:它不是一个强制的条件,指B设定该资源请求只允许出现哪些请求头,若A向B发送的跨域请求包含了多余的请求头,这些请求头被忽略。
    4. exposedHeaders:它也不是一个强制的条件,指B设定该资源请求会返回哪些响应头,类似于API接口,allowedHeaders相当于需要哪些参数,exposedHeaders相当于会返回哪些值。
    5. allowCredentials:相当于B为该资源请求加密,此时A向B发送跨域请求信息,需要提供认证的信息。若B没有任何机制去使用A提供的敏感信息,那么可以选择把此项去掉。因为A提供的敏感信息存在被窃取的情况。
    6. maxAge:只适用于预检请求,表示预检成功之后会被缓存的超时时间。后续的请求在超时时间之内无需再次预检。它的单位是秒,不是毫秒。

      通常情况下,无法全局配置allowedHeaders, exposedHeaders, allowCredentials。它们需根据资源请求视情况而定。类似于你无法为所有API接口定义通用的参数和返回值,每个API接口都有自己的情况

    2.2   全局配置

      全局配置有两种方式,代码方式和XML配置文件方式。

      代码方式:实现WebMvcConfigurer, 重写addCrosMapping方法。示例如下:

    public void addCorsMappings(CorsRegistry registry) {
    	// 跨域的全局配置项
    	registry.addMapping("/**").allowedOrigins("*")
    			.allowedMethods("GET","POST","OPTIONS")
    			.allowedHeaders("Content-Type", "Some Header")
    			.exposedHeaders("")
    			.allowCredentials(true).maxAge(3600);
    }
    

      XML配置文件:引入mvc的schema,配置cros子标签

    <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="true"
    	max-age="123" />
    </mvc:cors>
    

    2.3   controller配置

      类似于@RequestMapping,只是为了将handler方法中公共的CrossOrigin配置提取到Controller类上,若handler方法和Controller类上出现相同的项,handler方法上的配置项有更高的优先级。

      在Controller类上添加@CrossOrigin注解即可。

    2.4   handler方法配置

      在handler方法上添加@CrossOrigin注解即可,它只适用当前handler方法。所以更适用于配置allowedHeaders, exposedHeaders, allowCredentials这些项。

    3、过滤器

      Mvc提供了CrosFilter用于请求的跨域拦截,相当于将跨域请求的判定请求提前到Filter链阶段。了解Servlet知道,Servlet处理请求的过程,先执行过滤器链,在执行service方法。

      对于mvc而言,它将判定请求提前到DispatcherServlet的service方法之前。此时还未进行mvc处理请求的核心流程,未经过拦截器,handlerMapping,HandlerAdapater等等的处理。

      使用CrosFilter的步骤如下:

      配置CrosFilter,绑定URL和添加跨域请求的条件。

    CorsConfiguration config = new CorsConfiguration();
    // Possibly...
    // config.applyPermitDefaultValues()
    config.setAllowCredentials(true);
    config.addAllowedOrigin("http://domain1.com");
    config.addAllowedHeader("*");
    config.addAllowedMethod("*");
    UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
    source.registerCorsConfiguration("/**", config);
    CorsFilter filter = new CorsFilter(source);
    

      过滤器的配置方式与其他Filter的方式相同,

    // 添加过滤器,filter为之前创建的CorsFilter
    FilterRegistration.Dynamic filterRegistration = 
    servletContext.addFilter("crosFilter", filter);
    // 配置请求的分发类型
    EnumSet<DispatcherType> dispatchers = 
    EnumSet.of(DispatcherType.REQUEST, DispatcherType.ASYNC, 
    DispatcherType.FORWARD, DispatcherType.INCLUDE);
    // 过滤器拦截dispatcherServlet
    filterRegistration.addMappingForServletNames(dispatchers, true, "dispatcherServlet");
    

      在web.xml中配置也是同样的。

  • 相关阅读:
    浏览器驱动
    django中的cookie和session
    django自定义中间件实现登陆
    django虚拟环境与文件上传
    了解和熟悉数据库相关知识
    JMeter ---相关脚本笔记
    JMeter脚本---关于时间戳的处理笔记
    JMeter中的读取json数据---JSON Extractor插件
    更多API知识学习
    认识VIM编辑器
  • 原文地址:https://www.cnblogs.com/rain144576/p/12902901.html
Copyright © 2011-2022 走看看