最近在做RESTfulAPI认证功能,记录下整个过程,方便以后查看。本文参考了https://segmentfault.com/a/1190000016368603的部分内容。感谢作者分享。以下内容根据本人项目实际情况进行了调整。身份验证介绍不同于Web应用程序。RESTfulAPI通常是无状态的,这意味着不应使用会话或cookie。因此,每个请求都应附有某种授权凭据,因为用户授权状态可能无法通过会话或cookie来维护。常用的做法是为每个请求发送一个秘密的访问令牌来对用户进行身份验证。由于accesstoken可以唯一标识和验证用户,API请求应该通过HTTPS以防止中间人(MitM)中间人攻击。认证方式为HTTPBasic认证:accesstoken作为用户名发送,应用于accesstoken可以安全存在于API客户端的场景。例如,API客户端是一个运行在服务器上的程序。请求参数:accesstoken作为APIURL请求参数发送,如https://example.com/users?acc...,由于大部分服务器都会将请求参数保存到日志中,该方式应该主要用于JSONP请求,因为它不能使用HTTP头来发送accesstokenOAuth2:用户从认证服务器获取基于OAuth2协议的accesstoken,然后通过HTTPBearerTokens发送给API服务器。以上是简单介绍,内容来自YiiFramework2.0权威指南实施步骤延续上一篇文章的内容(这里暂时使用默认的User数据表,正式环境下请将不同的数据表分开进行认证)数据内容需要添加的内容接上一篇用户数据表,我们还需要添加一个access_token和expire_at字段,进入项目根目录,打开控制台输入如下命令:./yiimigrate/createadd_column_access_token_to_user./yiimigrate/createadd_column_expire_at_to_user打开你的项目目录/console/migrations/m181224_075747_add_column_access_token_user.php修改如下内容:()ANDtable_name='user'ANDcolumn_name='access'to")->queryOne();//判断user表是否有字段d'access_token'if(empty($ret)){$this->addColumn('user','access_token',$this->string(255)->defaultValue(NULL)->comment('token'));}}publicfunctiondown(){$this->dropColumn('user','access_token');返回真;}打开你的项目目录/console/migrations/m181224_092333_add_column_expire_at_user.php修改如下内容:publicfunctionup(){$ret=$this->db->createCommand("SELECT*FROMinformation_schema.columnsWHEREtable_schema=DATABASE()ANDtable_name='user'ANDcolumn_name='expire_at'")->queryOne();if(empty($ret)){$this->addColumn('user','expire_at',$this->integer(11)->defaultValue(NULL)->comment('token过期时间'));}}publicfunctiondown(){$this->dropColumn('user','expire_at');返回真;}执行迁移命令./yiimigrateconfiguration打开api\config\main.php配置用户应用组件:'user'=>['identityClass'=>'api\models\User','enableAutoLogin'=>true,'enableSession'=>false,//'identityCookie'=>['name'=>'_identity-api','httpOnly'=>true],],注释掉会话组件,或者删除//'session'=>[////这是用于在后端登录的会话cookie的名称//'name'=>'advanced-api',//],编写api\models\User.php实现认证类,继承IdentityInterface并将common\models\User类复制到api\models\目录下,修改命名空间为api\modelsvalidate()){//returnYii::$app->user->login($this->getUser(),$this->还记得我吗?3600*24*30:0);如果($this->getUser()){$access_token=$this->_user->generateAccessToken();$this->_user->expire_at=time()+static::EXPIRE_TIME;$this->_user->save();伊伊::$app->user->login($this->_user,static::EXPIRE_TIME);返回$access_token;}}returnfalse;}上面的代码给User模型添加了一个generateAccessToken()方法,所以我们去api\models\User.php命名空间api\models;useYii;useyii\base\NotSupportedException中添加这个方法;使用yii\behaviors\TimestampBehavior;使用yii\db\ActiveRecord;使用yii\web\IdentityInterface;使用yii\web\UnauthorizedHttpException;......类UserextendsActiveRecordimplementsIdentityInterface{....../***生成accessToken字符串*@returnstring*@throws\yii\base\Exception*/publicfunctiongenerateAccessToken(){$this->access_token=Yii::$app->security->generateRandomString();返回$this->access_token;}}接下来在api\controllers\中添加一个新的controller,命名为UserController,继承自yii\rest\ActiveController,编写Login方法,具体代码如下:namespaceapi\controllers;useapi\models\LoginForm;useyii\rest\ActiveController;使用yii;类UserControllerextendsActiveController{public$modelClass='api\models\User';publicfunctionactions(){$action=parent::actions();//TODO:更改自动生成的存根unset($action['index']);取消设置($action['创建']);取消设置($action['更新']);取消设置($action['delete']);}publicfunctionactionIndex(){//你的代码}/***Login*@returnarray*@throws\yii\base\Exception*@throws\yii\base\InvalidConfigException*/publicfunctionactionLogin(){$model=新的登录表单();if($model->load(Yii::$app->getRequest()->getBodyParams(),'')&&$model->login()){return['access_token'=>$model->login(),];}else{return$model->getFirstErrors();}}}最后添加一条URL规则打开api\config\main.php修改components属性,添加如下代码:'urlManager'=>['enablePrettyUrl'=>true,'enableStrictParsing'=>true,'showScriptName'=>false,'rules'=>[['class'=>'yii\rest\UrlRule','controller'=>'user','extraPatterns'=>['POSTlogin'=>'login',],],],]使用调试工具测试http://youdomain/users/login记住是POST请求发送,如果POSTMAN有问题,指定Content-Type:application/x-www-form-urlencodedok,不出意外的话,相信你已经可以收到一个access_token了,接下来就是如何使用这个token,如何保持认证状态,如果不携带这个token,是无法访问的,返回401保持认证状态实现认证步骤:在你的REST控制器类中Configuretheauthenticatorbehavior指定使用哪种认证方式。在您的用户身份类中实现yiiwebIdentityInterface::findIdentityByAccessToken()方法。具体实现方法如下:打开之前的User控制器(api\controllers\UserController.php),添加如下内容:useyii\helpers\ArrayHelper;useyii\filters\auth\QueryParamAuth;...//some这里省略代码publicfunctionbehaviors(){returnArrayHelper::merge(parent::behaviors(),['authenticatior'=>['class'=>QueryParamAuth::className(),//实现访问令牌认证'except'=>['login'],//不需要验证accesstoken的方法,注意区分$noAclLogin]]);}...实现findIdentityByAccessToken()方法:打开api\models\User.php重写findIdentityByAccessToken()方法...使用yii\web\UnauthorizedHttpException;...classUserextendsActiveRecordimplementsIdentityInterface{....../***{@inheritdoc}*/公共静态functionfindIdentityByAccessToken($token,$type=null){//thrownewNotSupportedException('"findIdentityByAccessToken"未实现。');$user=static::find()->where(['access_token'=>$token,'status'=>self::STATUS_ACTIVE])->one();如果(!$user){返回false;}if($user->expire_at
