JavaScript

JavaScript 知识量:26 - 101 - 483

23.3 跨源资源共享><

跨源资源共享- 23.3.1 -

跨源资源共享(CORS)是一种安全机制,它允许来自不同源(origin)的浏览器和服务器之间进行跨源通信。CORS定义了一种标准化的方式,通过使用自定义的HTTP头部来告知浏览器和服务器,请求或响应是否应该成功还是失败。

在CORS中,"源"是指协议、域名和端口的三元素组合。如果这三个元素中的任何一个不同,则两个URL属于不同的源。例如,http://example.com和https://example.com就属于不同的源,因为它们的协议不同(一个是http,一个是https)。

CORS的基本思路是允许浏览器向跨源服务器发送请求,但要求服务器在响应中包含一些特定的HTTP头部信息,以便浏览器可以确定请求是否应该成功。这些头部信息包括:

  • Access-Control-Allow-Origin:这个头部指定了哪些源可以访问资源。它通常设置为请求的Origin头部中的值,或者通配符"*",表示允许来自任何源的请求。

  • Access-Control-Allow-Methods:这个头部指定了实际请求中允许使用的HTTP方法。通常包括GET、POST、PUT、DELETE等。

  • Access-Control-Allow-Headers:这个头部指定了实际请求中允许携带的自定义HTTP头部。通常包括常见的非敏感头部,如Content-Type、Authorization等。

  • Access-Control-Allow-Credentials:这个头部指定了是否允许携带认证信息(如Cookies)。

  • Access-Control-Expose-Headers:这个头部指定了哪些额外的HTTP头部可以在浏览器中通过JavaScript访问。

当一个跨源请求发出时,浏览器会先发送一个预检请求(OPTIONS请求),以确定服务器是否允许该请求。预检请求中会包含Origin头部,以指示请求来自哪个源。服务器在响应中会包含相应的CORS头部信息,以指示请求是否被允许。

如果服务器返回的CORS头部信息中包含"Access-Control-Allow-Origin"且值不为"",那么浏览器会认为该请求是跨源的,并且会根据响应的CORS头部信息来决定是否允许请求完成。如果服务器返回的CORS头部信息中包含"Access-Control-Allow-Origin"且值为"",那么浏览器会认为该请求是跨源的,并且会允许请求完成,但不会暴露响应中的任何自定义HTTP头部信息给JavaScript代码。

通过这种方式,CORS提供了一种安全、灵活的方式来允许跨源通信,同时保护了用户的数据和隐私。

以下是一个简单的例子,展示了如何在客户端使用JavaScript发送一个跨域请求,并处理服务器的响应。假设有一个名为"example.com"的网站,它有一个API接口"/data"。想从另一个网站"partner.com"上发送一个跨域请求到这个接口,并处理响应。这需要使用fetch API发送一个跨域请求:

fetch('http://example.com/data', {  
  method: 'GET', // 或者 'POST'  
  headers: {  
    'Content-Type': 'application/json',  
  },  
  // 如果有需要的话,还可以在这里添加请求体  
})  
.then(response => {  
  // 这里是处理服务器响应的地方  
  if (response.ok) {  
    return response.json(); // 假设服务器返回JSON格式的响应  
  } else {  
    throw new Error('服务器响应不是ok');  
  }  
})  
.then(data => {  
  // 这里是处理服务器返回的数据的地方  
  console.log(data);  
})  
.catch(error => {  
  // 这里是处理错误的地方  
  console.error('发生错误:', error);  
});

这段代码会向"http://example.com/data"发送一个GET请求,并尝试将服务器的响应解析为JSON格式。如果一切顺利,服务器的响应数据将被打印到控制台。如果发生错误(例如服务器响应不是2xx范围),则错误信息将被打印到控制台。

注意:上述代码仅仅是一个例子,它并没有处理CORS相关的问题。实际上,如果服务器没有正确配置CORS头部信息,那么浏览器可能会阻止这个跨域请求。因此,要实现跨源资源共享,需要在服务器端进行相应的配置。

预检请求- 23.3.2 -

预检请求(preflight request)是跨源资源共享(CORS)机制中的一种服务器验证机制。它是用于在真正的跨域请求被发送之前,由浏览器发起的一种请求方式。预检请求的目的是为了确定浏览器和服务器是否能够成功地处理跨域请求。

预检请求的过程如下:

  1. 当浏览器接收到一个跨域请求时,它首先会检查请求的HTTP方法是否是GET或POST。如果是GET或POST方法,浏览器会继续处理该请求。否则,浏览器会抛出一个安全错误。

  2. 如果请求的HTTP方法是GET或POST,浏览器会检查请求头中是否包含"Origin"字段。如果"Origin"字段不存在或值不是包含当前源的URL,浏览器会继续处理该请求。

  3. 如果"Origin"字段存在且值是包含当前源的URL,浏览器会向服务器发送一个预检请求,以确认服务器是否允许该跨域请求。预检请求的HTTP方法是OPTIONS,请求头中包含"Access-Control-Request-Method"字段,该字段的值是实际的请求方法(如PUT、DELETE等)。

  4. 服务器在收到预检请求后,会检查"Access-Control-Request-Method"字段的值,并确定是否允许该跨域请求。服务器可以通过在响应头中设置"Access-Control-Allow-Origin"、"Access-Control-Allow-Methods"和"Access-Control-Allow-Headers"等字段来告知浏览器是否允许该跨域请求。

  5. 浏览器在收到预检请求的响应后,会检查响应头中的CORS相关字段,以确定服务器是否允许该跨域请求。如果服务器允许该跨域请求,浏览器会继续处理该请求。否则,浏览器会抛出一个安全错误。

通过预检请求机制,CORS允许浏览器和服务器在真正的跨域请求被发送之前进行验证,以确保请求可以被正确地处理。这有助于保护用户的数据和隐私,并确保跨域请求的安全性。

凭据请求- 23.3.3 -

凭据请求(credentialed request)是一种跨源请求中带有用户凭证(如cookie、HTTP认证或客户端SSL证书)的请求。在默认情况下,跨源请求不会发送这些凭证,因为这可能会导致安全和隐私问题。然而,当将withCredentials属性设置为true时,浏览器会允许将用户凭证包含在请求中。

当凭据请求被发送时,浏览器会执行以下步骤:

  1. 浏览器会检查请求的源是否与之前请求的源相同。如果源不同,浏览器会阻止将凭证发送到该源。这是为了防止潜在的安全风险,例如恶意网站可能会窃取用户的凭据。

  2. 如果请求的源与之前的源相同,浏览器会检查withCredentials属性是否设置为true。如果未设置该属性或设置为false,则浏览器不会发送凭证。

  3. 如果withCredentials属性设置为true,浏览器会将凭证添加到请求中。这包括将cookie附加到请求头中,如果请求使用了HTTP认证,则会将认证信息添加到请求头中,以及如果使用了客户端SSL证书,则会将证书添加到请求头中。

  4. 浏览器会将带有凭据的请求发送到服务器。服务器可以通过检查请求头中的凭证来验证用户的身份和授权。

需要注意的是,只有当服务器在响应头中设置了正确的CORS头部信息(如"Access-Control-Allow-Origin"和"Access-Control-Allow-Credentials"等)时,浏览器才会允许将凭据发送到服务器。否则,浏览器会阻止凭据请求。

通过使用凭据请求,开发者可以在跨源通信中实现更高级的安全性和用户身份验证机制,以满足特定应用程序的需求。