Генериране на уникални и непрозрачни потребителски идентификатори в Google App Engine

Работя върху приложение, което позволява на регистрирани потребители да създават или качват съдържание и позволява на анонимни потребители да преглеждат това съдържание и да разглеждат страниците на регистрирани потребители, за да намерят това съдържание - това е много подобно на това как сайт като Flickr, например, позволява хората да разглеждат страниците на потребителите му.

За да направя това, имам нужда от начин да идентифицирам потребителя в анонимната HTTP GET заявка. Потребителят трябва да може да въведе http://myapplication.com/browse/<userid>/<contentid> и да стигне до правилната страница - трябва да е уникален, но не трябва да бъде нещо като имейл адреса на потребителя от съображения за поверителност.

Чрез Google App Engine мога да получа имейл адреса, свързан с потребителя, но както казах, не искам да го използвам. Мога да накарам потребителите на моето приложение да изберат уникално потребителско име, когато се регистрират, но бих искал да направя това по избор, ако изобщо е възможно, така че процесът на регистрация да е възможно най-кратък.

Друг вариант е да генерирате произволна бисквитка (GUID?) по време на процеса на регистрация и да я използвате, не виждам очевиден начин за гарантиране на уникалността на такава бисквитка без пътуване до базата данни.

Има ли начин, като се има предвид потребителски обект на App Engine, за получаване на уникален идентификатор за този обект, който може да се използва по този начин?

Търся решение на Python - забравих, че GAE поддържа и Java вече. Все пак очаквам техниките да са подобни, независимо от езика.


person Ori Pessach    schedule 22.04.2009    source източник


Отговори (3)


Вашият момент е безупречен: Точно вчера излезе нова версия на SDK с поддръжка за уникални, постоянни потребителски идентификатори. Те отговарят на всички критерии, които сте посочили.

person Nick Johnson    schedule 23.04.2009
comment
Ако текущият потребител не е влязъл, конструкторът Users повдига UserNotFoundError. - т.е. изисква влизане в Google. Бих казал обаче, че използването на механизма за влизане в Google е по-добро, отколкото да пускате свой собствен, особено за очакванията на потребителите. - person Mark; 23.04.2009
comment

Така че операторът WQL LIKE не се поддържа в моя WMI клас от този въпрос. Как да кажа предварително или интерактивно, докато пиша, какво се/не се поддържа? Бих искал да се придържам към Powershell тук и да избягвам други решения като wmic.

- person Mark; 23.04.2009
comment
Това звучи сякаш е точно това, което търся, всъщност. Използвам вход в Google и всъщност е изискване за световен уникален user_id. перфектен - person Ori Pessach; 23.04.2009
comment
Значи не искате да проследявате потребители извън Google? Под световен уникален имам предвид, че е същото и на други уебсайтове. Ако user_id наистина е уникален за света (не съм тествал), трябва да помислите, че хората могат да съпоставят вашите потребители с техните имейли. - person Mark; 23.04.2009
comment
О, разбирам какво казвате за проследяване на потребители чрез техния user_id. Ще трябва да помисля за последиците от това. И не - не е необходимо да проследявам потребители извън Google. Хората, които публикуват съдържание, трябва да са влезли и следователно трябва да са потребители на Google, но за да посетят сайта и да чета съдържание, всичко, от което се нуждая, е уникален начин за идентифициране на съдържанието в URL адреса, за който user_id() е подходящ. - person Ori Pessach; 23.04.2009
comment
Здравейте, Ник, Ори и други. Имахте ли късмет с генерирането на user_id() от потребителски обект, след като го създадете? (Тоест, не от извикването на users.get_current_user()?) user_id() връща None за мен, когато го правя по този начин. Ако имате някакви съвети, ще се радвам на обратна връзка във въпроса ми: stackoverflow.com/questions/816372/ Благодаря. - person JasonSmith; 03.05.2009

Мисля, че трябва да правите разлика между два типа потребители:

1) потребители, които са влезли чрез Google акаунти или които вече са се регистрирали на вашия сайт с имейл адрес, различен от Google

2) потребители, които са отворили вашия сайт за първи път и не са влезли по никакъв начин

За втория случай не виждам друг начин освен да генерирам произволен низ (напр. чрез uuid.uuid4() или от ключа на бисквитката на сесията на този потребител), тъй като анонимният потребител не носи никаква уникална информация със себе си.

За потребители, които са влезли обаче, вече имате уникален идентификатор - техния имейл адрес. Съгласен съм с вашите опасения за поверителност - не трябва да го използвате като идентификатор. Вместо това какво ще кажете за генериране на низ, който изглежда произволен, но всъщност е генериран от имейл адреса? Функциите за хеширане са идеални за тази цел. Пример:

>>> import hashlib

>>> email = '[email protected]'
>>> salt = 'SomeLongStringThatWillBeAppendedToEachEmail'

>>> key = hashlib.sha1('%s$%s' % (email, salt)).hexdigest()
>>> print key
f6cd3459f9a39c97635c652884b3e328f05be0f7

Тъй като hashlib.sha1 не е произволна функция, но за дадени данни винаги връща един и същ резултат, но е доказано, че е практически необратим, можете безопасно да представите хеширания ключ на уебсайта, без да компрометирате имейл адреса на потребителя. Освен това можете спокойно да предположите, че няма два еднакви хеша на различни имейли (те могат да бъдат, но вероятността това да се случи е много, много малка). За повече информация относно функциите за хеширане вижте записа в Уикипедия.

person DzinX    schedule 22.04.2009
comment
Обмислих хеширане и това няма да ми спечели много поради възможността за сблъсъци (много малко вероятно, но стабилна програма трябва да го проверява) Все още имам нужда от двупосочно пътуване до базата данни, в който момент бих могъл просто да генерирам случаен идентификатор и проверете това. Което точно се опитвах да избегна. Що се отнася до неавтентифицираните потребители, те не могат да генерират съдържание, така че това не е проблем. - person Ori Pessach; 23.04.2009

Имате предвид сесийни бисквитки?

Опитайте http://code.google.com/p/gaeutilities/


Какво каза DzinX. Единственият начин за създаване на непрозрачен ключ, който може да бъде удостоверен без обход на база данни, е използването на криптиране или криптографски хеш.

Дайте на потребителя произволно число и го хеширайте или шифровайте с частен ключ. Все още имате (малък) риск от сблъсъци, но можете да избегнете това, като докоснете базата данни при създаване на ключ, променяйки произволното число в случай на сблъсък. Уверете се, че произволното число е криптографско и добавете дълго произволно число от страна на сървъра, за да предотвратите избрани атаки с обикновен текст.

В крайна сметка ще получите токен като ключа на Google Документи, основно подпис, доказващ, че потребителят е удостоверен, което може да бъде потвърдено, без да се докосва базата данни.

Въпреки това, като се има предвид цената на GAE и скоростта на bigtable, вероятно е по-добре да използвате идентификатор на сесия, ако наистина не можете да използвате собственото удостоверяване на Google.

person Mark    schedule 22.04.2009
comment
Не, нямам предвид сесийни бисквитки. GAE вече предоставя това за проследяване на влезлия потребител. Въпросът ми се отнася конкретно до анонимни потребители и тяхното взаимодействие със съдържание, което е свързано с регистриран потребител. - person Ori Pessach; 23.04.2009
comment
Моето предложение е да използвате gaeutilities за невлязъл потребител. - person Mark; 23.04.2009
comment
невлезлите потребители взаимодействат с приложението по напълно бездържавен начин, така че това не е наистина приложимо. Благодаря за указателя все пак - изглежда като удобна библиотека. - person Ori Pessach; 23.04.2009
comment
Всъщност много ми харесва това предложение. По същество това щях да направя, ако Google просто не пусна новия SDK с уникални, постоянни потребителски идентификатори. Единственият проблем с това е, че всъщност е много трудно (може би невъзможно) да се избегнат сблъсъци - дори и да проверите хранилището за данни, няма гаранция, че няма да възникне сблъсък между вашата проверка и когато записвате данните, ако се регистрират двама потребители по едно и също време и двамата завършват с един и същ хеш. Това е много малко вероятно. - person Ori Pessach; 23.04.2009
comment
Можете да го заобиколите с транзакции (code.google.com/appengine/ docs/python/datastore/) или като дадете на хеша ограничение за уникалност (което би имало като първичен ключ). Ще имате същия проблем, ако създавате произволни ключове и ги търсите всеки път. Но да, ако използването на удостоверяване на Google е предпоставка, най-добре е да се възползвате напълно от него! - person Mark; 23.04.2009
comment
Начинът, по който Google прилага транзакции, е причината, поради която казах, че ще бъде трудно да се направи. :) Използвам транзакции другаде в приложението и има строги ограничения за това какво можете да правите в тях. Запитванията не са разрешени, например, което изглежда ограничава приложимостта им тук, освен ако не пропускам нещо умно. Не съм сигурен и за уникалността на ключа - все още не съм толкова запознат с всички странности на хранилището за данни. - person Ori Pessach; 23.04.2009