2012-03-19 14 views
15

Po sprawdzeniu implementacji java.util.UUID.fromString, okazało się, że nie sprawdza długości UUID. Czy jest jakiś szczególny powód tego? Sprawdza tylko składniki oddzielone przez "-".java.util.UUID.fromString nie sprawdzanie długości

Czy powinien również powodować wyjątek IllegalArgumentException, gdy długość nie wynosi 36?

Obecnie bez sprawdzania długości numery są automatycznie dodawane z zerami, jeśli są mniejsze niż długość komponentu lub przesunięte, jeśli są większe. Wadą jest to, że jeśli wprowadzono ciąg UUID z brakującą cyfrą, to jest on akceptowany jako poprawny i dodawany z 0. Trudno jest debugować. Na przykład ten "12345678-1234-1234-1234-123456789ab" staje się "12345678-1234-1234-1234-ab". Zwróć uwagę na "0"? I ten "12345678-1234-1234-1234-123456789abcd" staje się "12345678-1234-1234-1234-23456789abcd" z usuniętym "1".

Aby popchnąć to jeszcze dalej, ciąg "1-2-3-4-5" będzie również traktowany jako ważny i stanie się "00000001-0002-0003-0004-000000000005".

Edytuj: Aby wyjaśnić moje pytanie, czy jest to błąd, czy też zrobiono to celowo, aby zastosować jakiś standard lub zasadę?

+2

Jakie jest dokładnie twoje pytanie? Wiesz, jak działa 'UUID.fromString', sprawdziłeś jego kod źródłowy. Wygląda na to, że nie sprawdza długości części. Więc jakiego rodzaju odpowiedzi oczekujesz tutaj? – Jesper

Odpowiedz

15

Jedynie oryginalne autorzy klasy UUID mógłby powiedzieć, dlaczego nie zdecydował się sprawdzić długości składnika w metodzie fromString, ale podejrzewam, że staraliśmy się słuchać Postel's law:

być liberalne w tym, co akceptuj i zachowuj w tym, co wysyłasz.

Możesz zawsze sprawdzić wejście przeciwko wyrażenia regularnego jak ten:

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

To jest prawdopodobnie powód, dla którego zrobili to, ale IMO są zbyt liberalni w tym przypadku. –

12

Zachowanie UUID.fromString jest dziwne, nie jestem pewien, czy jest to błąd czy nie, ale tutaj jest co robiłem, aby złapać te błędy.

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

Zgodnie z najlepszą praktyką wyjątki należy stosować wyłącznie w wyjątkowych sytuacjach. –

+0

Jest to jeden liniowiec w Clojure (taki ładny język): '(try (= uuid (.toString (UUID/fromString uuid))) (catch IllegalArgumentException false))' –

-1

Kopię odpowiedzi AMS ale dla scala xD

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

Oto rozwiązanie:

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

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

Upewnij się, aby sprawdzić przed id.equalsIgnoreCase(parsed.toString()) ponieważ UUID.fromString(id) zwrotów małe litery, nawet jeśli przejdą id jako wielkie litery.

@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; 
     } 
    } 
} 
Powiązane problemy