Лучший способ обработать аутентификацию учетной записи пользователя и пароли

Когда вы объявляете ссылочную переменную (т. е. объект), вы действительно создаете указатель на объект. Рассмотрим следующий код, в котором вы объявляете переменную примитивного типа int:

int x;
x = 10;

В этом примере переменная x является int, и Java инициализирует ее для 0. Когда вы назначаете его 10 во второй строке, ваше значение 10 записывается в ячейку памяти, на которую указывает x.

Но когда вы пытаетесь объявить ссылочный тип, произойдет что-то другое. Возьмите следующий код:

Integer num;
num = new Integer(10);

Первая строка объявляет переменную с именем num, но она не содержит примитивного значения. Вместо этого он содержит указатель (потому что тип Integer является ссылочным типом). Поскольку вы еще не указали, что указать на Java, он устанавливает значение null, что означает «Я ничего не указываю».

Во второй строке ключевое слово new используется для создания экземпляра (или создания ) объекту типа Integer и переменной указателя num присваивается этот объект. Теперь вы можете ссылаться на объект, используя оператор разыменования . (точка).

Exception, о котором вы просили, возникает, когда вы объявляете переменную, но не создавали объект. Если вы попытаетесь разыменовать num. Перед созданием объекта вы получите NullPointerException. В самых тривиальных случаях компилятор поймает проблему и сообщит вам, что «num не может быть инициализирован», но иногда вы пишете код, который непосредственно не создает объект.

Например, вы можете имеют следующий метод:

public void doSomething(SomeObject obj) {
   //do something to obj
}

В этом случае вы не создаете объект obj, скорее предполагая, что он был создан до вызова метода doSomething. К сожалению, этот метод можно вызвать следующим образом:

doSomething(null);

В этом случае obj имеет значение null. Если метод предназначен для того, чтобы что-то сделать для переданного объекта, целесообразно бросить NullPointerException, потому что это ошибка программиста, и программисту понадобится эта информация для целей отладки.

Альтернативно, там могут быть случаи, когда цель метода заключается не только в том, чтобы работать с переданным в объекте, и поэтому нулевой параметр может быть приемлемым. В этом случае вам нужно будет проверить нулевой параметр и вести себя по-другому. Вы также должны объяснить это в документации. Например, doSomething может быть записано как:

/**
  * @param obj An optional foo for ____. May be null, in which case 
  *  the result will be ____.
  */
public void doSomething(SomeObject obj) {
    if(obj != null) {
       //do something
    } else {
       //do something else
    }
}

Наконец, Как определить исключение & amp; причина использования Трассировки стека

5
задан Brian R. Bondy 13 September 2008 в 18:34
поделиться

11 ответов

Это было распространенной проблемой в UNIX много лет назад и было разрешено путем разделения пользовательских компонентов идентификационных данных (имя пользователя, UID, оболочка, полное имя, и т.д.) от компонентов аутентификации (хэш пароля, соль хэша пароля). Компоненты идентификационных данных могут быть глобально читаемыми (и на самом деле должен быть, если UIDs должны быть отображены на именах пользователей), но компоненты аутентификации должны быть сохранены недоступными пользователям. Для аутентификации пользователя имейте достоверную систему, которая примет имя пользователя и пароль, и возвратит простой результат "аутентифицируемых" или "не аутентифицируемый". Эта система должна быть единственным приложением с доступом к базе данных аутентификации и должна ожидать случайного количества времени (возможно, между 0,1 и 3 секундами) прежде, чем ответить, чтобы помочь избежать атак временным анализом.

4
ответ дан 18 December 2019 в 07:32
поделиться

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

Нет действительно никакого пути вокруг этого. Любой, который как доступ для записи к файлу паролей имеет полный контроль над компьютером.

5
ответ дан 18 December 2019 в 07:32
поделиться

У Jeff Atwood есть некоторые хорошие сообщения относительно хеширования, если Вы решаете пойти тем путем:

3
ответ дан 18 December 2019 в 07:32
поделиться

Я пошел бы с 2, но использовал бы немного соли. Некоторый псевдокод:

SetPassword(user, password)
    salt = RandomString()
    hash = Hashfunction(salt+password)
    StoreInDatabase(user, salt, hash)

CheckPassword(user, password)
    (salt, hash) = GetFromDatabase(user)
    if Hashfunction(salt+password) == hash
        return "Success"
    else
        return "Login Failed"

Важно использовать известную хеш-функцию (такую как MD5 или SHA-1), реализованный в библиотеке. Не прокручивайте свою собственную реализацию или реализацию попытки это из книги ее просто не стоящий риска понимания превратно его.

@Brian R. Bondy: причина Вы используете соль, состоит в том, чтобы сделать нападения словаря тяжелее, взломщик не может хешировать словарь и попытку против всех паролей, вместо этого она должна взять соль + словарь и хешировать его, который делает требования устройства хранения данных expode. Если Вы имеете словарь 1000 большинство commaon паролей и хешируете их, Вам нужно что-то как 16 КБ, но если Вы добавляете две случайных буквы, Вы получаете 62*62*16 КБ ≈ 62 Мбита.

Еще Вы могли использовать некоторые Одноразовые пароли, я услышал хорошие вещи о OTPW, но не использовал его.

4
ответ дан 18 December 2019 в 07:32
поделиться
  1. Очень плохая идея действительно. Если база данных поставлена под угрозу, все учетные записи поставлены под угрозу.
  2. Хороший способ пойти. Если Ваш хеш-алгоритм будет включать имя пользователя, то заменение хэша пароля с другим не будет работать.

Unix хранит хеши в текстовый файл/etc/shadow, который доступен только для привилегированных пользователей. Пароли шифруются с солью.

2
ответ дан 18 December 2019 в 07:32
поделиться

Вы могли использовать открытый и не сохранить конфиденциальные пароли пользователя вообще. Кто сказал, что это для веб-сайтов только?

3
ответ дан 18 December 2019 в 07:32
поделиться

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

0
ответ дан 18 December 2019 в 07:32
поделиться

Хешируйте имя пользователя и пароль вместе. Тот путь, если у двух пользователей есть тот же пароль, хеши, будет все еще отличаться.

0
ответ дан 18 December 2019 в 07:32
поделиться

Обычный подход должен использовать опцию два с электронной почтой:

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

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

Править: Если база данных будет поставлена под угрозу затем, то можно только гарантировать, что ни к какой разумной информации нельзя получить доступ, Вы больше не можете гарантировать безопасность своего приложения.

0
ответ дан 18 December 2019 в 07:32
поделиться

Это не проблема для многих приложений, потому что получение доступа к базе данных, вероятно, является наиболее частой целью любого злоумышленника. Итак, если у них уже есть доступ к базе данных, зачем им все еще входить в приложение? :)

0
ответ дан 18 December 2019 в 07:32
поделиться

Если "система" является публичным сайтом, RPX может предоставить вам услуги входа/аккаунта для наиболее распространенных провайдеров, таких как OpenId, Facebook, Google и т.д.

Теперь, учитывая то, как вы сформулировали свой вопрос, я предполагаю, что "система", о которой вы говорите, скорее всего, является внутренним корпоративным приложением на базе windows/linux. Тем не менее, для тех, кто ищет провайдеров логинов/аккаунтов (как это делал я, пока не наткнулся на RPX), это может подойти :)

.
0
ответ дан 18 December 2019 в 07:32
поделиться
Другие вопросы по тегам:

Похожие вопросы: