关于前端:一个由于前端缺少-encodeURIComponent-引起的登录问题的分析和解决

7次阅读

共计 4433 个字符,预计需要花费 12 分钟才能阅读完成。

笔者最近三年始终在 SAP 中国研究院负责 Angular 利用开发程序员的职位,负责的产品是 SAP 电商云 Spartacus UI 的开发。Spartacus 是 SAP 公司主导的一个开源我的项目,Github 我的项目地址:https://github.com/SAP/spartacus.

电商云 Storefront UI 界面如下,客户如果想在下面下单,须要点击 Sign In / Register 进行用户注册或者登录。

因为电商云是一款面向企业级用户的产品,不少客户在施行的过程中,抉择将 SAP Customer Data Cloud(简称 CDC) 接入电商云的用户登录认证模块。CDC 容许企业轻松施行繁多登录(Single Sign-On,SSO)以提供无缝的用户体验。用户只需一次登录即可拜访多个企业应用程序。

除了 SSO 之外,CDC 还反对通过社交媒体账户进行登录,如 Facebook、Google 或 LinkedIn. 这简化了用户注册流程,进步了转化率。

问题形容和剖析

客户反映网站登录时,很少可能一次登录胜利:应用 SSO 登录时,login 按钮往往要反复点好几次才可能实现失常的网站登录。

咱们接到这个 incident 之后,在 Chrome 开发者工具的 network 面板里察看,发现 login 按钮点击之后,发送的 HTTP Post 申请,收到了 400 谬误:

这个 HTTP Post 申请的作用,是通过从 SAP CDC 颁发的 UID 和 UIDSignature,发送到 SAP Commerce Cloud authorization server endpoint 去换取 access token.

咱们逐个察看引起 HTTP 400 谬误的申请 Payload,发现 UIDSignature 这个字段里,蕴含了一个非凡的 = 字符。

这个非凡的 = 被浏览器传递到后盾后,就变成了一个空白字符。这导致了整个 authorization 申请不再无效,因而后盾返回了 HTTP 400 谬误。

解决方案

既然搞清了问题的前因后果,解决方案也就不难找到了。

这个 incident 的修复代码在这个 Pull Request 里:

能够看到,咱们在 UIDSignature 字段值传递到后盾时,增加了 encodeURIComponent 函数进行 encode 解决。

什么是 encodeURIComponent 函数?

encodeURIComponent 是 JavaScript 中的一个内置函数,用于将字符串中的特殊字符进行编码,以便可能在 URL 中传递或嵌入到 HTML 文档中。它的作用是将字符串中的非平安字符转换为平安的 URL 编码,这些非平安字符包含空格、标点符号、特殊符号等。

encodeURIComponent的语法如下:

encodeURIComponent(uriComponent)

其中,uriComponent 是要进行编码的字符串。函数会返回一个新的字符串,其中的特殊字符都被替换成了特定的编码值,以确保 URL 的有效性和完整性。

为什么须要 encodeURIComponent?

在 HTTP 交互中,数据的传输通常波及到 URL,包含 URL 参数、门路和查问字符串等。URL 是一种蕴含特殊字符的文本,而 HTTP 协定要求 URL 必须是无效的、符合规范的。如果 URL 中蕴含特殊字符而未通过编码,就会导致各种问题,包含:

  • URL 不符合规范,可能会导致申请失败或被服务器回绝。
  • 数据传输的完整性可能会受到破坏,因为特殊字符可能被谬误地解释或截断。
  • 安全性问题,未编码的 URL 可能会被用于攻打,例如跨站脚本(XSS)攻打。

为了防止这些问题,encodeURIComponent 函数成为了一个必不可少的工具,它确保了 URL 中的所有字符都被正确编码,以便平安地传输数据。

encodeURIComponent 的应用示例

为了更好地了解 encodeURIComponent 的必要性,咱们通过一些示例来演示它在 HTTP 交互中的利用。

1. URL 参数传递

假如咱们有一个搜寻性能,用户能够输出关键字进行搜寻。用户输出的关键字可能蕴含特殊字符,如空格、问号、和号等。为了将关键字作为 URL 参数传递给服务器,咱们须要应用 encodeURIComponent 对其进行编码。

const userInput = "Angular 2+ Tutorial?";

// 编码用户输出
const encodedKeyword = encodeURIComponent(userInput);

// 构建 URL
const searchURL = `https://example.com/search?keyword=${encodedKeyword}`;

// 发送申请
// 此时 searchURL 是平安且无效的 URL

在这个示例中,用户输出的关键字蕴含空格和问号,这些字符都不适宜间接放在 URL 中。通过应用 encodeURIComponent,咱们将用户输出平安地编码为 URL 参数,确保了 URL 的有效性和完整性。

2. HTML 表单提交

在 HTML 表单中,用户能够输出各种字符,包含特殊字符。当用户提交表单数据时,表单数据通常会被编码并以 HTTP POST 或 GET 申请的形式发送到服务器。如果不应用encodeURIComponent 对表单数据进行编码,可能会导致数据传输问题。

<form action="https://example.com/submit" method="post">
  <input type="text" name="username" value="John Doe">
  <input type="text" name="email" value="john.doe@example.com">
  <input type="submit" value="Submit">
</form>

在下面的表单中,如果用户在输入框中输出蕴含空格或其余特殊字符的内容,这些字符须要进行编码,以确保表单数据可能正确传输到服务器。

3. AJAX 申请

在应用 JavaScript 进行 AJAX 申请时,encodeURIComponent 也十分有用。当应用 fetchXMLHttpRequest 发送数据时,特地是发送 POST 申请时,须要确保申请体中的数据是通过编码的。

  username: "John Doe",
  email: "john.doe@example.com"
};

// 将 JavaScript 对象转换为 URL 编码的字符串
const encodedData = Object.keys(data)
  .map(key => `${encodeURIComponent(key)}=${encodeURIComponent(data[key])}`)
  .join("&");

fetch("https://example.com/submit", {
  method: "POST",
  headers: {"Content-Type": "application/x-www-form-urlencoded"},
  body: encodedData
});

在这个示例中,咱们将 JavaScript 对象编码为 URL 编码的字符串,并将其作为 POST 申请的申请体发送到服务器。这确保了数据的完整性和有效性。

encodeURIComponent 的编码规定

理解 encodeURIComponent 的编码规定对于正确应用它十分重要。该函数遵循一些根本的规定来确保编码后的字符串是无效的 URL 组件。

以下是 encodeURIComponent 的编码规定:

  1. 字母和数字以及 -_.~字符不会被编码。它们放弃不变。
  2. 其余字符都会被编码成 % 后跟两位十六进制数字。例如,空格会被编码为%20,问号会被编码为 %3F
  3. encodeURIComponent 不会编码常见的 URL 保留字符,如 :/?& 等。这些字符在 URL 中具备非凡的含意,不应该被编码。
  4. 如果 encodeURIComponent 函数的参数不是字符串类型,它会将参数转换为字符串,而后再进行编码。

当初,让咱们通过一些示例来演示 encodeURIComponent 的编码规定:

const originalString = "Hello, World!";
const encodedString = encodeURIComponent(originalString);

console.log(encodedString); // 输入 "Hello%2C%20World%21"

在这个示例中,逗号和空格被正确编码为 %2C%20,而叹号放弃不变。

encodeURIComponentencodeURI 的区别

除了 encodeURIComponent 之外,JavaScript 还提供了另一个编码函数encodeURI。这两者有一些区别,因而在应用它们时须要留神。

  • encodeURI 用于编码整个 URL,而不是 URL 的一部分。它不会对常见的 URL 保留字符进行编码,包含 :/?& 等。这意味着咱们能够应用 encodeURI 来编码整个 URL,而不必放心毁坏 URL 构造。
  • encodeURIComponent 用于编码 URL 中的组件,例如查问字符串参数的值。它会对所有非平安字符进行编码,包含常见的 URL 保留字符。这使得它非常适合用于编码查问字符串参数,以确保数据的完整性。

咱们通过示例来看看这两个函数之间的区别:

const url = "https://example.com/search?q=JavaScript & Angular";
const encodedURL = encodeURI(url);
const encodedComponent = encodeURIComponent(url);

console.log(encodedURL);
// 输入 "https://example.com/search?q=JavaScript%20&%20Angular"
console.log(encodedComponent);
// 输入 "https%3A%2F%2Fexample.com%2Fsearch%3Fq%3DJavaScript%20%26%20Angular"

在这个示例中,encodeURI 只对 URL 中的空格进行了编码,而encodeURIComponent 对整个 URL 进行了编码,包含保留字符。

总结

encodeURIComponent 是 HTTP 交互中不可或缺的工具之一,它用于将字符串中的特殊字符编码为合乎 URL 标准的平安字符串。通过确保数据的有效性和安全性,encodeURIComponent 有助于防止各种潜在的问题,包含 URL 的有效性、数据传输的完整性和安全性破绽。

在构建 URL、解决用户输出、发送 JSON 数据等 HTTP 交互场景中,正确应用encodeURIComponent 是一种良好的编程实际,有助于构建安全可靠的 Web 应用程序。在编写 Web 应用程序时,请始终记住应用 encodeURIComponent 来解决蕴含特殊字符的数据,以确保数据的安全性和有效性。

正文完
 0