首页 > 其他分享 >一个由于前端缺少 encodeURIComponent 引起的登录问题的分析和解决

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

时间:2023-09-09 19:22:27浏览次数:33  
标签:编码 HTTP 登录 字符 URL 前端 字符串 encodeURIComponent

笔者最近三年一直在 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="[email protected]">
  <input type="submit" value="Submit">
</form>

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

3. AJAX请求

在使用 JavaScript 进行 AJAX 请求时,encodeURIComponent 也非常有用。当使用 fetchXMLHttpRequest 发送数据时,特别是发送 POST 请求时,需要确保请求体中的数据是经过编码的。

  username: "John Doe",
  email: "[email protected]"
};

// 将 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 来处理包含特殊字符的数据,以确保数据的安全性和有效性。

标签:编码,HTTP,登录,字符,URL,前端,字符串,encodeURIComponent
From: https://www.cnblogs.com/sap-jerry/p/17690024.html

相关文章

  • 考试系统前端项目复盘
    前段时间和朋友做了一个局域网考试系统,总共有3个端:考生端、监考端、管理端。框架与相关的库先简单说明一下我使用的框架和相关的库:构建工具:Vite框架:Vue3UI组件库:element-plus网络请求库:axios路由跳转:vue-router状态管理:piniaCSS扩展语言:sass其它与项目......
  • 登录拦截器校验JWT
    importcom.alibaba.csp.sentinel.util.StringUtil;importcom.xtw.enums.BizCodeEnum;importcom.xtw.model.LoginUser;importcom.xtw.util.CommonUtil;importcom.xtw.util.JWTUtil;importcom.xtw.util.JsonData;importio.jsonwebtoken.Claims;importorg.springf......
  • 图文带你了解华为华三路由器交换机登录的几种方法(开局必备)
    作者:网络之路一天 首发公众号:网络之路博客(ID:NetworkBlog)前言我们学习路由交换就是在实际工作中来配置,解决客户或者上级给的需求,真正接触的就是实实在在的路由器跟交换机,当拿到一套全新的设备的时候,要知道如何去登录,以及一些注意的事项,这个比较关键,很多初学者用惯了模拟器,而模拟器......
  • 设置一台新服务器允许root用户登录
    操作如下:1.使用ubuntu用户登陆2.运行sudopasswdroot 要求输入密码和确认密码3.sudovi/etc/ssh/sshd_config修改ssh配置找到 #PermitRootLoginprohibit-password修改为 PermitRootLoginyes按esc:wq!保存退出4.重启ssh服务sudoservicesshrestart......
  • 前端使用proxy代理解决跨域的问题
     实现方法:本地向proxy代理服务器发送请求,proxy接收本地请求,转换为目标地址相同IP和端口向目标地址发送请求。配置:(注意:因为我是本地启动的后端服务器,所以使用地址为localhost'一些为/api')vue.config.jsdevServer:{open:true,proxy:{"/localhost":{/......
  • web前端技能方法总结(css、js、jquery、html)(2)
    创建链接块display:block;列表样式在一个无序列表中,列表项的标志(marker)是出现在各列表项旁边的圆点。在有序列表中,标志可能是字母、数字或另外某种计数体系中的一个符号。要修改用于列表项的标志类型,可以使用属性list-style-type:ul{list-style-type:square;}1上面的声明把......
  • 前端几个常用的官网模版记录一下
    无意间发现的几个官网模版对于一些要求不高,不需要特定设计的官网,这几个模版套一套,改一改,轻松解决!......
  • 前端开发中如何高效渲染大数据量
    我们是袋鼠云数栈UED团队,致力于打造优秀的一站式数据中台产品。我们始终保持工匠精神,探索前端道路,为社区积累并传播经验价值。本文作者:琉易liuxianyu.cn  在日常工作中,较少的能遇到一次性往页面中插入大量数据的场景,数栈的离线开发(以下简称离线)产品中,就有类似的场景。......
  • PHP 网页扫码登录 , 推送模板消息
    缘由:因为老板要做个PC端的微信扫码绑定登录,关注公众号,推送模板消息的功能框架:ThinkPHP5功能:实现扫码微信公众号授权登录绑定,推送模板消息1.正式配置准备:微信公众号(必须申请了服务号) Appid, AppSecret配置:微信公众平台修改: 授权回调地址域名......
  • 前端三件套案例
    以下是一个使用前端三件套(HTML、CSS、JavaScript)编写的最简单的前端案例:<!DOCTYPEhtml><html><head><title>最简单的前端案例</title><metacharset="UTF-8"><style>/*CSS样式*/h1{color:red;......