×

前端跨域:使用CORS去解决平时的跨域问题

作者:Terry2021.12.20来源:Web前端之家浏览:12918评论:2
关键词:jscors跨域

前端跨域:使用CORS去解决平时的跨域问题。

和大多数跨域的解决方案一样,JSONP也是我的选择,可是某天PM的需求变了,某功能需要改成支持POST,因为传输的数据量比较大,GET形式搞不定。所以折腾了下闻名已久的CORS(跨域资源共享,Cross-Origin Resource Sharing),这边文章也就是折腾期间的小记与总结。

•CORS能做什么:

正常使用AJAX会需要正常考虑跨域问题,所以伟大的程序员们又折腾出了一系列跨域问题的解决方案,如JSONP、flash、ifame、xhr2等等。

• CORS的原理:

CORS定义一种跨域访问的机制,可以让AJAX实现跨域访问。CORS 允许一个域上的网络应用向另一个域提交跨域 AJAX 请求。实现此功能非常简单,只需由服务器发送一个响应标头即可。

下面我们步入正题具体详情如下所示:

跨站HTTP请求(Cross-site HTTP request)是指发起请求的资源所在域不同于请求指向的资源所在域的HTTP请求。

比如说,我在Web网站A(www.a.com)中通过<img>标签引入了B站的资源(www.b.com/images/1.jpg),那么A站会向B站发起一个跨站请求。

这种图片资源的跨站请求是被允许的,类似的跨站请求还有CSS文件,JavaScript文件等。

但是如果是在脚本中发起HTTP请求,出于安全考虑,会被浏览器限制。比如,使用 XMLHttpRequest 对象发起 HTTP 请求就必须遵守 同源策略。

所谓“同源策略”是指Web应用程序只能使用 XMLHttpRequest 对象向发起源所在域内发起HTTP请求,这个请求源和请求对象必须在一个域内。

举例来说,http://www.a.com,这个网址的协议是http,域名是www.a.com,端口默认是80。那么以下是它的同源情况:

•http://www.a.com/index.html 同源

•https://www.a.com/a.html 不同源(协议不同)

•http://service.a.com/testService/test 不同源(域名不同)

•http://www.b.com/index.html 不同源(域名不同)

•http://www.a.com:8080/index.html 不同源(端口不同)

为了开发出更强大,更丰富的Web应用,跨域请求是很常见的,那么如何在不舍弃安全的情况下进行跨域请求呢?

W3C推荐了一种新的机制,即跨源资源共享(Cross-Origin Resource Sharing (CORS))。

跨源资源共享(CORS)是通过客户端+服务端协作声明的方式来确保请求安全的。服务端会在HTTP请求头中增加一系列HTTP请求参数(例如Access-Control-Allow-Origin等),来限制哪些域的请求和哪些请求类型可以接受,而客户端在发起请求时必须声明自己的源(Orgin),否则服务器将不予处理,如果客户端不作声明,请求甚至会被浏览器直接拦截都到不了服务端。服务端收到HTTP请求后会进行域的比较,只有同域的请求才会处理。

一个使用CORS实现跨域请求的示例:

客户端:

function getHello() {
    var xhr = new XMLHttpRequest();
    xhr.open("post", "http://b.example.com/Test.ashx", true);
    xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");    
    // 声明请求源
    xhr.setRequestHeader("Origin", "http://a.example.com");
    xhr.onreadystatechange = function () {
        if (xhr.readyState == 4 && xhr.status == 200) {
            var responseText = xhr.responseText;
            console.info(responseText);
        }
    }
    xhr.send();
}

服务端:

public class Test : IHttpHandler{
    public void ProcessRequest(HttpContext context){
        context.Response.ContentType = "text/plain";
        // 声明接受所有域的请求
        context.Response.AddHeader("Access-Control-Allow-Origin", "*");
        context.Response.Write("Hello World");
        }
        public bool IsReusable{
            get{
                return false;
            }
    }
}

在Web API中启用跨域访问

CORS是服务端和客户端协作声明来确保请求安全的,因此,如果需要在Web API中启用CORS也需要进行相应配置。好在微软的ASP.NET团队提供了官方的支持跨域的解决方案,只需要在NuGet中添加即可。

然后在App_Start/WebApiConfig.cs进行如下配置即可实现跨域访问:

public static class WebApiConfig{
    public static void Register(HttpConfiguration config)    {
        // Web API 配置和服务
        // 将 Web API 配置为仅使用不记名令牌身份验证。
        config.SuppressDefaultHostAuthentication();
        config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType));
        // Web API 路由
        config.MapHttpAttributeRoutes();
        config.Routes.MapHttpRoute(
        name: "DefaultApi",
        routeTemplate: "api/{controller}/{id}",
        defaults: new { id = RouteParameter.Optional }
        );
        // 允许Web API跨域访问
        EnableCrossSiteRequests(config);
        config.Formatters.JsonFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/html"));
        }
        private static void EnableCrossSiteRequests(HttpConfiguration config) {
        var cors = new EnableCorsAttribute(
        origins: "*",
        headers: "*",
        methods: "*"
        );
        config.EnableCors(cors);
    }
}

由于IE10以下浏览器不支持CORS,所以目前在国内CORS并不是主流的跨域解决方案,但是随着windows 10的发布,IE的逐渐衰落,可以预见,在不远的将来CORS将成为跨域的标准解决方案。

您的支持是我们创作的动力!
温馨提示:本文作者系Terry ,经Web前端之家编辑修改或补充,转载请注明出处和本文链接:
https://jiangweishan.com/article/kuayu20211220.html

网友评论文明上网理性发言 已有2人参与

发表评论:

评论列表

  • 访客 访客  发布于 2022-09-22 15:33:12   回复该评论
  • sddddddddddddddVS的vVS VS但是v方法v方法v发v方法v发v发v方不方便德文法文俄文