Jak wygenerować UUID „bezpieczny dla języka”?

20

Zawsze chciałem używać losowo generowanych ciągów dla identyfikatorów moich zasobów, więc mogłem mieć krótsze adresy URL takie: / user / 4jz0k1

Ale nigdy tego nie zrobiłem, ponieważ martwiłem się, że losowe generowanie ciągów tworzy rzeczywiste słowa, np .: / user / f * cker. Powoduje to dwa problemy: może być mylące lub nawet obraźliwe dla użytkowników, a także może popsuć SEO.

Potem pomyślałem, że wszystko, co muszę zrobić, to ustawić stały wzór, taki jak dodawanie liczby co 2 litery. Byłem bardzo zadowolony z mojej metody „generate_safe_uuid”, ale potem zdałem sobie sprawę, że było to lepsze tylko dla SEO, a gorsze dla użytkowników, ponieważ zwiększyło współczynnik generowanych słów, np .: / user / g4yd1ck5

Teraz myślę, że mógłbym stworzyć metodę „replace_numbers_with_letters” i sprawdzić, czy nie utworzyła żadnych słów w słowniku lub czymś podobnym.

Jakieś inne pomysły?

ps. Pisząc to, zdałem sobie również sprawę, że sprawdzanie słów w więcej niż jednym języku (np. Angielskim i francuskim, hiszpańskim itp.) Byłoby bałaganem i znów zaczynam kochać identyfikatory zawierające tylko liczby.

AKTUALIZACJA

Niektóre linki każdy powinien przeczytać:

http://thedailywtf.com/Articles/The-Automated-Curse-Generator.aspx

http://blogs.msdn.com/b/oldnewthing/archive/2008/06/27/8659071.aspx

HappyDeveloper
źródło
Używać skrótu lub sumy kontrolnej? Jeśli wolisz używać losowego ciągu, nie ma reguły, że musisz używać każdej litery w alfabecie.
Austin Henley,
21
Nie nazywaj tego uuid, uuid to uniwersalne unikalne identyfikatory. Odnosi się do konkretnego systemu identyfikatorów, którego można użyć. Nie to robisz tutaj, więc nie używaj tego terminu.
Winston Ewert,
4
Zostawię wam opowieść o automatycznym generatorze klątw
Scott Chamberlain,
1
@HappyDeveloper, po pierwsze, nie jest uniwersalny. Jest to specyficzne dla twojej aplikacji. Po drugie, uuid konkretnie odnosi się do en.wikipedia.org/wiki/Universally_unique_identifier, a nie do żadnego podobnego schematu, który wymyślisz.
Winston Ewert,
2
To takie niewiarygodne marnowanie czasu braintime. Szanse na to, że tak się stanie, są o wiele za małe, aby warto o tym pomyśleć ...
Michael Borgwardt,

Odpowiedzi:

6

Kilka wskazówek, które zmniejszą szanse na nieumyślne utworzenie znaczących słów:

  • Dodaj do mieszanki znaki inne niż alfabetyczne i nienumeryczne, takie jak „-”, „!” lub „_”.
  • Skomponuj UUID, gromadząc sekwencje znaków (a nie pojedynczych znaków), które raczej nie występują w prawdziwych słowach, takich jak „zx” lub „aa”.

To jest przykładowy kod w C # (przy użyciu .NET 4):

private string MakeRandomString()  
{  
    var bits = new List<string>()  
    {  
            "a",  
            "b",  
            "c",  
            "d",  
            "e",  
            //keep going with letters.  
            "0",  
            "1",  
            "2",  
            "3",  
            //keep going with numbers.  
            "-",  
            "!",  
            "_",  
            //add some more non-alpha, non-numeric characters.  
            "zx",  
            "aa",  
            "kq",  
            "jr",  
            "yq",  
            //add some more odd combinations to the mix.  
    };  

    StringBuilder sb = new StringBuilder();  
    Random r = new Random();  
    for (int i = 0; i < 8; i++)  
    {  
        sb.Append(bits[r.Next(bits.Count)]);  
    }  

    return sb.ToString();  
}  

Nie gwarantuje to, że nikogo nie urazisz, ale zgadzam się z @DeadMG, że nie możesz celować tak wysoko.

CesarGon
źródło
1
Problem z niealfanumerycznymi polega na tym, że niektóre z nich nie powinny ładnie grać w URI (co prowadzi do znaków ucieczki, które są dużym nie-nie w małym adresie URL: istnieje powód, dla którego bit.ly i tinyurl nie używają ich). Innym problemem jest to, że są mniej intuicyjne dla użytkownika: nie są łatwe, powiedzmy, napisać na kartce pocztowej lub przesłać przez telefon (wielu nie-techników nie ma pojęcia, jak nazywa się podkreślenie, ponieważ przykład). Po raz kolejny istnieje powód, dla którego mały URL i bit.ly ich nie używają.
user988052
@ user988052: Stąd niektóre znaki inne niż alfabetyczne i nienumeryczne . Łatwo jest wybrać kilka, które są odpowiednie dla URI i wystarczająco łatwe dla ludzi.
CesarGon
„Stąd niektóre znaki alfanumeryczne, nienumeryczne”. [sic] ... Usługi skracania adresów URL (bit.ly, tinyurl, t.co, goo.gl itp.) wydają się uważać, że zero innych niż alfanum jest lepsze niż „niektóre”. I myślę, że powody, które wyjaśniłem w moich poprzednich komentarzach, są częścią wyjaśnienia, dlaczego te usługi nie zgadzają się z twoim punktem widzenia. Teraz oczywiście nasze opinie różnią się w tej sprawie i zostawię wam ostatnie słowo; )
user988052,
@ user988052: Używam goo.gl od wieków i nigdy nie miałem problemu z konwersją wszelkiego rodzaju znaków innych niż alfa; jedynym wyjątkiem jest%. Można to znaleźć w grupie dyskusyjnej serwisu. Czy możesz podać jakieś referencje potwierdzające twoje roszczenia?
CesarGon
1
OP stwierdził, że chce krótkich nazw i prosi o metodę ich wygenerowania. Sugerujesz „dodawanie do miksu znaków niealfatycznych, nienumerycznych [sic]. Więc co sugerujesz? Ten PO najpierw generuje „coś”, a następnie wysyła to do tinyurl / bit.ly? Myślę, że nie o to chodzi w OP. OP chce bezpośrednio wygenerować adres URL, który jest stosunkowo „mały”. Mówię tylko, że jeśli o to mu chodzi, to może lepiej użyć alfabetu alfanum, tak jak robi to malutki / bit.ly! Teraz naprawdę mnie nie ma.
user988052,
5

Po prostu utwórz listę niegrzecznych słów, listę zastępowania liter, a następnie, jeśli wygenerowany identyfikator jest niegrzecznym słowem, powtórz je.

Na przykład (pseudo kod)

naughty_words = ["ass", "shit", "boobs"]
substitutions = {
    "4" : "a"
    "1" : "i"
    "3" : "e"
    "7" : "t"
    "5" : "s"
    "0" : "o"
    // etc.
}

function reducestring (str) {
    newstr = ""
    for (character in str) {
        if (substitituions[character]) newstr += substitutions[character]
        else newstr += character
    }
    return tolower(newstr)
}

do {
    new_id_numeric = random_number()
    short_id = compress_to_alphanumeric(new_id_numeric) // 0-9, a-z, A-Z
    // that function should create a base 62 number
} while (!contains(naughty_words, reducestring(short_id))

(Możesz zapoznać się z innymi zaleceniami krótkiego adresu URL, takimi jak ten, aby uzyskać informacje na temat mieszania / konwersji bazy 62)

Teraz już nie dostać identyfikatory podoba a55, sh1talbo „b00bs”. Oczywiście twoja lista zastępowania liter musi zawierać tylko znaki w twoich niegrzecznych słowach.

Ponieważ nikt nie będzie czytać „455”, jak „dupa”, to może chcesz również return strw reducestringjeśli nie zawiera żadnych liter.

Przykłady

Witryna graficzna Dribbble ma własne krótkie ciągi znaków dla postów. Używają 0-9, az i AZ jak http://drbl.in/dCWi .

Przeprowadziłem kilka eksperymentów i mam krótkie identyfikatory dla co najmniej kilku niegrzecznych słów. Myślę, że zobaczymy, kiedy dotrą f, ale jeszcze ich tam nie ma.

To prawda - przekazanie użytkownikowi własnego adresu URL ( /user/whatever) zamiast samego posta jest znacznie gorsze w przypadku niegrzecznych słów.

Nicole
źródło
2
Kiedyś napisałem program, który generował hasła do usługi online. Były przypadkowe, ale istniało kilka heurystyk, które sprawiały, że można je było wymawiać, więc łatwiej byłoby je zapamiętać. I te heurystyki doprowadziły do ​​wulgaryzmów. Rozwiązanie było takie, jak opisano tutaj: sprawdź pod względem wulgarnych podciągów, w tym tych, które mogłyby być wymawiane podobnie jak wulgarne słowa (np. Szukaj FUC i FUK) i ponownie wygeneruj hasło. (W przypadku chichotów program zapisał odrzucone hasła do osobnego pliku.)
uprzejmie
1
A jak, u licha, zamierzasz napisać coś takiego dla każdego języka ?
DeadMG
1
@DeadMG Dla pełnego zestawu wszystkich możliwych obraźliwych słów, może to tylko zmniejszyć ten zestaw. Czy twoje stanowisko jest naprawdę: „ponieważ nie możesz osiągnąć 100%, automatycznie nie warto nic robić”?
Nicole
Co z UTF-8? Istnieje wiele alternatywnych znaków do wydruku, które omijają tę zamianę.
JBRWilkinson
1
@JBRWilkinson, który nie ma zastosowania, ponieważ OP ustawia zestaw znaków znaków alfanumerycznych dla identyfikatorów, prawda?
Nicole,
5

Rozważ użycie zamiast tego klucza numerycznego lub szesnastkowego. Zaoszczędzi ci to wielu kłopotów w porównaniu do napisania filtru wulgaryzmów świadomego i18n, a najgorsze, o co musisz się martwić, to martwa wołowina .

Społeczność
źródło
1
+1: Myślę, że to najprostsze i najbezpieczniejsze rozwiązanie. Możesz wygenerować identyfikator UUID w postaci liczby i użyć dla niego reprezentacji łańcuchowej (dziesiętna, szesnastkowa, ósemkowa).
Giorgio
4
Nadal musisz się martwić B16B00B5: P
CodesInChaos
3

Nigdy nie można uniemożliwić automatycznemu systemowi generowania ciągu, który jest obraźliwy dla użytkownika. Na przykład w Chinach niektóre liczby uważa się za pechowe.

Wszystko, co możesz naprawdę zrobić, to powiedzieć użytkownikowi, że jego identyfikator jest losowy, a treść jest nieistotna, a jeśli go dostanie /user/fucker, powinien go po prostu zignorować. Te rzeczy się zdarzają i po prostu nie jest to technicznie niewykonalne - tak jak nigdy nie można odfiltrować wulgaryzmów.

DeadMG
źródło
9
Nie jestem zwolennikiem, ale bardzo mocno czuję, że w przypadku obraźliwych słów naprawdę musisz zrobić o wiele, wiele, wiele więcej niż „powiedz im, że powinni to po prostu zignorować”. Możesz przynajmniej zaoferować sposób na zmianę wygenerowanego identyfikatora na taki, który uznają za akceptowalny.
Marjan Venema,
4
Nie jestem też zwycięzcą, ale zgadzam się z @MarjanVenema, nie można zaakceptować / user / f * cker
HappyDeveloper,
@HappyDeveloper: Jak wcześniej sugerowałem, co zamierzasz z tym zrobić? Nie można uniemożliwić użytkownikom otrzymywania identyfikatorów, które uznają za obraźliwe.
DeadMG,
3
@DeadMG Możesz pomóc w tej sytuacji, zapobiegając kilku często obraźliwym przypadkom. Myślałem, że pierwotne pytanie wyjaśniło to całkiem jasno.
Nicole,
2
@NickC: Jedyne przykłady są zwykle obraźliwe w języku angielskim . Czy masz pojęcie, co jest zwykle obraźliwe w języku arabskim, portugalskim, chińskim, rosyjskim? Nie wspominając już o tym, że te języki mogą mieć przekleństwa, które przybierają wiele, wiele form. Łatwo jest wyróżnić oczywiste formy słów z angielskiego, ale nie jest to takie łatwe dla wszystkich.
DeadMG
2

Istnieją zasadniczo dwie strategie, które możesz zastosować:

  1. Utwórz system, który nie będzie generował żadnych ofensywnych ciągów. Na przykład możesz skomponować swój identyfikator tylko z liter spółgłosek. Pomijając wszystkie samogłoski, możesz mieć pewność, że Twój system nigdy nie wygeneruje żadnych angielskich słów, niegrzecznych lub w inny sposób.

  2. Po wygenerowaniu całkowicie losowego identyfikatora sprawdź, czy nowy identyfikator nie zawiera żadnych obraźliwych podciągów.

Caleb
źródło
1

W wielu sytuacjach (spam e-mail, blokowanie adresu IP itp.) Czarna lista jest przegrywającą grą - nigdy nie będziesz w stanie stworzyć „pełnej” czarnej listy wszystkich możliwych złych rzeczy, które mogą się zdarzyć. a b c d e f

Wiele osób korzysta z białej listy akceptowalnych słów i łączy je w losowej kolejności. (Być może z myślnikiem, kropką lub spacją między każdym słowem).

Niektóre popularne słowniki używane do konwertowania dowolnych liczb na dającą się wyrazić serię słów obejmują:

David Cary
źródło
0

Możesz ustawić losowo generowane liczby lub użyć wyrażenia regularnego, aby anulować te, które są obraźliwe:

/ass/ =~ userid
/boobs/ =~ userid
/morenaughtywordshere/ =~ userid
Billjk
źródło
2
Zabawne, bo nigdy nie uważałbym żadnej z nich za obraźliwą.
DeadMG
Wiem… To drażliwy temat, aby zamieścić prawdziwe przekleństwa na stronie SE: meta.stackexchange.com/questions/22232/…
Billjk