php - por - sistema de autenticación api rest con laravel 5.6 — parte 2
Implementación de una Autenticación API RESTful usando tokens(Yii/Yii2) (3)
Estoy construyendo una API en Yii 1.x que se usará con una aplicación móvil. Parte del proceso implica un inicio de sesión (con nombre de usuario y contraseña) utilizando la siguiente solicitud JSON a continuación:
// Solicitud enviada con nombre de usuario y contraseña
{
"request" : {
"model" : {
"username" : "bobbysmith",
"password" : "mystrongpassword"
}
}
}
// Si se registra con éxito a cambio la siguiente respuesta
{
"response": {
"code": 200,
"message": "OK",
"model": {
"timestamp": 1408109484,
"token": "633uq4t0qdtd1mdllnv2h1vs32"
}
}
}
Este token es bastante importante: una vez que un usuario inicia sesión en la aplicación, me gustaría que tengan acceso a otras páginas que requieren que inicien sesión. Quiero que la aplicación móvil almacene este token y si el mismo token 633uq4t0qdtd1mdllnv2h1vs32 es encontrado en cualquier solicitud posterior, aceptará esto como una solicitud autenticada (para este usuario ''bobbysmith'').
Estoy un poco inseguro de cómo hacer esto mejor, hice algunas investigaciones y se puede mencionar OAuth algunas veces, junto con la Autenticación básica a través de HTTPS.
Entonces, en pocas palabras, esto ...
- En la página de inicio de la aplicación móvil, el usuario inicia sesión correctamente con su nombre de usuario y contraseña y esto envía una solicitud a la API.
- Esto devuelve una respuesta exitosa (mostrada arriba) con la marca de tiempo actual y el token más importante.
- El mismo usuario va a otra página / vista de la aplicación donde este token es necesario) yb) si coincide, esto autentica a ese usuario (por ejemplo, para que pueda editar esa cuenta, etc.)
- Una vez que el usuario hace clic en "Cerrar sesión", este token se elimina (y puede acceder más tiempo a Mi cuenta, etc.), esencialmente un sistema de autenticación basado en tokens.
¿Alguien puede explicar la mejor manera de lograr esto? Por favor, avíseme si lo que dije no es 100% claro y proporcionaré más información.
Mientras uso PHP, una solución Yii 1.x es ideal, ya que es con eso que se construye la API actual.
En pocas palabras, la aplicación garantiza que cada solicitud al servidor incluye token en la carga útil o en el encabezado para que este token pueda recuperarse en cada publicación posterior, una vez que se haya desconectado, este token simplemente se elimina O se establece en nulo / vacío
Si está creando una aplicación móvil nativa, lo sensato sería confiar en la seguridad de la memoria nativa (por ejemplo, el llavero iOS) y no en una solución basada en cookies. De lo contrario, cómo has descrito parece estar bien. Siempre que su carga se envíe a través de SSL, realmente no importa si el token está en el PUT o POST. La gestión de tokens (es decir, los tiempos de caducidad) son decisiones comerciales que debe tomar. Detrás, yo haría lo que describa y mantendré el token en su base de datos y lo eliminaré cuando se haya extinguido por cualquier motivo y devolveré un mensaje a su aplicación cliente para volver a ponerlo en las credenciales de sesión / nueva solicitud.
EDITAR: Echa un vistazo a este increíble tut del prolífico Phil Sturgeon. También tiene una gran biblioteca de CI para construir RESTful API en CI, que podría valer la pena mirar.
http://philsturgeon.uk/blog/2013/07/building-a-decent-api
http://code.tutsplus.com/tutorials/working-with-restful-services-in-codeigniter--net-8814
En este momento, probablemente haya cambiado a Yii2, y para futuras referencias, la solución más limpia sería usar clases incluidas para RESTful APIs, o puede implementarlas en cualquier framework.
Fuente: HttpBearerAuth.php
Las ventajas se explican completamente en este artículo , pero para resumir, es mejor usar su solución con los encabezados de solicitud , ya que los parámetros GET pueden guardarse en registros y la contraseña de autenticación básica puede ser interceptada fácilmente si no usa SSL (¡debería hacerlo! )
Información sobre el manejo de interfaces de seguridad
Enfoque una solución que proporcione todas las buenas (RESTful) cosas de autenticación a la vez, que probablemente serán:
- SSL (lo más importante, de lo contrario, "HTTP-Auth" sería menos, todos podrían leer su encabezado de solicitud / cuerpo -en-el-medio-ataque )
- oAuth (o mejor oAuth2!)
- HTTP-Auth
- Fichas (incluida una vida útil limitada, actualice y tal vez incluya la lógica de comprobación de IP / DeviceUID-> si es móvil).
- Contraseñas generadas sal
- Cabeceras HTTP personalizadas para verificaciones ID / ENV / CLIENT o lo que sea.
- Datos corporales encriptados para Solicitud y Respuesta para prevenir manipulaciones de datos
Sugerencia: ¡ Los datos personales del usuario deben estar siempre encriptados!
Quizás una solución
Arriba puede ver la información estándar sobre las interfaces de seguridad. Para garantizar una seguridad duradera, puedes intentarlo como en la siguiente parte. No estoy seguro de su AppSidePersitence. Tal vez es sqlLite o algo así. Es por eso que no indico un DB-Schema basado en código, como lo hice con Yii. Necesitará un almacenamiento / persistencia dentro de su aplicación Yii (backend) y también dentro de su aplicación (cliente) para almacenar tiempos y tokens.
Tu YiiDBModel
-- -----------------------------------------------------
-- 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;
Tu AppPersitenceModel
Manejando su token a la derecha y asegurando la seguridad de inicio de sesión
- Cualquier token que genere en el lado Yii-Application se almacenará con un "created" -Datetime en su YiiApp-Database (consulte la tabla authToken). Cada usuario tiene solo un "token", que se generará después de un "inicio de sesión" correcto - Solicitud. De esa forma, no necesita verificar los tokens mientras "inicia sesión". ¡Definido por el esquema, "token" es único! Creo que no es necesario manejar datos históricos (tokens antiguos caducados).
Una vez que el inicio de sesión de usuario fue validado como "exitoso" por Yii, usted genera un nuevo token de usuario con la marca de tiempo actual, que se almacenará en su YiiApp-DB. En su YiiApp necesita configurar un "tiempo de caducidad", que se agregará a la marca de tiempo actual, por ejemplo, si desea usar "marcas de tiempo": La marca de tiempo actual es:
1408109484
y su tiempo de caducidad está configurado a3600
(que es 3600 seg = 1 h). Entonces ... su fecha de vencimiento que se enviará a través de API es(1408109484+3600)
. Por cierto. Sugerencia: No necesita enviar atributos como"code": 200
. Los Códigos de respuesta se incluyen en sus Solicitudes / Datos de encabezado de respuesta.** 200 OK Respuesta-Ejemplo, después de que el inicio de sesión de usuario fue exitoso, contiene la fecha de vencimiento calculada: **
{ "error": null, "content": { "expires": 1408109484, "token": "633uq4t0qdtd1mdllnv2h1vs32" } }
Importante: todas las solicitudes que desea asegurar, deben enviarse con su "Token" de usuario generado. Que probablemente se almacenará en su dispositivo Almacenamiento. Puede manejar sus "estados de inicio de sesión": realmente RESTful si usa códigos de respuesta HTTP correctos, por ejemplo, 200 OK (si todo está bien) o 401 (no autorizado, el usuario no está conectado o la sesión ha expirado). Debe validar su solicitud de usuario en el lado Yii. Lea el token de las solicitudes entrantes, valídelo debido a tokens dados en la base de datos y compare el "creado" -DB con el tiempo de solicitud entrante actual (HTTP-Requests).
** Ejemplo de solicitud, esquema predeterminado en cualquier solicitud de seguridad: **
{ "token": "633uq4t0qdtd1mdllnv2h1vs32" "content": { "someDataYouNeed" : null } }
** 401 Respuesta no autorizada-Ejemplo, token caducado: **
{ "error": 1, // errorCode 1: token is expired "content": { "someDataYouNeed" : null } }
** 401 Respuesta no autorizada: ejemplo, el usuario no ha iniciado sesión (no existe token en YiiDB): **
{ "error": 2, // errorCode 2: user is not logged in "content": { "someDataYouNeed" : null } }
Mantenga una sesión de usuario viva? Eso es bastante fácil. Simplemente actualice "creado" -Fecha en
authToken
-Table a la hora de solicitud actual. Haga eso cada vez, una solicitud válida fue enviada por el usuario. De esa forma, la sesión no caducará, si el usuario aún está activo. Asegúrese de que su DB-Token no esté vencido, antes de que la actualizaciónexpires
Campo de fecha en DB. Si no se envía ninguna solicitud mientras expira la sesión, el mantener vivo no será posible más.Lo siento, pero agregar códigos PHP sería demasiado.