Не удалось отличить значение типа Swift.Array & lt; Swift.String & gt; to 'Swift.AnyHashable' [дублировать]

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

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

Они должны быть направлены для ввода неправильных учетных данных следующим образом, например. пустое имя пользователя и пароль, и в ответ вы отправляете страницу «Вы успешно вышли из системы». Неправильные / пустые учетные данные затем перезапишут предыдущие правильные учетные данные.

Короче говоря, сценарий выхода из строя инвертирует логику сценария входа, только возвращает страницу успеха, если пользователь не является передавая правильные учетные данные.

Вопрос в том, будет ли любопытный пароль «не вводить пароль», будет соответствовать принятию пользователем. Администраторы паролей, которые пытаются автозаполнять пароль, также могут попасть сюда.

Отредактируйте для добавления в ответ на комментарий: повторный вход в систему - это немного другая проблема (если вам не требуется двух- выход из системы / логин). Вы должны отклонить (401) первую попытку доступа к ссылке relogin, чем принять вторую (которая предположительно имеет другое имя пользователя / пароль). Есть несколько способов сделать это. Можно было бы указать текущее имя пользователя в ссылке выхода (например, имя пользователя / relogin?) И отклонить, когда учетные данные совпадут с именем пользователя.

40
задан Community 23 May 2017 в 12:18
поделиться

5 ответов

Этот ответ был полностью переписан после отправки моего исходного ответа на просмотр кода .

Как реализовать протокол Hashable

Hashable protocol позволяет использовать ваш собственный класс или структуру в качестве словарного ключа. Для реализации этого протокола вам необходимо

  1. Внедрить Equatable protocol (Hashable наследует от Equatable)
  2. Возвратить вычисленный 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
}

Другое полезное чтение

Кредиты

Большое спасибо Мартину R в обзоре кода. Моя перепись во многом основана на его ответе . Если вы нашли это полезным, то, пожалуйста, дайте ему преимущество.

Обновить

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

43
ответ дан Community 17 August 2018 в 18:12
поделиться
  • 1
    Я удалил свой комментарий, я заметил одну важную вещь, это используется в isEqual, которая будет обрабатывать хеш-коллизии. Таким образом, это, вероятно, хорошее решение и намного быстрее, чем SHA-256. Единственное, чего не хватает, это то, что классы обоих объектов одинаковы. Поскольку это не расширение для Array и только метод в классе, это работаемое решение для однородного массива. – zaph 16 July 2015 в 03:22
  • 2
    См. Equality & amp; Идентичность Mattt Thompson. «Одно из самых распространенных заблуждений относительно реализации пользовательской хэш-функции происходит от подтверждения последующего, считая, что значения хеша должны быть разными. ... На самом деле простой XOR по хэш-значениям критических свойств достаточен в 99% случаев. – zaph 16 July 2015 в 03:31
  • 3
    Возможно, вы захотите обновить управляющий оператор цикла for ... – Nicolas Miari 31 May 2017 в 01:56
  • 4
    Спасибо за идею использования reduce! – kelin 1 February 2018 в 13:57
  • 5
    FYI - я не верю, что расширенная форма вашего примера метода выше эквивалентна методу уменьшения. В методе уменьшения значение $ 0 & amp; $ 1 изменит каждую итерацию по мере уменьшения значения (поэтому изначально будет 5381, а следующее будет значением первого уменьшения), тогда как в примере цикла цикл «hash» остается постоянным на 5381. Я не уверен, это имеет какое-то влияние на производительность, но я хотел бы указать, что они не функционально эквивалентны. – hurlbz 23 February 2018 в 16:15

Одно предложение - так как вы моделируете 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 - это способ пойти ...

3
ответ дан Aaron Rasmussen 17 August 2018 в 18:12
поделиться
  • 1
    Это интересная идея, и она работает. Я немного не решаюсь использовать его, потому что вся идея создания этого настраиваемого массива UInt32 заключалась в том, чтобы избежать преобразования в String. Вы знаете, как String получает свой hashValue? – Suragch 15 July 2015 в 19:20
  • 2
    Нет, не знаю. Но это очень интересный вопрос ... – Aaron Rasmussen 15 July 2015 в 19:23
  • 3
    Тем не менее, я бы доверял Swift, чтобы оптимизировать процесс вычисления хэш-значения String лучше, чем я мог, накрыв его ... – Aaron Rasmussen 15 July 2015 в 19:29

Это не очень изящное решение, но оно прекрасно работает:

"\(scalarArray)".hashValue

или

scalarArray.description.hashValue

Который использует текстовое представление как источник хэша

4
ответ дан Kametrixom 17 August 2018 в 18:12
поделиться
  • 1
    Оба эти способа преобразуют массив в String, а затем получают String 's hashValue. Вы знаете, как String получает hashValue? Кажется, если бы я знал это, я мог бы просто сделать это напрямую, не пройдя через String. – Suragch 15 July 2015 в 19:24
  • 2
    Рассматривали ли вы, как это может повлиять на массивы других типов? – zaph 15 July 2015 в 20:21
  • 3
    @zaph Это не так. Эта реализация полностью безопасна для каждого массива любого типа. – Kametrixom 15 July 2015 в 20:28
  • 4
    Только для моего образования, почему это не влияет на Массивы других типов. – zaph 15 July 2015 в 20:38
  • 5
    Я просто прочитал еще один ответ, в котором говорится, что криптографические хэши следует избегать для хеш-таблиц. stackoverflow.com/a/7666668/3681880 Не применимо ли это в этом случае? – Suragch 15 July 2015 в 20:44
  • 6
    Я только что сделал несколько тестов скорости, проверьте редактирование. @Suragch Возможно, SHA-256 работает медленно для хэширования, но он все еще довольно быстрый и, конечно же, не вызывает много (или даже любых) хеш-коллизий. Это зависит от того, что вы ищете, я думаю – Kametrixom 15 July 2015 в 21:06
  • 7
    интересное решение в любом случае. – Bohdan Savych 21 December 2016 в 07:15
4
ответ дан Kametrixom 6 September 2018 в 11:57
поделиться
4
ответ дан Kametrixom 29 October 2018 в 18:22
поделиться
Другие вопросы по тегам:

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