Springboot整合web学习之CORS跨域相关学习整理

本文详细介绍了CORS跨域的概念、原因及解决策略,包括全局和局部跨域配置,自定义filter、WebMvcConfigurer和使用@CrossOrigin注解的方法,以及nginx和Java后台的实现步骤。
摘要由CSDN通过智能技术生成

Springboot整合web学习之CORS跨域相关学习整理

一、什么是CORS跨域?

CORS 是一个W3C标准,全称是跨域资源共享(Cross-origin resource sharing)。

CORS 是一种基于 HTTP Header 的机制,该机制可以允许服务器除了它自己之外的其他域获取到非同源限制资源。服务器端配合浏览器实现 CORS 机制,可以突破浏览器对跨域资源访问的限制,实现跨域资源请求。

二、什么是跨域?

域=协议+域名+端口
当一个请求的协议、域名、端口三者之前任意一个与当前界面不一致,就叫跨域。

三、为什么会出现跨域问题?

是因为浏览器的同源策略限制。同源策略是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响。
同源策略作用就是会阻止一个域的javascript脚本和另外一个域的内容进行交互。
同源策略是一种安全限制

四、非同源限制了哪些信息?

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

五、如何解决跨域?

  • jsonp(平时工作不常用,不作了解)
  • nginx反向代理(这里不做解释)
  • CORS(跨域资源共享)

六、CORS提供header部分

Access-Control-Request-Method–指明请求方法
Access-Control-Request-Headers–指明请求携带字段
Access-Control-Allow-Origin–指明响应允许的域(CORS时必选,其他的都是可选),可以是一个或者多个
Access-Control-Allow-Credentials–如果为true,标识跨域请求携带cookie,此时Access-Control-Allow-Origin值不能设置为*,必须指明确。
Access-Control-Allow-Methods–指明响应方法
Access-Control-Allow-Headers–指明响应携带字段
Access-Control-Expose-Headers–指明响应哪些信息可以对外显示
Access-Control-Max-Age–指明响应时间

七、CORS跨域根本方法

解决方法就是在资源的头中加入Access-Control-Allow-Origin 指定你授权的域。

示例如下:
如www.aaa.com需要提取www.bbb.com的资源信息,就需要在www.bb.com服务端添加:

Access-Control-Allow-Origin: http://www.aaa.com
Access-Control-Allow-Credentials: true (可选,为true时会获取到cookie信息)

如www.bbb.com允许所有网站获取信息,则添加:

Access-Control-Allow-Origin: * ;

八、nginx如何添加?

add_header Access-Control-Allow-Origin *;

location /{
	add_header Access-Control-Allow-Origin *;
}

重启服务即可。

九、java后台如何添加CORS?

  • 自定义filter完成跨域(全局跨域,SpringMVC 3 及之前的版本)
  • 手动设置响应头(局部跨域)
  • 重写 WebMvcConfigurer(全局跨域,也可以匹配路径)
  • 类或者方法名上使用@CrossOrigin注解(局部跨域)
  • 返回新的CorsFilter

示例情况:本地起两个服务,

B服务:localhost:8081;
服务代码:
引入jquery.js,

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>CORS跨域效果验证</title>
    <script src="js/jquery/jquery.js"></script>
</head>
<body>
    <div id="message"></div>
    <input type="button" value="提交" onclick="submitData()"><br>
    <input type="button" value="删除" onclick="deleteData()"><br>
    <input type="button" value="局部跨域1" onclick="cors1()"><br>
    <input type="button" value="局部跨域2" onclick="cors2()"><br>
<script>
    function submitData() {
        $.ajax({
            url:'http://localhost:8080/api/hello',
            type:'GET',
            success:function (msg) {
                $("#message").html(msg);
            }
        })
    }
    function deleteData() {
        $.ajax({
            url:'http://localhost:8080/api/demo',
            type:'GET',
            success:function (msg) {
                $("#message").html(msg);
            }
        })
    }
    function cors1() {
        $.ajax({
            url:'http://localhost:8080/api/cors/1',
            type:'GET',
            success:function (msg) {
                $("#message").html(msg);
            }
        })
    }
    function cors2() {
        $.ajax({
            url:'http://localhost:8080/api/cors/2',
            type:'GET',
            success:function (msg) {
                $("#message").html(msg);
            }
        })
    }
</script>
</body>
</html>

A服务:localhost:8080;

1、自定义filter完成跨域(全局跨域,SpringMVC 3 及之前的版本

/**
 * FileName: MyCorsFilter
 * Author:   Administrator
 * Date:     2021/2/22 16:54
 * Description: 过滤器完成跨域设置
 * History:
 * <author>          <time>          <version>          <desc>
 * 作者姓名           修改时间           版本号              描述
 */
package com.yangxf.si.config.cors;

import org.springframework.stereotype.Component;

import javax.servlet.*;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * 〈SpringMVC3以及之前的版本通过如下方式完成CORS〉<br>
 * 〈过滤器完成跨域设置〉
 *
 * @author Administrator
 * @create 2021/2/22
 * @since 1.0.0
 */
@Component
public class MyCorsFilter implements Filter {

    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
        HttpServletResponse response = (HttpServletResponse) res;
        response.setHeader("Access-Control-Allow-Origin", "http://localhost:8081");
        response.setHeader("Access-Control-Allow-Credentials", "true");
        response.setHeader("Access-Control-Allow-Methods", "GET, HEAD, POST, PUT, DELETE, TRACE, OPTIONS, PATCH");
        response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type,Token,Accept, Connection, User-Agent, Cookie");
        response.setHeader("Access-Control-Max-Age", "3600");

        System.out.println("设置跨域请求");
        chain.doFilter(req, response);
    }
    @Override

    public void init(FilterConfig filterConfig) {
    }
    @Override

    public void destroy() {
    }
}

2、手动设置响应头(局部跨域)

@RequestMapping("/")
public String demo(HttpServletResponse response) {
            response.setHeader("Access-Control-Allow-Origin", "http://localhost:8081");
        response.setHeader("Access-Control-Allow-Credentials", "true");
        response.setHeader("Access-Control-Allow-Methods", "GET, HEAD, POST, PUT, DELETE, TRACE, OPTIONS, PATCH");
        response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type,Token,Accept, Connection, User-Agent, Cookie");
        response.setHeader("Access-Control-Max-Age", "3600");
        System.out.println("设置跨域请求");
    return "demo";
}

3、重写 WebMvcConfigurer

注:该方法使用的情况下,项目中不能有自定义拦截器,否则跨域配置将失效。

/**
 * FileName: CorsConfig
 * Author:   Administrator
 * Date:     2021/2/23 9:07
 * Description: 重写 WebMvcConfigurer(全局跨域)
 * History:
 * <author>          <time>          <version>          <desc>
 * 作者姓名           修改时间           版本号              描述
 */
package com.yangxf.si.config.cors;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

/**
 * 〈一句话功能简述〉<br> 
 * 〈重写 WebMvcConfigurer(全局跨域)〉
 *
 * @author Administrator
 * @create 2021/2/23
 * @since 1.0.0
 */
@Configuration
public class CorsConfig implements WebMvcConfigurer {
    /**
     * 但是使用此方法配置之后再使用自定义拦截器时跨域相关配置就会失效。
     *
     * 原因是请求经过的先后顺序问题,当请求到来时会先进入拦截器中,而不是进入 Mapping 映射中,所以返回的头信息中并没有配置的跨域信息。浏览器就会报跨域异常。
     * 不建议用
     * @param registry
     */
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/hello")
                //是否发送Cookie
                .allowCredentials(true)
                .allowedOrigins("http://localhost:8081")
                .allowedMethods(new String[]{"GET", "POST", "PUT", "DELETE"})
                .allowedHeaders("*")
                .maxAge(3600);
    }
}

4、类或者方法名上使用@CrossOrigin注解(局部跨域,与3配置的路径无冲突)

当在类以及方法名上同时配置不同的域时,两个都可以跨域,不存在优先级情况,已验证。

/**
 * FileName: CrossOriginController
 * Author:   Administrator
 * Date:     2021/2/23 10:30
 * Description: 局部跨域测试控制器
 * History:
 * <author>          <time>          <version>          <desc>
 * 作者姓名           修改时间           版本号              描述
 */
package com.yangxf.si.modules.business.controller.cors;

import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * 〈一句话功能简述〉<br> 
 * 〈局部跨域测试控制器〉
 *
 * @author Adminitrator
 * @create 2021/2/23
 * @since 1.0.0
 */
@CrossOrigin("http://localhost:8081")
@RestController
public class CrossOriginController {

    @GetMapping(value="/cors/1")
    public String cors1(){
        return "跨域测试1";
    }

    @CrossOrigin(value="http://localhost:8082")
    @GetMapping(value="/cors/2")
    public String cors2(){
        return "跨域测试2";
    }
}

5、返回新的CorsFilter

/**
 * FileName: NewCorsFilter
 * Author:   Administrator
 * Date:     2021/2/23 10:56
 * Description: 返回新的 CorsFilter
 * History:
 * <author>          <time>          <version>          <desc>
 * 作者姓名           修改时间           版本号              描述
 */
package com.yangxf.si.config.cors;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpHeaders;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;

/**
 * 〈一句话功能简述〉<br>
 * 〈返回新的 CorsFilter〉
 *
 * @author Administrator
 * @create 2021/2/23
 * @since 1.0.0
 */
@Configuration
public class NewCorsFilter {
    @Bean
    public CorsFilter corsFilter() {
        // 添加 CORS配置信息
        CorsConfiguration config = new CorsConfiguration();
        //放行域
        config.addAllowedOrigin("*");
        //是否发送 Cookie
        config.setAllowCredentials(true);
        //放行请求方式
        config.addAllowedMethod("*");
        //放行请求头部信息
        config.addAllowedHeader("*");
        //暴露头部信息--不能默认*
        config.addExposedHeader(HttpHeaders.ACCEPT);
        //映射路径
        UrlBasedCorsConfigurationSource corsConfigurationSource = new UrlBasedCorsConfigurationSource();
        corsConfigurationSource.registerCorsConfiguration("/**", config);
        //返回新的CorsFilter
        return new CorsFilter(corsConfigurationSource);
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

lwd2307997664

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值