使用令牌实现RESTful API身份验证(Yii/Yii2)

Zab*_*abs 21 php rest restful-authentication yii access-token

我正在Yii 1.x中构建一个API,它将与移动应用程序一起使用.部分过程涉及使用以下JSON请求登录(使用用户名和密码): -

//使用用户名和密码发送的请求

{
"request" : {
    "model" : {
        "username" : "bobbysmith",
        "password" : "mystrongpassword"
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

//如果成功登录,则返回以下响应

{
"response": {
    "code": 200,
    "message": "OK",
    "model": {
        "timestamp": 1408109484,
        "token": "633uq4t0qdtd1mdllnv2h1vs32"
    }
 }
}
Run Code Online (Sandbox Code Playgroud)

此令牌非常重要 - 一旦用户登录应用程序,我希望他们可以访问要求他们登录的其他页面.我希望移动应用程序存储此令牌,如果相同的633uq4t0qdtd1mdllnv2h1vs32令牌是在任何后续请求中发现它将接受此作为经过身份验证的请求(对于此用户'bobbysmith').

我有点不确定如何最好地做到这一点,我做了一些研究,oAuth已被提及几次,以及通过HTTPS的基本身份验证.

所以简而言之......

  1. 在移动应用主页上,用户使用其用户名和密码正确登录,并向API发送请求.
  2. 这将返回一个成功的响应(如上所示),其中包含当前时间戳和所有重要令牌.
  3. 同样的用户进入到另一个应用程序页面/图,其中该令牌是)要求和b)如果它匹配了这个认证用户(例如,这样他们就可以编辑该帐户等.)
  4. 一旦用户点击"注销",该令牌就会被删除(并且可以更长时间访问我的帐户等) - 基本上是基于令牌的身份验证系统.

任何人都可以解释实现这一目标的最佳方法吗?如果我所说的内容不是100%明确的,请告诉我,我会提供更多信息.

当我使用PHP时,Yii 1.x解决方案是理想的,因为这是使用当前API构建的.

概括地说,该应用可确保到服务器的每个请求包括在所述有效载荷或报头,以便此令牌可以被检索令牌随后的后,一旦退出该令牌被简单地移除或设置为空/空

lin*_*lin 55

有关处理安全接口的信息

集中一个解决方案,一次性提供所有好的(RESTful)auth东西,这可能是:

  • SSL(最重要的,否则"HTTP-AUTH"将SENCE少,每个人都可以读出你的请求头/身体人在这方面的中间人攻击)
  • oAuth(或更好的oAuth2!)
  • HTTP-AUTH
  • 令牌(包括有限的生命周期,刷新,可能包括IP/DeviceUID检查逻辑 - >如果它是移动的!)
  • Salt生成密码
  • 用于ID/ENV/CLIENT检查的自定义HTTP标头或者什么.
  • 请求和响应的加密正文数据,以防止数据操作

提示:个人用户数据应该是永久加密的!


也许解决方案

您可以在上面看到有关安全接口的标准信息.为确保持久的安全性,您可以像下一部分一样尝试.我不确定你的AppSidePersitence.也许它的sqlLite或类似的东西.这就是为什么我没有指出基于代码的DB-Schema,就像我对Yii做的那样.您需要在Yii应用程序(后端)内部以及应用程序(客户端)内部存储/持久存储时间和令牌.

你的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;
Run Code Online (Sandbox Code Playgroud)

你的AppPersitenceModel

在此输入图像描述

正确处理您的令牌并确保登录安全性

  1. 您在Yii-Application端生成的任何令牌都将在YiiApp-Database中以"created"-Datetime存储(请参阅表authToken).每个用户只有一个"令牌",它将在正确的"登录" - 请求后生成.这样,您无需在"登录"时检查令牌.由架构定义,"令牌"是独一无二的!我认为没有必要处理历史数据(过期的旧令牌).
  2. 一旦用户登录被Yii验证为"成功",您就会生成一个带有当前时间戳的新用户令牌,该用户令牌将存储在您的YiiApp-DB中.在你的YiiApp中你需要配置一个"过期时间",它将被添加到当前时间戳中,例如,如果你想使用"timestamps":当前时间戳是:1408109484你的过期时间设置为3600(3600秒) = 1小时).所以......你的过期日期时间将通过API发送(1408109484+3600).顺便说一句.提示:您不需要发送类似的属性"code": 200.响应代码包含在您的请求/响应标头数据中.

    **200 OK响应 - 例如,在用户登录成功后,保持计算的"过期"日期:**

     {
        "error": null,
        "content": {
            "expires": 1408109484,
            "token": "633uq4t0qdtd1mdllnv2h1vs32"
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)
  3. 重要提示:您希望保护的每个请求都需要与生成的用户"令牌"一起发送.哪个可能会存储在您的deviceStorage中.您可以处理"登录状态" - 如果您正确使用HTTP响应代码,则确实是RESTful ,例如,200 OK(如果一切正常)或401(未授权,用户未插入或会话已过期).您需要在Yii方面验证您的用户请求.从传入请求中读出令牌,由于数据库中给定的令牌验证它,并将"created"-DB与当前传入的Request-Time(HTTP-Requests)进行比较.

    **请求 - 示例,任何安全请求的默认架构:**

    {
        "token": "633uq4t0qdtd1mdllnv2h1vs32"
        "content": {
            "someDataYouNeed" : null
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)

    **401未经授权的响应 - 示例,令牌已过期:**

    {
        "error": 1, // errorCode 1: token is expired
        "content": {
            "someDataYouNeed" : null
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)

    **401 Unauthorized Response-Example,用户未登录(YiiDB中不存在令牌):**

    {
        "error": 2, // errorCode 2: user is not logged in
        "content": {
            "someDataYouNeed" : null
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)
  4. 保持用户会话活着?这很简单.只需将"创建"-Date更新authToken为当前请求时间.每次都这样做,用户发送了有效请求.这样,如果用户仍处于活动状态,会话将不会过期.在更新expiresDB中的-Date字段之前,请确保您的DB-Token未过期.如果在会话到期时没有发送请求,则不再可能保持活动状态.

    对不起,但添加PHP代码太多了.

  • 只有细节意味着你值得这样的感谢:-) (2认同)
  • 回到这几个月后......我仍然喜欢Stackoverflow.:) (2认同)