it-swarm.com.ru

Реализация аутентификации RESTful API с использованием токенов (Yii/Yii2)

Я создаю API в Yii 1.x, который будет использоваться с мобильным приложением. Часть процесса включает вход в систему (с именем пользователя и паролем), используя следующий запрос JSON ниже:

// Запрос отправлен с именем пользователя и паролем

{
"request" : {
    "model" : {
        "username" : "bobbysmith",
        "password" : "mystrongpassword"
    }
  }
}

// Если вы успешно вошли в систему, верните следующий ответ

{
"response": {
    "code": 200,
    "message": "OK",
    "model": {
        "timestamp": 1408109484,
        "token": "633uq4t0qdtd1mdllnv2h1vs32"
    }
 }
}

Этот токен очень важен - как только пользователь вошел в приложение, я бы хотел, чтобы у него был доступ к другим страницам, которые требуют, чтобы он вошел в систему. Я хочу, чтобы мобильное приложение сохраняло этот токен и, если он тот же 633uq4t0qdtd1mdllnv2h1vs32 токен найден в любых последующих запросах, он примет это как аутентифицированный запрос (для этого пользователя 'bobbysmith').

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

Итак, в двух словах это ...

  1. На домашней странице мобильного приложения пользователь правильно входит в систему со своим именем пользователя и паролем, и это отправляет запрос в API.
  2. Это возвращает успешный ответ (показанный выше) с текущей меткой времени и всем важным токеном.
  3. Тот же пользователь переходит на другую страницу/представление приложения, где этот токен необходим а) и б) если он совпадает, это аутентифицирует этого пользователя (например, он может редактировать эту учетную запись и т.д.)
  4. Как только пользователь нажимает «Выйти», этот токен удаляется (и может больше обращаться к Моей учетной записи и т.д.) - по сути, система аутентификации на основе токенов.

Кто-нибудь может объяснить лучший способ достичь этого? Пожалуйста, дайте мне знать, если то, что я сказал, не на 100% ясно, и я предоставлю больше информации.

В то время как я использую PHP, решение Yii 1.x является идеальным, так как именно это использует текущий API.

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

21
Zabs

Информация об обработке интерфейсов безопасности

Сфокусируйтесь на решении, которое предоставляет все хорошие (RESTful) средства аутентификации одновременно, которые, вероятно, будут:

  • SSL (самое важное, иначе «HTTP-Auth» будет меньше смысла, каждый сможет прочитать ваш заголовок запроса/тело атака «человек посередине» )
  • oAuth (или лучше oAuth2!)
  • HTTP-Auth
  • Tokens (включая ограниченное время жизни, обновление и, возможно, включение логики проверки IP/DeviceUID-> если это мобильно!)
  • Соляные пароли
  • Пользовательские заголовки HTTP для проверок ID/ENV/CLIENT или что-либо еще.
  • Зашифрованные данные тела для запросов и ответов для предотвращения манипуляций с данными

Подсказка: Персональные данные пользователя должны быть всегда зашифрованы!


Может быть решение

Выше вы можете увидеть стандартную информацию об интерфейсах безопасности. Для обеспечения длительной безопасности вы можете попробовать это, как в следующей части. Я не уверен в вашей AppSidePersitence. Может быть, это sqlLite или что-то в этом роде. Вот почему я не указываю основанную на коде DB-схему, как я сделал это для Yii. Вам понадобится хранилище/постоянство внутри вашего приложения Yii (бэкэнд), а также внутри вашего приложения (клиента) для хранения времени и токенов.

Ваша модель YiiDB

enter image description here

-- -----------------------------------------------------
-- Table `mydb`.`user`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `mydb`.`user` (
  `id` INT NOT NULL,
  `username` VARCHAR(255) NOT NULL,
  `password` VARCHAR(255) NOT NULL,
  `lastLogin` DATETIME NULL,
  `modified` DATETIME NULL,
  `created` DATETIME NULL,
  PRIMARY KEY (`id`))
ENGINE = InnoDB;

----------------------------------------------------
-- Table `mydb`.`authToken`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `mydb`.`authToken` (
  `id` INT NOT NULL,
  `userId` INT NOT NULL,
  `token` VARCHAR(255) NOT NULL,
  `created` DATETIME NOT NULL,
  PRIMARY KEY (`id`, `userId`),
  INDEX `fk_authToken_user_idx` (`userId` ASC),
  UNIQUE INDEX `token_UNIQUE` (`token` ASC),
  CONSTRAINT `fk_authToken_user`
    FOREIGN KEY (`userId`)
    REFERENCES `mydb`.`user` (`id`)
    ON DELETE NO ACTION
    ON UPDATE NO ACTION)
ENGINE = InnoDB;

Ваша AppPersitenceModel

enter image description here

Правильно обработайте свой токен и обеспечьте безопасность входа в систему

  1. Любой токен, который вы сгенерируете на стороне Yii-Application, будет храниться с «созданным» -Datetime в вашей YiiApp-базе данных (см. Таблицу authToken). У каждого пользователя есть только один «токен», который будет сгенерирован после правильного «входа в систему» ​​- запрос. Таким образом, вам не нужно проверять токены при входе в систему. Определяемый схемой «токен» уникален! Я думаю, что нет необходимости обрабатывать исторические данные (старые токены, срок действия которых истек).
  2. После того, как Yii подтвердит логин пользователя как «успех», вы создадите новый токен пользователя с текущей меткой времени, который будет сохранен в вашей YiiApp-DB. В вашем YiiApp вам нужно настроить «время истечения», которое будет добавлено к текущей отметке времени, например, если вы хотите использовать «отметки времени»: текущая отметка времени: 1408109484, а время истечения установлено на 3600 (что 3600 с = 1 ч). Итак ... ваша дата истечения срока действия, которая будет отправлена ​​через API, (1408109484+3600). Btw. Подсказка: вам не нужно отправлять такие атрибуты, как "code": 200. Коды ответов включены в ваши запросы/заголовок ответа. 

    ** 200 OK Response-Example, после успешного входа пользователя в систему содержит вычисленную дату «expired»: ** 

     {
        "error": null,
        "content": {
            "expires": 1408109484,
            "token": "633uq4t0qdtd1mdllnv2h1vs32"
        }
    }
    
  3. Важно: все запросы, которые вы хотите защитить, должны отправляться с вашим сгенерированным пользователем токеном. Который, вероятно, будет храниться в вашем устройстве хранения. Вы можете обрабатывать свои «состояния входа» - действительно RESTful, если вы используете HTTP-Response-Codes right, например, 200 OK (если все в порядке) или 401 (не авторизовано, пользователь не вошел в систему или сеанс истек) Вам необходимо подтвердить свой запрос пользователя на стороне Yii. Считать токен из входящих запросов, проверить его на наличие заданных токенов в базе данных и сравнить «созданный» -DB с текущим временем входящего запроса (HTTP-запросами). 

    ** Request-Example, схема по умолчанию для любых запросов безопасности: ** 

    {
        "token": "633uq4t0qdtd1mdllnv2h1vs32"
        "content": {
            "someDataYouNeed" : null
        }
    }
    

    ** 401 Несанкционированный ответ-пример, срок действия токена истек: ** 

    {
        "error": 1, // errorCode 1: token is expired
        "content": {
            "someDataYouNeed" : null
        }
    }
    

    ** 401 Unauthorized Response-Example, пользователь не авторизован (токен не существует в YiiDB): ** 

    {
        "error": 2, // errorCode 2: user is not logged in
        "content": {
            "someDataYouNeed" : null
        }
    }
    
  4. Поддерживать сеанс пользователя? Это довольно легко. Просто обновите "создан" -Дату в authToken- Таблице к текущему времени запроса. Делайте это каждый раз, когда пользователь отправил действительный запрос. Таким образом, сеанс не истечет, если пользователь все еще активен. Перед обновлением поля expires- Date в DB убедитесь, что ваш DB-Token не устарел. Если по истечении сеанса не будет отправлено ни одного запроса, сохранение активности будет невозможно. 

    Извините, но добавление PHP-кодов было бы слишком много. 

55
lin

Если вы создаете нативное мобильное приложение, разумно было бы полагаться на безопасность нативной памяти (например, цепочки ключей iOS), а не решение на основе файлов cookie. В противном случае, как вы описали, кажется, хорошо. Пока ваша полезная нагрузка отправляется через SSL, на самом деле не имеет значения, находится ли токен в PUT или POST. Управление вашим токеном (т.е. срок действия) - это бизнес-решения, которые вы должны принять. Back end Я бы сделал, как вы описали, и удержал токен в вашей базе данных и удалил его, когда он перестал работать по каким-либо причинам, и вернул бы сообщение клиентскому приложению, чтобы вернуть его в режим выхода из системы/повторно запросить учетные данные. 

Правка: Проверьте этот удивительный разговор от плодовитого Фила Осетра. У него также есть отличная библиотека CI для создания RESTful API в CI, на которую, возможно, стоит обратить внимание.

http://philsturgeon.uk/blog/2013/07/building-a-decent-api

http://code.tutsplus.com/tutorials/working-with-restful-services-in-codeigniter--net-8814

0
Mike Miller

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

Источник: HttpBearerAuth.php

Преимущества подробно объясняются в этой статье , но в итоге лучше использовать ваше решение с request headers, поскольку параметры GET могут быть сохранены в журналах, а пароль Basic Auth может быть легко перехвачен, если вы не не используйте SSL (вы должны!)

0
Razvan Grigore