2012-03-19 21 views
15

Cuando analicé la implementación de java.util.UUID.fromString, encontré que no verifica la longitud del UUID. ¿Hay una razón en particular para esto? Solo verifica los componentes separados por "-".java.util estadounidenseID.fromString sin verificar la longitud

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

¿Debería lanzar también IllegalArgumentException cuando la longitud no es 36?

Actualmente, sin la verificación de longitud, los números se anteponen automáticamente con 0, si son menores que la longitud del componente o se cambian si hay más. La desventaja es que, si uno ingresó una cadena de UUID con un dígito faltante, se acepta como válido y se antepone con 0. Esto es difícil de depurar.

Por ejemplo, este "12345678-1234-1234-1234-123456789ab" se convierte en "12345678-1234-1234-1234-ab". Observe que se agregó '0'? Y este "12345678-1234-1234-1234-123456789abcd" se convierte en "12345678-1234-1234-1234-23456789abcd" con el "1" eliminado.

Para impulsar esto aún más, la cadena "1-2-3-4-5" también se tratará como válida y se convierte en "00000001-0002-0003-0004-000000000005".

Editar: Para aclarar mi pregunta, ¿se trata de un error o hecho a propósito para seguir algún estándar o principio?

+2

Entonces, ¿cuál es exactamente tu pregunta? Ya sabes cómo funciona 'UUID.fromString', has mirado su código fuente. Aparentemente no verifica la longitud de las partes. Entonces, ¿qué tipo de respuestas esperas aquí? – Jesper

Respuesta

15

Sólo los autores originales de la clase UUID podría decirle por qué eligieron no comprobar las longitudes de los componentes en el método fromstring, pero sospecho que estaban tratando de prestar atención Postel's law:

Sé liberal en lo que aceptar y conservador en lo que envía.

Siempre se puede comprobar la entrada con una expresión regular como éste:

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

Esta es probablemente la razón por la que lo hicieron, pero IMO son demasiado liberales en este caso. –

12

El comportamiento de UUID.fromString es extraño No estoy seguro de si se trata de un error o no, pero aquí es lo que he estado haciendo para detectar esos errores.

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

La práctica recomendada establece que solo debe usar excepciones para casos excepcionales. –

+0

Es un trazador de líneas en Clojure (un lenguaje tan bonito): '(try (= uuid (.toString (UUID/fromString uuid))) (catch IllegalArgumentException false))' –

-1

Una copia de la respuesta de AMS pero para xD Scala

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

he aquí una solución:

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

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

Asegúrese de poner a prueba contra id.equalsIgnoreCase(parsed.toString()) PORQUE UUID.fromString(id) vuelve minúsculas, incluso si pasa id como mayúsculas

@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; 
     } 
    } 
} 
Cuestiones relacionadas