UUID 的用户体验

UUID 的用户体验

唯一标识符(UUID)在所有应用程序中都起着至关重要的作用,从用户认证到资源管理。虽然使用标准的 UUID 可以满足所有的安全需求,但我们可以为用户做很多改进。

基础知识:确保全局唯一性

唯一标识符对于区分系统中的各个实体至关重要。它们提供了一种可靠的方法来确保每个项目、用户或数据具有唯一的身份。通过保持唯一性,应用程序可以有效地管理和组织信息,从而提高操作效率并促进数据完整性。

我们不需要像 Google 或 AWS 那样有特殊需求。任何具有 128 位的安全生成的 UUID 对我们来说已经足够了。有许多库可以生成 UUID,或者你可以使用你所选编程语言的标准库。在这篇博客中,我将使用 Java 示例,但基本思想适用于任何语言。

import java.util.UUID;

UUID id = UUID.randomUUID();
// 5727a4a4-9bba-41ae-b7fe-e69cf60bb0ab

到这里为止是一个选项,但让我们抓住机会,通过一些小而有效的迭代改进来提升用户体验:

  1. 使它们易于复制
  2. 添加前缀
  3. 更高效的编码
  4. 改变长度

复制 UUID 很烦人

尝试通过双击复制这个 UUID:

c6b10dd3-1dcf-416c-8ed8-ae561807fcaf

如果你幸运的话,你得到了整个 UUID,但对于大多数人来说,他们只得到了一部分。增强唯一标识符的可用性的一种方法是使其易于复制。可以通过移除 UUID 中的连字符来实现,这样用户只需双击标识符即可复制。通过消除手动选择和复制粘贴的需要,这一小改动可以大大改善使用标识符时的用户体验。

移除连字符在所有语言中都很简单,以下是 Java 的实现:

String id = UUID.randomUUID().toString().replace("-", "");
// fe4723eab07f408384a2c0f051696083

现在试试复制它,体验是不是好很多?

添加前缀

避免在开发环境中意外使用生产环境的 API 密钥。可以通过添加有意义的前缀来帮助用户区分不同的环境或系统中的资源。例如,Stripe 使用 sk_live_ 作为生产环境密钥的前缀,或 cus_ 作为客户标识符。通过加入这样的前缀,可以确保清晰度并减少混淆的可能,特别是在多个环境共存的复杂系统中。

String id = "hello_" + UUID.randomUUID().toString().replace("-", "");
// hello_1559debea64142f3b2d29f8b0f126041

命名前缀就像命名变量一样,需要描述性但尽量简短。

使用 base58 编码

除了使用十六进制表示标识符,还可以考虑更高效的编码方式,如 base58 编码。Base58 编码使用更大的字符集,并避免了易混淆的字符,如大写字母 I 和小写字母 l,从而在不影响可读性的情况下生成更短的标识符字符串。

例如,一个 8 字符长的 base58 字符串,可以存储大约 30,000 倍于 8 字符十六进制字符串的状态。而 16 字符的 base58 字符串可以存储 889,054,070 倍于 UUID 的组合。

可以使用第三方库来实现这一点,以下是 Java 的实现示例:

import com.aventrix.jnanoid.jnanoid.NanoIdUtils;
import java.util.Random;

Random random = new Random();
String alphabet = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
String id = "prefix_" + NanoIdUtils.randomNanoId(random, alphabet.toCharArray(), 22);
// prefix_KSPKGySWPqJWWWa37RqGaX

我们生成了一个 22 字符长的 ID,这可以编码约 100 倍于 UUID 的状态,同时短了 10 个字符。

字符集长度总状态数
UUID162^122 = 5.3e+36
Base585858^22 = 6.2e+38

状态越多,碰撞的概率越低,因为生成相同 ID 所需的时间更长(在算法真正随机的情况下)。

改变熵值

并不是所有标识符都需要高碰撞抵抗性。在某些情况下,根据应用程序的具体要求,较短的标识符可能就足够了。通过减少标识符的熵,可以生成较短的 ID,同时仍然保持可接受的唯一性水平。

减少 ID 长度可能很不错,但需要确保系统能防止 ID 碰撞。在我们的 MySQL 数据库中,我们主要使用 ID 作为主键,数据库可以保护我们免受碰撞的影响。如果 ID 已存在,我们只需生成一个新 ID 并重试。如果碰撞率显著上升,可以简单地增加所有未来 ID 的长度。

长度示例总状态数
nanoid(8)re6ZkUUV1.3e+14
nanoid(12)pfpPYdZGbZvw1.4e+21
nanoid(16)sFDUZScHfZTfkLwk1.6e+28
nanoid(24)u7vzXJL9cGqUeabGPAZ5XUJ62.1e+42
nanoid(32)qkvPDeH6JyAsRhaZ3X4ZLDPSLFP7MnJz2.7e+56

结论

通过实施这些改进,可以增强应用程序中唯一标识符的可用性和效率。这将为用户和开发人员提供更好的体验,因为他们在系统内与各种实体交互和管理这些实体。无论是轻松复制标识符、区分不同环境,还是实现更短且更易读的标识符字符串,这些策略都可以帮助构建一个更用户友好和健壮的识别系统。

Unkey 的 ID 和密钥

我们使用一个简单的函数,该函数接收一个类型化的前缀,然后为我们生成 ID。这样我们可以确保同一类型的 ID 总是使用相同的前缀。这在系统中有多种类型的 ID 时特别有用。

import com.aventrix.jnanoid.jnanoid.NanoIdUtils;
import java.util.Random;

public class IdGenerator {
    private static final Random random = new Random();
    private static final String ALPHABET = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
    private static final int ID_LENGTH = 16;

    private static final Map<String, String> prefixes = Map.of(
        "key", "key",
        "api", "api",
        "policy", "pol",
        "request", "req",
        "workspace", "ws",
        "keyAuth", "key_auth",
        "vercelBinding", "vb",
        "test", "test"
    );

    public static String newId(String prefix) {
        if (!prefixes.containsKey(prefix)) {
            throw new IllegalArgumentException("Invalid prefix: " + prefix);
        }
        return prefixes.get(prefix) + "_" + NanoIdUtils.randomNanoId(random, ALPHABET.toCharArray(), ID_LENGTH);
    }
}

在代码库中使用它时,我们可以确保始终为正确类型的 ID 使用正确的前缀。

String id = IdGenerator.newId("workspace");
// ws_dYuyGV3qMKvebjML

String id = IdGenerator.newId("keyy");
// 抛出异常,因为 `keyy` 不是有效的前缀名称

API 密钥实际上也是一种标识符。它只是一种特殊的标识符,用于验证请求。我们对 API 密钥使用与标识符相同的策略。可以添加一个前缀,让用户知道他们正在使用哪种类型的密钥,并且可以在合理范围内指定密钥的长度。API 密钥的碰撞比 ID 更严重,因此我们强制执行安全限制。

通常,会在 API 密钥前添加一个标识公司的前缀。例如,Resend 使用 re_ 和 OpenStatus 使用 os_ 前缀。这使用户能够快速识别密钥并了解其用途。

String key = IdGenerator.newId("blog");
// blog_cLsvCvmY35kCfchi

参考链接

  • UUID 标准
  • NanoID 文档
  • Crypto API
  • Stripe API Keys

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/673884.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

UR机器人通信汇总

文章目录 一、概述二、UR机器人通信2.1UR通信协议2.2 UR通信端口 三、UR机器人通信端口类型3.1 Modbus TCP端口&#xff08;502端口&#xff09;3.2 Dashboard端口&#xff08;29999端口&#xff09;3.3 上位机编程端口&#xff08;30001/30002/30003端口&#xff09;3.3.1 URS…

C基础-标准库上

下:http://t.csdnimg.cn/LXa0J C 标准库是一组 C 内置函数、常量和头文件&#xff0c;比如 <stdio.h>、<stdlib.h>、<math.h>&#xff0c;等等。 目录 一. assert.h 二. ctype.h 三. errno.h 四. float.h 五.limits.h 六. locale.h 一. assert.h 源码…

Go语言垃圾回收(GC原理)

1. GC回收机制 1.1 V1.3标记清除法 (1)概述 1.STW暂停 STW(暂停业务逻辑,找出可达和不可达对象) 2.对可达对象做上标记 标记完成之后,对象5和对象6不可达,被GC清除.之后STW结束. (2).缺点 STW :让程序暂停,程序出现卡顿.标记需要扫描整个heap.清除数据会产生heap碎片. 1.…

【linux软件基础知识】与调度相关的进程描述符

进程描述符 每个进程描述符都包括几个与调度相关的字段,如下代码所示: struct thread_struct {unsigned long rsp0;unsigned long rsp;unsigned long userrsp; /* Copy from PDA */ unsigned long fs;unsigned

SprigBoot中的配置优先级 Bean管理

黑马程序员JavaWeb开发教程 文章目录 一、配置优先级1.1 SpringBoot 中支持三种格式的配置文件1.2 Java系统属性 & 命令行参数1.3 总结 二、Bean管理2.1 获取bean2.1.1 在默认情况下 2.2 bean 作用域&#xff08;实际开发中一般不需要考虑&#xff09;2.2.1 bean的作用域2.…

XML 相关漏洞风险研究

前言 经常看到有关 XXE 的漏洞分析&#xff0c;大概知道原理&#xff0c;但是对 XML 中相关的定义却一知半解。XEE 全称为 XML External Entity 即 XML 外部实体&#xff0c;但除了常见的 EXP 还有哪些触发方法&#xff1f;XML 相关的漏洞除了 XXE 还有什么其他攻击面&#xf…

已办理劳务资质,为何无法在全国建筑市场网查询到企业?

已办理劳务资质的企业无法在全国建筑市场网&#xff08;四库一平台&#xff09;查询到&#xff0c;可能的原因如下&#xff1a; 数据更新延迟&#xff1a; 全国建筑市场监管公共服务平台&#xff08;四库一平台&#xff09;的数据更新可能存在延迟。新获得的劳务资质信息在平台…

系统架构设计师【第14章】: 云原生架构设计理论与实践 (核心总结)

文章目录 14.1 云原生架构产生背景14.2 云原生架构内涵14.2.1 云原生架构定义14.2.2 云原生架构原则14.2.3 主要架构模式14.2.4 典型的云原生架构反模式 14.3 云原生架构相关技术14.3.1 容器技术14.3.2 云原生微服务14.3.3 无服务器技术14.3.4 服务网格 14.4 云原生…

Arthas使用教程——JVM常用命令

JVM相关命令 dashboard——当前系统的实时数据面板 显示当前 tomcat 的实时信息。 使用方式&#xff1a;dashboard 数据说明 ID: Java 级别的线程 ID&#xff0c;注意这个 ID 不能跟 jstack 中的 nativeID 一一对应。 NAME: 线程名 GROUP: 线程组名 PRIORITY: 线程优先级…

网站入门:Flask用法讲解

Flask是一个使用Python编写的轻量级Web服务框架&#xff0c;旨在帮助开发人员快速构建和部署Web应用程序。下面将对Flask进行更为详细的解释说明&#xff0c;并展示其使用示例与注意事项&#xff1a; 1.解释说明 定义及特点: Flask以其简洁和灵活著称&#xff0c;允许开发者以…

一个弹出的虚假安全警告去除

虚假的安全警告 poratus.azurewebsites.net Pornographic spyware detected! Remove viruses with Avira Antivirus 通过 Microsoft Edge GPT-4 (OpenAI) 这个提示可能是一个虚假的安全警告&#xff0c;被称为“恐吓软件”&#xff08;scareware&#xff09;&#xff0c;旨在…

直流输电系统氧化锌ZnO电阻设计方案

氧化锌限压器是超高压直流输电系统的主要过电压保护装置。现代直流输电系统的换流站都采用品闸元件作为换流阀,高压晶闸阀的绝缘是非自恢复的,对过电压一分敏感,耐压特性与波头关系很小,只要电压上升到某一定值时,将立即发生击穿,造成损坏。因此,往往将ZnO限压器直接跨接在桥阀…

Python量化交易学习——Part4:基于基本面的单因子选股策略

技术分析与基本面分析是股票价格分析最基础也是最经典的两个部分。技术分析是针对交易曲线及成交量等指标进行分析,基本面分析是基于公司的基本素质进行分析。 一般来说选股要先选行业,在选个股,之后根据技术分析选择买卖节点,因此针对行业及个股的基本面分析是选股的基础。…

【旧文更新】【优秀课设】基于FPGA的Verilog HDL自动售货机

【旧文更新】基于FPGA的Verilog HDL自动售货机 文章目录 关于旧文新发FPGACortex-M架构SysTick系统定时器阻塞和非阻塞延时 附录&#xff1a;压缩字符串、大小端格式转换压缩字符串浮点数压缩Packed-ASCII字符串 大小端转换什么是大端和小端数据传输中的大小端总结大小端转换函…

HTTPS 为什么比 HTTP 更安全?

HTTPS 为什么比 HTTP 更安全&#xff1f; 在当今互联网环境中&#xff0c;安全性是至关重要的。无论是浏览网站还是进行在线交易&#xff0c;确保数据传输的安全性都是用户和企业的共同目标。HTTP 和 HTTPS 是两种用于传输网页数据的协议&#xff0c;但它们之间的安全性存在显…

常见算法(基本查找、二分查找、分块查找冒泡、选择、插入、快速排序和递归算法)

一、常见算法-01-基本、二分、插值和斐波那契查找 1、基本查找/顺序查找 需求1&#xff1a;定义一个方法利用基本查找&#xff0c;查询某个元素是否存在 数据如下&#xff1a;{131&#xff0c;127&#xff0c;147&#xff0c;81&#xff0c;103&#xff0c;23&#xff0c;7&am…

k8s学习--Secret详细解释与应用

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 Secret什么是Secret?Secret四种类型及其特点Secret应用案例&#xff08;1&#xff09;将明文密码进行base64编码&#xff08;2&#xff09;编写创建secret的YAML文…

如何设置让背景颜色不包括 padding 部分,顺带全面学习 background-clip 属性(可以实现文字渐变)

先解决需求 实现背景颜色不包括 padding 部分&#xff0c;直接给容器添加 css 属性&#xff1a;background-clip:content-box; 示例代码&#xff1a; .content-box-example {background-color: lightblue;padding: 20px;border: 1px solid black;background-clip: content-bo…

vue项目出现多次ElMessage弹框

问题&#xff1a; 解决方法&#xff1a; let message null if (message null) { message ElMessage.error(“登录过期,请重新登录”); } 最终效果&#xff1a;只出现一个弹框

AI大模型在穿戴设备健康中的心率深度融合与案例分析

文章目录 1. 架构设计2. 应用场景3. 实现步骤3.1 步骤1&#xff1a;数据预处理3.2 步骤2&#xff1a;边缘计算初步分析3.3 步骤3&#xff1a;数据上传到云端3.4 步骤4&#xff1a;云端复杂分析3.5 步骤5&#xff1a;深度学习模型训练与部署 4. 云端API设计4.1 安装Flask4.2 API…