java.util.UUID.fromString没有检查长度

时间:2012-03-19 10:25:32

标签: java

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

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

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

目前,如果没有长度检查,如果小于组件长度,则数字会自动添加0,如果更多,则会自动移位。缺点是,如果输入一个缺少数字的UUID字符串,它将被接受为有效并且前缀为0.这很难调试。

例如,此“12345678-1234-1234-1234-123456789ab”变为“12345678-1234-1234-1234-0123456789ab”。注意添加了'0'?并且“12345678-1234-1234-1234-123456789abcd”变为“12345678-1234-1234-1234-23456789abcd”并删除了“1”。

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

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

5 个答案:

答案 0 :(得分:15)

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

  

在接受的内容中保持自由,在发送内容时要保守。

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

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

答案 1 :(得分:12)

UUID.fromString的行为很奇怪我不确定它是不是一个bug,但这是我一直在做的就是抓住这些错误。

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;
        }
    }
}

答案 2 :(得分:1)

这是一个解决方案:

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

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

答案 3 :(得分:0)

确保针对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;
        }
    }
}

答案 4 :(得分:-1)

ams答案的副本,但是对于scala xD

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