RESTful API 的跨域访问授权方案

面试官:小伙子,你的代码为什么这么丝滑?

在传统的 Web 应用中,前端页面和后端服务都在同一个域名下,因此跨域请求并不常见。然而,在现代 Web 应用中,前端和后端往往分开部署,且可能由不同的开发部门负责。这种情况下,为了让前端页面能够访问后端服务,就涉及到了跨域请求的问题。

跨域访问的问题还不止于此,还需要考虑授权方案。如果不进行授权,那么任何人都可以通过 API 直接访问你的后端服务,这将带来严重的安全风险。因此,我们需要设计一种跨域访问授权方案,以保护后端服务的安全。

什么是 RESTful API?

RESTful API 是一种 Web API 设计风格,它基于 HTTP/HTTPS 协议,旨在提供可伸缩、可靠和高效的 Web 服务。RESTful API 的设计遵循一些简单的规则:

  • 使用 HTTP 方法:
    • GET 用于获取资源
    • POST 用于创建资源
    • PUT 用于更新资源
    • DELETE 用于删除资源
  • 使用 HTTP 状态码来表示操作状态
  • 使用 URL 来标识资源
  • 使用 JSON 或 XML 格式来交换数据

跨域访问的问题

跨域访问指的是当页面的来源域(或协议、端口)和 API 请求的域不同的时候,浏览器会默认禁止这种请求。这样做是为了避免跨站点脚本攻击(Cross-Site Scripting,简称 XSS)等安全问题。

举个例子,假设有一个前端页面 http://example.com,它需要请求一个 RESTful API http://api.example.com/user/1 来获取用户信息。由于协议和端口相同,但是页面来源和 API 请求的域名不同,这就被认为是跨域请求。在默认情况下,浏览器将拒绝这个请求。

解决跨域访问的方法

虽然浏览器不允许跨域请求,但是我们可以通过以下方法来解决这个问题:

1. JSONP

JSONP(JSON with Padding)是一种跨域数据访问的方案,它利用了 <script> 标签可以跨域加载 JavaScript 的特性。JSONP 的基本原理是在页面中动态生成一个 <script> 标签,使用 API 的 URL 作为其 src 属性,同时在 URL 后面添加一个回调函数的参数名来指定一个 JavaScript 函数名,使得 API 响应的数据作为该函数的参数被返回。

例如下面的代码提供了一个 jsonp() 函数,我们把 API 的地址和需要得到的数据字段传入它,然后它会在页面上添加一个 <script> 标签,获得指定的数据并调用指定的回调函数:

-------- ---------- ---- --------- -
  ----- ------ - ---------------------------------
  ---------- - ------------------------------
  ----------------------------------

  ---------------- - -------------- -
    -------------------- -- -- --- -----
    ----------------------------------
    ------ -----------------
  --
-

然后,我们可以这样调用:

-------------------------------------- ------- -------------- -
  ------------------ -- -------
---

JSONP 的优点是简单易用,无需特殊配置。不过,它有以下缺点:

  • 安全性不高:由于 API 可以随意返回任意 JavaScript 代码,所以可能会带来安全漏洞。
  • 仅支持 GET 方法:由于使用了 <script> 标签,所以只能使用 GET 方法来访问 API。
  • 不容易处理错误:由于 JSONP 的本质是通过 <script> 标签来加载脚本,因此没有办法直接捕获错误。

2. CORS

CORS(Cross-Origin Resource Sharing)是一种更为安全和灵活的跨域访问方案,它是通过修改服务器的响应头来完成的。在服务器端,允许其他域名的请求访问所需的配置如下:

------------------------------------ ---------------------
------------------------------------- ---- ----- ---- ---------
------------------------------------- ----------------

这个响应头的意思是,允许 http://example.com 这个域名发起请求,并支持 GET、POST、PUT、DELETE 四种方法,同时也允许 Authorization 这个 HTTP 头字段。如果请求的域名和方法不被允许,那么浏览器会在控制台中输出一个错误。

在客户端代码中,我们只需要在发起请求时指定 withCredentials: true 即可:

-------------------------------------- -
  ------- ------
  ------------ ----------
  -------- -
    -------------- ------- - - -----
  --
  ----- ------
---------- --- ------------ --- ----

注意到我们在请求中添加了几个选项:

  • credentials: "include":这个选项表示在跨域请求中会携带 Cookie 和 HTTP 认证等相关数据,这使得 API 能够获取到你的登录状态,然后根据你的请求来返回对应的数据。
  • headers: { Authorization: "Bearer " + token }:如果 API 需要认证,我们需要添加一个 Authorization 头字段,表示该请求是经过认证的。这里使用了 OAuth 2.0 的 Bearer Token 认证方案,后端服务将检查请求头中的 Authorization 字段,如果找到 Bearer Token,就会验证该 Token 是否有效,有效则返回请求的数据,无效则返回 401 Unauthorized
  • mode: "cors":这个选项告诉浏览器这一请求是跨域请求。

CORS 的优点是更为安全,支持 POST、PUT、DELETE 等方法,而且不限于跨域访问 JSONP 方式下的问题。缺点是需要在后端设置一些响应头,而且需要浏览器的支持才行。

授权方案

当我们选择了 CORS 方案之后,我们还需要考虑如何授权来保护我们的 API。下面介绍一下 OAuth 2.0 的 Bearer Token 方案:

1. 定义 Authorization 头字段

在 HTTP 协议中,Authorization 头字段用于提供身份认证信息。用来告诉服务端通讯方案认证成功。它的格式通常是 Authorization: <type> <credentials>,其中 type 表示认证类型,比如 BasicBearer 等,credentials 则表示认证信息。

在 Bearer Token 方案中,参数 type 固定为 Bearer,而 credentials 表示一个随机生成的 Token,可以使用 UUID 或者 JWT 等方式生成。

例如,一个有效的 Bearer Token 头字段的格式如下:

-------------- ------ -----------------------------------------------------------------------------------------------------------------------------------------------------------

其中,Token 如下:

-----------------------------------------------------------------------------------------------------------------------------------------------------------

2. 验证 Token

在接收到请求后端 API 请求时,我们需要首先验证 Token 的有效性。具体的验证过程需要根据你的业务需求来设计,下面是一个简单的示例代码:

----- --- - ------------------------

----- ---------- - ----------------------------

-------- ------------------ -
  --- -
    ----- ------- - ----------------- ------------
    ------ --------
  - ----- -
    ------ -----
  -
-

---------------- ----- ---- -- -
  ----- ---------- - --------------------------
  -- ------------- -
    -------------------------------------
    -------
  -

  ----- --- ------ - ------------------ ---
  ----- ------- - -------------------
  -- ---------- -
    -------------------------------------
    -------
  -

  ----- ------ - ------------
  ----- ---- - -----------------------
  ---------------
---

在上面的代码中,我们首先获取了 Authorization 头字段,然后检查是否存在。如果不存在,则返回 401 Unauthorized。如果存在,则从中获取 Token,然后使用 jwt.verify() 函数来验证 Token 是否有效。如果验证成功,则返回 Token 中的 sub 字段,表示该 Token 对应的用户 ID,通过该 ID 我们可以从数据库中获取到该用户的信息。

结论

本文介绍了使用 JSONP 和 CORS 两种方式来解决跨域访问问题,并介绍了 OAuth 2.0 的 Bearer Token 方案来实现 API 的授权访问。使用跨域访问和授权方案能够使你的 RESTful API 更加安全可靠,同时也提高了前端代码和后端代码的灵活性。如果你想要在项目中使用上述方案,可以参考本文中的示例代码来实现。

来源:JavaScript中文网 ,转载请联系管理员! 本文地址:https://www.javascriptcn.com/post/670505c0d91dce0dc851625b


猜你喜欢

  • React 高阶组件详解

    React 高阶组件 (Higher-Order Component, HOC) 是一种高阶函数,用于将组件逻辑复用。它不是 React API 的一部分,而是一种模式,通过这种模式,我们可以将多个组...

    10 天前
  • Promise 的优缺点及开发者需要注意的问题

    Promise 的优缺点及开发者需要注意的问题 Promise 是 JavaScript 异步编程的一种解决方案,它的出现大大降低了回调地狱的出现。本文将介绍 Promise 的优缺点以及开发者需要注...

    10 天前
  • 使用 React Router 构建 SPA 时遇到的 404 错误(及解决方案)

    前言 在使用 React Router 构建单页面应用时,我们经常会遇到 404 错误。这个错误通常发生在我们使用浏览器刷新页面或直接访问 URL 地址时。本篇文章将介绍什么是 SPA、为什么会出现 ...

    10 天前
  • 解决 Kubernetes 集群 DNS 问题的完美方案

    介绍 Kubernetes 是一个非常流行的容器编排系统,可以帮助我们管理和扩展应用程序的部署。然而,在使用 Kubernetes 时,可能会遇到 DNS 问题,例如域名解析失败,服务发现问题等。

    10 天前
  • Server-sent Events 和 Ajax 轮询的对比分析

    Server-sent Events 和 Ajax 轮询是实现服务器与浏览器之间实时通信的两种方案。Server-sent Events(以下简称 SSE)是 HTML5 引入的新特性,而 Ajax ...

    10 天前
  • 使用 Material Design 为 iOS App 创建动态开屏界面

    Material Design 是一种全新的设计风格,由 Google 推出。它的理念是为所有平台提供相同的设计语言,使用户能够更轻松地学习和使用应用程序。Material Design 同时提供了丰...

    10 天前
  • 无障碍性能测试最佳实践

    在前端开发中,无障碍性能测试是一个重要的领域,因为它可以帮助我们确保我们的网站和应用程序对所有用户都具有可访问性。本文将介绍无障碍性能测试的最佳实践,以及如何使用它来提高用户体验。

    10 天前
  • Next.js 中如何配置 PWA 支持?

    随着移动设备的普及,PWA(Progressive Web Apps)已经成为了现代 Web 开发中的热门技术之一。Next.js 作为一种流行的 React 框架,也支持 PWA,让我们能够创建出类...

    10 天前
  • Serverless中如何实现数据加密

    随着云计算技术的不断发展,Serverless架构在近年来越来越被广泛应用。然而,使用Serverless架构也同时带来了一些安全问题,比如数据的加密。数据加密是应用程序安全的一个关键环节,本文将介绍...

    10 天前
  • Redux 如何解决 React 中数据管理的混乱问题

    在 React 应用中,随着组件层次的不断加深,数据管理变得日益复杂。在传递数据的过程中,组件之间的耦合度很高,也很难维护。Redux 是一个使用 Flux 架构思想的开源 JavaScript 库,...

    10 天前
  • 使用 Workbox 实现在 PWA 中处理预缓存资源

    在现代 web 应用程序中,离线支持和快速加载速度是至关重要的。Progressive Web Apps(PWA)使我们能够在网络可用时动态加载资源,并在离线时使用预缓存资源。

    10 天前
  • RxJS 优化:避免取消订阅导致的内存泄漏

    RxJS 是目前前端开发中广泛使用的响应式编程库之一,用于处理异步数据流。RxJS 的优点之一是可以通过订阅和取消订阅来控制数据流。但是,如果不小心处理不当,取消订阅可能会导致内存泄漏。

    10 天前
  • Web Components 开发实战:使用 Polymer 构建单页面应用

    随着互联网的普及,Web 这个平台也变得越来越复杂。从最初的 HTML、CSS、JavaScript,到如今的 AJAX、前端框架,这一路上我们见证了前端技术的飞速发展。

    10 天前
  • SASS 与 Less 的比较分析

    前端开发过程中需要管理复杂的 CSS 样式,SASS 与 Less 是两种常用的CSS预编译器,它们提供了编程语言的特性,相比原生CSS更加灵活、可读性更高,本文对SASS与Less进行深入比较分析。

    10 天前
  • 从入门到实践:Kubernetes 服务的负载均衡

    Kubernetes是一款非常流行的容器编排工具,可以方便地部署、扩展和管理容器应用。Kubernetes中的服务(Service)是一种抽象的逻辑概念,可以将应用程序的实例打包成一组虚拟的Pod,并...

    10 天前
  • ESLint 插件 eslint-plugin-vue 的使用方法详解

    ESLint 是一个非常流行的 JavaScript 代码检测工具,能够帮助开发人员提高代码质量。而 eslint-plugin-vue,则是基于 ESLint 的 Vue.js 代码检测插件,能够检...

    10 天前
  • 使用 Enzyme 测试 React 组件的常见误解与错误建议

    Enzyme 是 React 的官方测试库之一,它可以帮助我们测试组件的各种状态和行为。虽然 Enzyme 是一个非常强大的工具,但是在使用的过程中也有一些常见的误解和错误。

    10 天前
  • 使用 MongoDB 修复数据时需要注意哪些问题?

    如果你正在使用 MongoDB 作为你的数据库,那么你很有可能需要修复数据。不管是在做数据迁移、数据清理、数据校验或是其他数据操作,修复数据非常重要。 在本文中,我们将谈论一些使用 MongoDB 修...

    10 天前
  • 使用 Istanbul 覆盖率工具统计 Mocha 单元测试代码覆盖率

    使用 Istanbul 覆盖率工具统计 Mocha 单元测试代码覆盖率 前言 在前端开发中,单元测试是不可或缺的一环,它可以保证代码的质量和稳定性。而代码覆盖率则是评估测试的重要指标之一,它可以帮助开...

    10 天前
  • PM2 管理多个 Node.js 应用程序的技巧

    在前端开发中,有时候需要同时管理多个 Node.js 应用程序,单独管理每个应用程序是很困难的,而 PM2 就是一种解决方案。本文将介绍如何使用 PM2 管理多个 Node.js 应用程序的技巧。

    10 天前

相关推荐

    暂无文章