springboot系列六 cors跨域支持

CORS理解

CORS(Cross-Origin Resource Sharing) 跨域资源共享
浏览器在访问当前域名下的资源时,能直接传输数据。但是出于安全考虑,浏览器在访问非当前域名的资源时会遇到跨域访问限制
这时候我们需要一种机制:跨域资源共享(cors)

cors的请求类型

来自 CORS简介(作者 loveis715)

简单请求(Simple Request)

如果一个请求没有包含任何自定义请求头,而且它所使用HTTP动词是GET,HEAD或POST之一,那么它就是一个Simple Request。但是在使用POST作为请求的动词时,该请求的Content-Type需要是application/x-www-form-urlencoded,multipart/form-data或text/plain之一。

预检请求(Preflighted Request)

如果一个请求包含了任何自定义请求头,或者它所使用的HTTP动词是GET,HEAD或POST之外的任何一个动词,那么它就是一个Preflighted Request。如果POST请求的Content-Type并不是application/x-www-form-urlencoded,multipart/form-data或text/plain之一,那么其也是Preflighted Request。

带凭证的请求(Requests with Credential)

一般情况下,一个跨域请求不会包含当前页面的用户凭证。一旦一个跨域请求包含了当前页面的用户凭证,那么其就属于Requests with Credential。

springboot的cors支持

场景

springboot提供api服务(端口8080),前端通过jquery发送http请求(端口63342),由于端口不同,会造成跨域访问

代码

springboot接口

@GetMapping("/api/cors/get")
    public String get(){
        return "cors test get method";
    }
@PostMapping("/api/cors/post")
    public String post(){
        return "cors test post method";
    }

前端代码:cors.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>cors跨域测试</title>
    <script src="https://cdn.bootcss.com/jquery/2.1.0/jquery.min.js"></script>
    <script type="text/javascript">
        function crosGet(){
            $.ajax({
                type:'get',
                url:'http://localhost:8080/api/cors/get',
                dateType: 'json',
                data:{},
                success: function (data) {
                    $("#getRes").html('请求成功。' + data);
                },
                error: function (data) {
                    console.log('请求失败:' + data);
                    $("#getRes").html('请求失败!!!' + JSON.stringify(data));
                }
            });
        }

        function crosPost(){
            $.ajax({
                type:'post',
                url:'http://localhost:8080/api/cors/post',
                dateType: 'json',
                data:{},
                success: function (data) {
                    $("#postRes").html('请求成功。' + data);
                },
                error: function (data) {
                    $("#postRes").html('请求失败!!!' + JSON.stringify(data));
                }
            });
        }
    </script>
</head>
<body>
<button onclick="crosGet()">get跨域测试</button>
<div id="getRes" style="width:80%;height:50px;background-color:#ccc;"></div>
<hr/>
<button onclick="crosPost()">post跨域测试</button>
<div id="postRes" style="width:80%;height:50px;background-color:#ccc;"></div>
</body>
</html>

前端代码cors.html可以放到tomcat或者nginx中,这里直接使用idea的open in Browser打开,默认端口为63342

不允许非当前域名访问错误

启动sprinboot后,点击前端按钮测试,会返回错误:

Access to XMLHttpRequest at 'http://localhost:8080/api/cors/get' from origin 'http://localhost:63342' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
当前域名:http://localhost:63342
要访问的域名:http://localhost:8080
错误原因:发生了跨域访问,服务端(8080)未允许该域名(63342)进行访问

添加cors支持,允许域名访问

springboot中,添加cors支持的配置:

@Configuration
public class CorsConfig {
    @Bean
    public WebMvcConfigurer corsConfigurer() {
        return new WebMvcConfigurer() {
            @Override
            public void addCorsMappings(CorsRegistry registry) {
                registry.addMapping("/api/**")
                        .allowedOrigins("http://localhost:63342");//允许域名访问,如果*,代表所有域名
            }
        };
    }
}

再次测试,成功

header跨域限制

修改配置,只允许header中带Authorization或者Token的请求访问

@Configuration
public class CorsConfig {
    @Bean
    public WebMvcConfigurer corsConfigurer() {
        return new WebMvcConfigurer() {
            @Override
            public void addCorsMappings(CorsRegistry registry) {
                registry.addMapping("/api/**")
                        .allowedHeaders("Authorization", "Token")//允许的头信息
                        .allowedOrigins("http://localhost:63342");
            }
        };
    }
}

修改html中,post接口header带Authorization,get接口header带aaa

function crosGet(){
            $.ajax({
                type:'get',
                url:'http://localhost:8080/api/cors/get',
                dateType: 'json',
                data:{},
                headers:{'aaa':'Basic 123456'},
                success: function (data) {
                    $("#getRes").html('请求成功。' + data);
                },
                error: function (data) {
                    console.log('请求失败:' + data);
                    $("#getRes").html('请求失败!!!' + JSON.stringify(data));
                }
            });
        }
function crosPost(){
            $.ajax({
                type:'post',
                url:'http://localhost:8080/api/cors/post',
                dateType: 'json',
                data:{},
                //headers:{'Authorization':'Basic 123456'},//带头信息方式1
                beforeSend: function (xhr) {
                    xhr.setRequestHeader('Authorization','Basic 123456');//带头信息方式2
                },
                success: function (data) {
                    $("#postRes").html('请求成功。' + data);
                },
                error: function (data) {
                    console.log('请求失败:' + data);
                    $("#postRes").html('请求失败!!!' + JSON.stringify(data));
                }
            });
        }

测试,get访问失败,post成功

请求方式限制

修改配置,只支持post方式访问:

@Configuration
public class CorsConfig {
    @Bean
    public WebMvcConfigurer corsConfigurer() {
        return new WebMvcConfigurer() {
            @Override
            public void addCorsMappings(CorsRegistry registry) {
                registry.addMapping("/api/**")
                        .allowedHeaders("Authorization", "Token")
                        .allowedMethods("POST")//只允许post方式
                        .allowedOrigins("http://localhost:63342");
            }
        };
    }
}

测试,get访问失败,post成功

配置get和post都允许,则都访问成功

egistry.addMapping("/api/**")
                        .allowedMethods("GET", "POST")

局部跨域设置

上面是配置了全局的跨域访问,也可以配置局部访问控制

类上面注解@CrossOrigin

@CrossOrigin(origins = "http://domain.com", allowedHeaders = "token", methods = {RequestMethod.GET, RequestMethod.POST})
@RestController
public class TestResource{

}

方法上面的@CrossOrigin

@RestController
public class TestResource{
    @CrossOrigin(origins = "http://domain.com", allowedHeaders = {"header1", "header2"})
    @GetMapping("/api/test")
    public String test(){
        return "test";
    }
}

CORS参考文档

CORS简介(作者 loveis715)

moz技术文档 HTTP访问控制(CORS)

springboot官方文档

源码地址

https://gitee.com/yimingkeji/springboot/tree/master/cors

转载于:https://my.oschina.net/yimingkeji/blog/2962277

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值