Обфускация идентификатора пользователя - PullRequest
9 голосов
/ 06 января 2012

Я ожидаю, что об этом уже спрашивали, но не нашел здесь подходящего ответа, а также у меня нет времени, чтобы найти собственное решение ...

Еслиу нас есть таблица пользователей с int identity первичным ключом, тогда у наших пользователей есть последовательные идентификаторы при регистрации на сайте.

У нас есть страница общедоступного профиля пользователя на URL сайта:

www.somesite.com/user/1234

где 1234 - фактический идентификатор пользователя.Нет ничего уязвимого, чтобы увидеть идентификатор пользователя как таковой , но он дает любому возможность проверить, сколько пользователей зарегистрировано на моем сайте ... Ручное увеличение числа в итоге приводит меня к неверному профилю.

Это основная причина, по которой я переворачиваю обратимое отображение идентификатора на казалось бы случайное число с фиксированной длиной:

www.somesite.com/user/6123978458176573

Можете ли вы указать мне простой класс, который выполняет это отображение?Конечно, важно, чтобы это сопоставление было просто обратимым, в противном случае мне пришлось бы сохранять сопоставление вместе с данными другого пользователя.

Я хочу избегать идентификаторов GUID

Идентификаторы GUID медленнее индексируют при их поискепотому что они не являются последовательными, поэтому SQL должен сканировать весь индекс, чтобы найти определенный GUID, а не только определенную вычисленную индексную страницу ...

Если бы у меня был ID + GUID, мне всегда нужно было бы выбиратьисходный идентификатор пользователя для выполнения любых значимых манипуляций с данными, что опять-таки приводит к снижению скорости ...

Математическая обратимая целочисленная перестановка представляется самым быстрым решением ...

Ответы [ 3 ]

15 голосов
/ 06 января 2012

Я бы на 100% пошел с подходом «Добавить столбец GUID к таблице».Потребуется несколько секунд, чтобы сгенерировать по одному для каждого текущего пользователя, и обновить процедуру вставки, чтобы сгенерировать по одному для каждого нового пользователя.Это лучшее решение.

Однако, если вы действительно не хотите использовать этот подход, вы можете использовать любое количество методов запутывания.

Просто закодируйте Base64строковое представление вашего числа - это один (плохой) способ сделать это.

    static public string EncodeTo64(string toEncode)
    {

      byte[] toEncodeAsBytes
            = System.Text.ASCIIEncoding.ASCII.GetBytes(toEncode);
      string returnValue
            = System.Convert.ToBase64String(toEncodeAsBytes);
      return returnValue;
    }

    static public string DecodeFrom64(string encodedData)
    {
      byte[] encodedDataAsBytes
          = System.Convert.FromBase64String(encodedData);
      string returnValue =
         System.Text.ASCIIEncoding.ASCII.GetString(encodedDataAsBytes);
      return returnValue;
    }

Плохо, потому что любой, имеющий пол-унции технических знаний (хакеры / scriptkiddies, как правило, имеют это в изобилии), мгновенно распознает результаткак Base64 и легко перепроектировать.


Редактировать: Этот пост Обфусцирование идентификаторов в URL-адресах с Rails обеспечивает вполне работоспособный пример.Преобразование в C # дает вам что-то вроде:

static int Prime = 1580030173;
static int PrimeInverse = 59260789;

public static int EncodeId(int input)
{
    return (input * Prime) & int.MaxValue;
}

public static int DecodeId(int input)
{
    return (input * PrimeInverse) & int.MaxValue;
}

Ввод -> Выход
1234 -> 1989564746
5678 -> 1372124598
5679 -> 804671123

В этом посте другого автора объясняется, как обеспечить это немного больше со случайным XOR, а также как рассчитать Primeи PrimeInverse - я только что использовал предварительно консервированные из оригинального блога для демонстрации.

1 голос
/ 06 января 2012
  1. Использовать UUID

  2. Создайте еще один столбец в пользовательской таблице, например, для 64-разрядные целые числа, и заполните его случайным числом (каждый раз, когда новый пользователь регистрируется - сгенерируйте его и проверьте его уникальность). Число выглядит лучше, чем UUID, однако требуется немного больше кодирования.

  3. Используйте математику. ;) Вы можете сгенерировать пару чисел X, Y, например X*Y = 1 (mod M). Например. X=10000000019L, Y=1255114267L и M=2^30. Тогда у вас будут две простые функции:

.

long encode(long id)
{  return (id * X) & M; }

long decode(long encodedId)
{  return (encodedId * Y) & M; }

Он будет генерировать почти случайные кодированные идентификаторы. Это легко, но можно взломать. Если кто-то захочет его взломать, он сможет угадать ваши цифры и увидеть закодированные значения. Однако я не совсем уверен, какая это сложность, но, насколько я помню, взломать не очень легко.

0 голосов
/ 06 января 2012

Могу ли я предложить вам использовать вместо этого UUID. Это может быть индексируемо и генерироваться в хранимой процедуре при добавлении нового пользователя в базу данных. Это будет означать либо добавление нового столбца в таблицу базы данных, либо новую таблицу, содержащую UUID, но с идентификатором пользователя в качестве связанного ключа.

редактировать

Если вы действительно хотите избежать GUID, то почему бы не использовать "username" пользователей, когда они получают доступ к странице своего профиля. В конце концов, я полагаю, что вы не назначаете пользователю идентификатор, пока он не введет правильную информацию и эти данные не будут сохранены в базе данных.

...