【SpringBoot学习 | 4】添加支持CORS跨域访问

一、跨域概念

1. 跨域分类

URL说明是否允许通信
http://www.demo.com/a.js
http://www.demo.com/b.js同一域名,不同文件或路径允许
http://www.demo.com/lab/c.js
http://www.demo.com:8000/a.js
http://www.demo.com/b.js同一域名,不同端口不允许
http://www.demo.com/a.js
https://www.demo.com/b.js同一域名,不同协议不允许
http://www.demo.com/a.js
http://127.0.0.1/b.js域名和域名对应相同ip不允许
http://www.demo.com/a.js
http://x.demo.com/b.js主域相同,子域不同不允许
http://demo.com/c.js
http://www.demo1.com/a.js
http://www.demo2.com/b.js不同域名不允许

2. 跨域解决方案

  1. 通过jsonp跨域
  2. document.domain + iframe跨域
  3. location.hash + iframe
  4. window.name + iframe跨域
  5. postMessage跨域
  6. 跨域资源共享(CORS)?
  7. nginx代理跨域
  8. nodejs中间件代理跨域
  9. WebSocket协议跨域

本文采用CORS后端解决跨域问题,前端无需配置:

CORS(Cross-Origin Resource Sharing)“跨域资源共享”,是一个W3C标准,它允许浏览器向跨域服务器发送Ajax请求,打破了Ajax只能访问本站内的资源限制,CORS在很多地方都有被使用,微信支付的JS支付就是通过JS向微信服务器发送跨域请求。开放Ajax访问可被跨域访问的服务器大大减少了后台开发的工作,前后台工作也可以得到很好的明确以及分工,下面我们就看讲一下如何让你的SpringBoot项目支持CORS跨域。

二、Cors跨域配置

目标:基于SpringBooot项目搭建可以站外Ajax请求访问的跨域资源服务器。

  1. 搭建Springboot项目
    主要是配置web服务,为了简单演示,暂时用不上数据库查询。

    项目创建参考:【Springboot学习 | 2】jpa+mysql8.0增删改查
    细节处理参考:【Springboot学习 | 3】配置使用FastJson返回Json视图

  2. 创建CorsConfig全局配置,在Controller前加上@CrossOrigin注解,即可支持跨域访问:
    在这里插入图片描述

CorsConfig.java

package com.springboot.three;

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

/**
 * 全局配置
 */
@Configuration//一定得加上
public class CorsConfig extends WebMvcConfigurerAdapter {
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")//配置可以被跨域的路径
                .allowedOrigins("*")//允许所有的请求域名访问我们的跨域资源
                .allowCredentials(true)//是否允许用户发送、处理 cookie
                .allowedMethods("GET", "POST", "DELETE", "PUT")//允许所有的请求方法访问该跨域资源服务器
                .maxAge(3600);//预检请求的有效期,单位为秒。有效期内,不会重复发送预检请求
    }
}

CORSConfiguration配置类继承了WebMvcConfiugrationAdaper父类并且重写了addCorsMappings方法。

属性说明
1addMapping配置可以被跨域的路径,可以任意配置,可以具体到直接请求路径
2allowedMethods允许所有的请求方法访问该跨域资源服务器,如:POST、GET、PUT、DELETE等
3allowedOrigins允许所有的请求域名访问我们的跨域资源,可以固定单条或者多条内容,如:“http://127.0.0.1:8848”,只有这个地址及端口号才可以访问我们的跨域资源
4allowedHeaders允许所有的请求header访问,可以自定义设置任意请求头信息,如:“X-YAUTH-TOKEN”
5maxAge预检请求的有效期,单位为秒。有效期内,不会重复发送预检请求

三、初次测试

在controller方法前加上@CrossOrigin注解

package com.springboot.three.controller;

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

@RestController
//实现跨域注解
//origin="*"代表所有域名都可访问
//maxAge飞行前响应的缓存持续时间的最大年龄,简单来说就是Cookie的有效期 单位为秒
//若maxAge是负数,则代表为临时Cookie,不会被持久化,Cookie信息保存在浏览器内存中,浏览器关闭Cookie就消失
@CrossOrigin(origins = "*",maxAge = 3600)//@CrossOrigin(origins = "http://localhost:8848", maxAge = 3600)
public class IndexController {
    @RequestMapping(value = "/cors")
    public String corsIndex(){
        return "this is cors info";
    }
}

前端测试:

这里在任意地方创建mytest项目,包含jQuery和test.html即可;我这里咋HBuilder创建效果如下,在html中只写一个ajax作为Cors跨域测试:
在这里插入图片描述
test.html:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
        <title>cors-demo</title>
		<link rel="stylesheet" href="css/bootstrap.min.css">
        <script type="text/javascript" src="js/jquery-3.4.1.min.js" ></script>
    </head>
    <body>
        <input type="button"value="测试" οnclick="ajaxloding()" />
        <div id="corsmessage"></div>
        <script>
            var getdata=0;
            function ajaxloding(){
                $.ajax({
                    async:false,
                    type:"get",
                    url:"http://localhost:8080/cors",
                    contentType: "application/x-www-form-urlencoded",
                    dataType: "json",
                    data: {},
                    success:function(result){
						console.log(result);
                        getdata=result
                    },
                    error: function (errorMsg) {
                        //请求失败时执行该函数
                        alert("请求数据失败!");
                    }
                });
                $("#corsmessage").text(getdata)
            }
        </script>
    </body>
</html>

运行结果:

  1. 提前运行springboot,端口在8080
  2. 在HBuilder端运行默认端口为8848,和springboot部署的8080满足跨域要求(如果没有HBuilder,可以在局域网下,另一台电脑打开html,端口不一致实现测试要求)
  3. 点击button,成功实现跨域:返回信息。
    在这里插入图片描述
    如果注释掉controller中的@CrossOrigin标签,会显示被cors拒绝访问。
    在这里插入图片描述

四、cors跨域原理解析

一个 CORS 配置用一个CorsConfiguration类来表示,它的定义如下:

public class CorsConfiguration {
    private List<String> allowedOrigins;
    private List<String> allowedMethods;
    private List<String> allowedHeaders;
    private List<String> exposedHeaders;
    private Boolean allowCredentials;
    private Long maxAge;
}

Spring`中对 CORS 规则的校验,都是通过委托给DefaultCorsProcessor实现的。

DefaultCorsProcessor 处理过程如下:

  1. 判断依据是Header中是否包含Origin。如果包含则说明为CORS请求,转到 2;否则,说明不是 CORS 请求,不作任何处理。
  2. 判断 responseHeader是否已经包含 Access-Control-Allow-Origin,如果包含,证明已经被处理过了, 转到 3,否则不再处理。
  3. 判断是否同源,如果是则转交给负责该请求的类处理
  4. 是否配置了 CORS 规则,如果没有配置,且是预检请求,则拒绝该请求,如果没有配置,且不是预检请求,则交给负责该请求的类处理。如果配置了,则对该请求进行校验。

校验就是根据 CorsConfiguration这个类的配置进行判断:

  1. 判断origin 是否合法
  2. 判断method是否合法
  3. 判断header是否合法
  4. 如果全部合法,则在response header中添加响应的字段,并交给负责该请求的类处理,如果不合法,则拒绝该请求。

ps.查资料时发现,如果allowedOrigins("*"),无法使用cookies,具体还没验证,等用到时再回来补充;
在这里插入图片描述
解决方法参考:跨域丢失cookie的问题

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值