Базовая проверка подлинности не была предназначена для управления протоколированием. Вы можете сделать это, но не полностью автоматически.
Что вам нужно сделать, так это нажать на ссылку выхода из системы и отправить ответ «401 несанкционированный» в ответ, используя ту же область и с тем же адресом уровень папки как обычный 401, который вы отправляете, запрашивая логин.
Они должны быть направлены для ввода неправильных учетных данных следующим образом, например. пустое имя пользователя и пароль, и в ответ вы отправляете страницу «Вы успешно вышли из системы». Неправильные / пустые учетные данные затем перезапишут предыдущие правильные учетные данные.
Короче говоря, сценарий выхода из строя инвертирует логику сценария входа, только возвращает страницу успеха, если пользователь не является передавая правильные учетные данные.
Вопрос в том, будет ли любопытный пароль «не вводить пароль», будет соответствовать принятию пользователем. Администраторы паролей, которые пытаются автозаполнять пароль, также могут попасть сюда.
Отредактируйте для добавления в ответ на комментарий: повторный вход в систему - это немного другая проблема (если вам не требуется двух- выход из системы / логин). Вы должны отклонить (401) первую попытку доступа к ссылке relogin, чем принять вторую (которая предположительно имеет другое имя пользователя / пароль). Есть несколько способов сделать это. Можно было бы указать текущее имя пользователя в ссылке выхода (например, имя пользователя / relogin?) И отклонить, когда учетные данные совпадут с именем пользователя.
Этот ответ был полностью переписан после отправки моего исходного ответа на просмотр кода .
Hashable protocol позволяет использовать ваш собственный класс или структуру в качестве словарного ключа. Для реализации этого протокола вам необходимо
hashValue
Эти точки следуют из аксиомы, приведенной в документации:
x == y
подразумеваетx.hashValue == y.hashValue
, где
x
иy
являются значениями некоторого типа.Реализация Equatable protocol
. Чтобы реализовать Equatable protocol, вы определяете, как ваш тип использует
==
( эквивалентности). В вашем примере эквивалентность может быть определена следующим образом:func ==(left: ScalarString, right: ScalarString) -> Bool { return left.scalarArray == right.scalarArray }
Функция
==
является глобальной, поэтому она выходит за пределы вашего класса или структуры.Возвращает вычисленный
hashValue
Ваш собственный класс или структура также должен иметь вычисленную переменную
hashValue
. Хороший алгоритм хеширования обеспечит широкий диапазон значений хеширования. Однако следует отметить, что вам не нужно гарантировать, что значения хэша уникальны. Когда два разных значения имеют одинаковые хэш-значения, это называется хеш-коллизией. Это требует некоторой дополнительной работы при столкновении (поэтому желательно хорошее распределение), но следует ожидать некоторых столкновений. Как я понимаю, функция==
делает эту дополнительную работу. (Обновление: Похоже, что==
может выполнять всю работу. )Существует множество способов вычисления хеш-значения. Например, вы можете сделать что-то так же просто, как вернуть количество элементов в массиве.
var hashValue: Int { return self.scalarArray.count }
Это дало бы хэш-столкновение каждый раз, когда два массива имели одинаковое количество элементов, но разные значения.
NSArray
, очевидно, использует этот подход.Функция хэша DJB
Общей хэш-функцией, которая работает со строками, является хеш-функция DJB. Это тот, который я буду использовать, но ознакомьтесь с некоторыми другими здесь .
Ниже приведена реализация Swift , предоставленная @MartinR :
var hashValue: Int { return self.scalarArray.reduce(5381) { ($0 << 5) &+ $0 &+ Int($1) } }
Это улучшенная версия моей первоначальной реализации, но позвольте мне также включить более старую расширенную форму, которая может быть более читаемой для людей, не знакомых с
reduce
. Это эквивалентно, я считаю:var hashValue: Int { // DJB Hash Function var hash = 5381 for(var i = 0; i < self.scalarArray.count; i++) { hash = ((hash << 5) &+ hash) &+ Int(self.scalarArray[i]) } return hash }
Оператор
&+
позволяетInt
переполняться и снова запускаться для длинных строк.Большое изображение
Мы просмотрели фрагменты, но позвольте мне теперь показать весь примерный код, относящийся к протоколу Hashable.
ScalarString
- это нестандартный тип вопроса. Конечно, это будет отличаться для разных людей.// Include the Hashable keyword after the class/struct name struct ScalarString: Hashable { private var scalarArray: [UInt32] = [] // required var for the Hashable protocol var hashValue: Int { // DJB hash function return self.scalarArray.reduce(5381) { ($0 << 5) &+ $0 &+ Int($1) } } } // required function for the Equatable protocol, which Hashable inheirits from func ==(left: ScalarString, right: ScalarString) -> Bool { return left.scalarArray == right.scalarArray }
Другое полезное чтение
- Какой алгоритм хеширования лучше всего подходит для уникальности и скорости?
- Операторы переполнения
- Почему 5381 и 33 настолько важны в алгоритме djb2?
- Как обрабатываются хэш-столкновения?
Кредиты
Большое спасибо Мартину R в обзоре кода. Моя перепись во многом основана на его ответе . Если вы нашли это полезным, то, пожалуйста, дайте ему преимущество.
Обновить
Swift теперь с открытым исходным кодом, так что можно увидеть, как
hashValue
реализовано дляString
из исходный код . Это кажется более сложным, чем ответ, который я дал здесь, и я не нашел времени, чтобы проанализировать его полностью. Не стесняйтесь делать это сами.
Одно предложение - так как вы моделируете String
, будет ли он работать, чтобы преобразовать ваш массив [UInt32]
в String
и использовать String
hashValue
? Например:
var hashValue : Int {
get {
return String(self.scalarArray.map { UnicodeScalar($0) }).hashValue
}
}
Это может позволить вам сравнить ваши пользовательские struct
с String
s, хотя, независимо от того, хорошо это или нет, зависит от того, что вы пытаетесь сделать ...
Заметим также, что, используя этот подход, экземпляры ScalarString
будут иметь одинаковый hashValue
, если их представления String
будут канонически эквивалентными, что может быть или не быть тем, что вы желаете.
Итак, я полагаю, что если вы хотите, чтобы hashValue
представлял уникальный String
, мой подход был бы хорошим. Если вы хотите, чтобы hashValue
представлял уникальную последовательность значений UInt32
, ответ @ Kametrixom - это способ пойти ...
UInt32
заключалась в том, чтобы избежать преобразования в String
. Вы знаете, как String
получает свой hashValue
?
– Suragch
15 July 2015 в 19:20
Это не очень изящное решение, но оно прекрасно работает:
"\(scalarArray)".hashValue
или
scalarArray.description.hashValue
Который использует текстовое представление как источник хэша
String
, а затем получают String
's hashValue
. Вы знаете, как String
получает hashValue
? Кажется, если бы я знал это, я мог бы просто сделать это напрямую, не пройдя через String
.
– Suragch
15 July 2015 в 19:24
isEqual
, которая будет обрабатывать хеш-коллизии. Таким образом, это, вероятно, хорошее решение и намного быстрее, чем SHA-256. Единственное, чего не хватает, это то, что классы обоих объектов одинаковы. Поскольку это не расширение для Array и только метод в классе, это работаемое решение для однородного массива. – zaph 16 July 2015 в 03:22for
... – Nicolas Miari 31 May 2017 в 01:56reduce
! – kelin 1 February 2018 в 13:57