java.util.UUID.fromString 不检查长度

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9768510/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-16 07:26:09  来源:igfitidea点击:

java.util.UUID.fromString not checking length

java

提问by Adrian M

When I looked into the implementation of java.util.UUID.fromString, I found that it doesn't check for the UUID length. Is there any particular reason for this? It only checks the components separated by "-".

当我查看 的实现时java.util.UUID.fromString,我发现它不检查 UUID 长度。这有什么特别的原因吗?它只检查以“-”分隔的组件。

String[] components = name.split("-");
        if (components.length != 5)
            throw new IllegalArgumentException("Invalid UUID string: "+name);

Should it also throw IllegalArgumentException when length is not 36?

当长度不是 36 时,它是否也应该抛出 IllegalArgumentException?

Currently, without the length checking, numbers are automatically prepended with 0's if less than the component length or shifted if more. The downside is, if one entered a UUID string with a missing digit, it is accepted as valid and prepended with 0. This is hard to debug.

目前,如果没有长度检查,如果小于组件长度,则数字会自动在前面加上 0,如果大于,则会移动。缺点是,如果输入的 UUID 字符串缺少数字,则它被认为是有效的并以 0 开头。这很难调试。

For example, this "12345678-1234-1234-1234-123456789ab" becomes "12345678-1234-1234-1234-0123456789ab". Notice the '0' added? And this "12345678-1234-1234-1234-123456789abcd" becomes "12345678-1234-1234-1234-23456789abcd" with the '1' removed.

例如,这个“12345678-1234-1234-1234-123456789ab”变成了“12345678-1234-1234-1234-0123456789ab”。注意到添加的“0”了吗?而这个“12345678-1234-1234-1234-123456789abcd”变成了“12345678-1234-1234-1234-23456789abcd”,去掉了“1”。

To push this even further, the string "1-2-3-4-5" will also be treated as valid and becomes "00000001-0002-0003-0004-000000000005".

为了进一步推动这一点,字符串“1-2-3-4-5”也将被视为有效并变为“00000001-0002-0003-0004-000000000005”。

Edit: To clarify my question, is this a bug or done on purpose to follow some standard or principle?

编辑:为了澄清我的问题,这是一个错误还是故意遵循某些标准或原则?

采纳答案by Joni

Only the original authors of the UUID class could tell you why they chose not to check the component lengths in the fromString method, but I suspect they were trying to heed Postel's law:

只有 UUID 类的原始作者可以告诉您为什么他们选择不检查 fromString 方法中的组件长度,但我怀疑他们试图注意Postel 定律

Be liberal in what you accept, and conservative in what you send.

在你接受的东西上保持自由,在你发送的东西上保守。

You can always check the input against a regular expression like this one:

您始终可以根据这样的正则表达式检查输入:

[0-9a-fA-F]{8}(?:-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}

回答by ams

The behaviour of UUID.fromString is strange I am not sure if it is a bug or not, but here is what I have been doing to catch those errors.

UUID.fromString 的行为很奇怪我不确定它是否是一个错误,但这是我一直在做的事情来捕捉这些错误。

public class UUIDUtils {
    public static boolean isValid(String uuid){
        if( uuid == null) return false;
        try {
            // we have to convert to object and back to string because the built in fromString does not have 
            // good validation logic.
            UUID fromStringUUID = UUID.fromString(uuid);
            String toStringUUID = fromStringUUID.toString();
            return toStringUUID.equals(uuid);
        } catch(IllegalArgumentException e) {
            return false;
        }
    }
}

回答by samthebest

A copy of ams's answer but for scala xD

ams 答案的副本,但用于 Scala xD

def isValidUuid(uuid: String): Boolean =
    try uuid != null && UUID.fromString(uuid).toString.equals(uuid)
    catch {
      case e: IllegalArgumentException => false
    }

回答by Otto

Here's a solution:

这是一个解决方案:

import java.util.UUID
import scala.util.control.Exception._

val uuId: Option[UUID] = allCatch opt UUID.fromString(uuidToTest)
require(uuId.isDefined, "invalid UUID")

回答by OpenCv User

Make sure to test against id.equalsIgnoreCase(parsed.toString())because UUID.fromString(id)returns lower case even if you pass idas upper case.

请务必进行测试,id.equalsIgnoreCase(parsed.toString())因为UUID.fromString(id)即使您id以大写形式通过,也会返回小写。

@Component
public class UuidDtoValidator {

    public boolean isValidUuid(String id) {
        if (isBlank(id)) {
            return false;
        }

        try {
            UUID parsed = UUID.fromString(id);
            if (parsed.equals(new UUID(0, 0))) {
                return false;
            }
            return id.equalsIgnoreCase(parsed.toString());
        } catch (IllegalArgumentException e) {
            return false;
        }
    }
}