当我查看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”。
编辑:为了澄清我的问题,这是一个错误或是否有意遵循某些标准或原则?
答案 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
}