Yii2 REST API没有返回预期的结果

时间:2014-08-18 22:53:47

标签: php json rest yii yii2

我正在尝试使用身份验证创建一个简单的REST API。但是,有些事情是错误的。

我正在使用Yii Framework 2的高级模板。我以前从未为yii编程,所以我正在学习。

我的代码:

〜/ API      - >配置        - > main.php

<?php

$params = array_merge(
    require(__DIR__ . '/../../common/config/params.php'),
    require(__DIR__ . '/../../common/config/params-local.php'),
    require(__DIR__ . '/params.php'),
    require(__DIR__ . '/params-local.php')
);

return [
    'id' => 'app-api',
    'basePath' => dirname(__DIR__),    
    'bootstrap' => ['log'],
    'modules' => [
        'v1' => [
            'basePath' => '@app/modules/v1',
            'class' => 'api\modules\v1\Module'
        ]
    ],
    'components' => [        
        'user' => [
            'identityClass' => 'common\models\User',
            'enableAutoLogin' => false,
        ],
        'log' => [
            'traceLevel' => YII_DEBUG ? 3 : 0,
            'targets' => [
                [
                    'class' => 'yii\log\FileTarget',
                    'levels' => ['error', 'warning'],
                ],
            ],
        ],
        'request' => [
            'class' => '\yii\web\Request',
            'enableCookieValidation' => false,
            'parsers' => [
                'application/json' => 'yii\web\JsonParser',
            ],
        ],        
        'urlManager' => [
            'enablePrettyUrl' => true,
            'enableStrictParsing' => true,
            'showScriptName' => false,
            'rules' => [
                [
                    'class' => 'yii\rest\UrlRule', 
                    'controller' => 'v1/teste',
                    'extraPatterns' => [
                            'GET testando' => 'testando',
                        ],
                ],
                [
                    'class' => 'yii\rest\UrlRule',
                    'controller' => 'v1/user',
                    'extraPatterns' => [
                            'GET login' => 'login',
                        ],
                ],
                'OPTIONS v1/user/login' => 'v1/user/login',
                'POST v1/user/login' => 'v1/user/login',
            ],        
        ]
    ],
    'params' => $params,
];

- &GT;模块 - &gt; v1 - &gt;控制器 - &gt; TesteController.php

<?php

namespace api\modules\v1\controllers;

//Formato json
use yii\filters\ContentNegotiator;
use yii\web\Response;

//Banco de dados
use yii\db\ActiveRecord;

//Segurança
use yii\filters\auth\CompositeAuth;
use yii\filters\auth\QueryParamAuth;

//Rest api
use yii\rest\ActiveController;

/**
 * Country Controller API
 *
 * @author Budi Irawan <deerawan@gmail.com>
 */
class TesteController extends ActiveController
{
    public $modelClass = 'api\modules\v1\models\Teste';

    public function behaviors()
    {
        $behaviors = parent::behaviors();
        $behaviors['authenticator'] = [
            'class' => QueryParamAuth::className(),
        ];
        $behaviors['bootstrap'] = [
            'class' => ContentNegotiator::className(),
        'formats' => [
            'application/json' => Response::FORMAT_JSON,
        ],
    ];  
        return $behaviors;  
    }

    public function actionTestando(){
    echo "testado";
    }
}

- &GT;模块 - &gt; v1 - &gt;控制器 - &gt; UserController.php

<?php
namespace api\modules\v1\controllers;

use common\models\LoginForm;
use yii\rest\ActiveController;

class UserController extends ActiveController
{
    public $modelClass = 'common\models\User';

    public function actionLogin()
    {
        $model = new LoginForm();

        if ($model->load(\Yii::$app->getRequest()->getBodyParams(), '') && $model->login()) {
            echo \Yii::$app->user->identity->getAuthKey();
        } else {
            return $model;
        }
    }

    public function actionIndex()
    {
        if (\Yii::$app->user->isGuest) {
            throw new \HttpHeaderException();
        }
        return \Yii::$app->user->getId();
    }
}

- &GT;模块 - &gt; v1 - &gt;模特 - &gt; Teste.php

<?php

namespace api\modules\v1\models;

use yii\behaviors\TimestampBehavior;

use \yii\db\ActiveRecord;

class Teste extends ActiveRecord 
{
    /**
     * @inheritdoc
     */
    public static function tableName()
    {
        return '{{%teste}}';
    }

    /**
     * @inheritdoc
     */
    public function behaviors()
    {
        return [
            TimestampBehavior::className(),
        ];
    }
}

- &GT;模块 - &gt; v1 - &gt;模特 - &gt; user.php的

<?php

namespace api\modules\v1\models;

use common\models\User as CommonUser;

class User extends CommonUser
{

}

- &GT;模块 - &gt; v1 - &gt; Module.php

<?php
namespace api\modules\v1;

class Module extends \yii\base\Module
{
    public $controllerNamespace = 'api\modules\v1\controllers';

    public function init()
    {
        parent::init();        
    }
}

然后当我用以下方法测试REST API时

curl -D- -u admin:123mudar! -H "Content-Type:application/json" 'http://www.domain.com/v1/testa/api/web/v1/testes'

我有:

HTTP/1.1 401 Unauthorized
Date: Mon, 18 Aug 2014 22:44:10 GMT
Server: Apache
Transfer-Encoding: chunked
Content-Type: application/json; charset=UTF-8

{"type":"yii\\web\\UnauthorizedHttpException","name":"Unauthorized","message":"You are requesting with an invalid access token.","code":0,"status":401}

即使我正在使用restClient插件。缺少什么?

数据库表结构:

CREATE TABLE IF NOT EXISTS `teste` (
  `codigo` int(11) NOT NULL AUTO_INCREMENT,
  `nome` varchar(100) NOT NULL,
  PRIMARY KEY (`codigo`),
  KEY `nome` (`nome`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=3 ;

INSERT INTO `teste` (`codigo`, `nome`) VALUES
(1, 'valor 1'),
(2, 'valor 2');

CREATE TABLE IF NOT EXISTS `user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(255) NOT NULL,
  `auth_key` varchar(32) NOT NULL,
  `password_hash` varchar(255) NOT NULL,
  `password_reset_token` varchar(255) DEFAULT NULL,
  `email` varchar(255) NOT NULL,
  `role` smallint(6) NOT NULL DEFAULT '10',
  `status` smallint(6) NOT NULL DEFAULT '10',
  `created_at` int(11) NOT NULL,
  `updated_at` int(11) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 AUTO_INCREMENT=2 ;


INSERT INTO `user` (`id`, `username`, `auth_key`, `password_hash`, `password_reset_token`, `email`, `role`, `status`, `created_at`, `updated_at`) VALUES
(1, 'admin', '79UF7P3XNV9t075lv1kA8G3mYVaysaIw', '$2y$13$A8x5bNgFSwyN6RTFtgZ2h.oGu87gWqiRrci/jZYzT.KwF6o6sLTzC', NULL, 'admin@admin.com', 10, 10, 1408061655, 1408061655);

3 个答案:

答案 0 :(得分:5)

来自@Ganiks的回答有点误导。您不必重新构造任何内容,您需要做的是覆盖控制器行为并添加自定义回调以进行凭据检查。您的身份模型中也没有必要使用访问令牌

快速解决方案:

$behaviors['authenticator'] = [
    'class' => HttpBasicAuth::className(),
    'auth' => function ($username, $password) {
        // Return Identity object or null
        return User::findOne([
            'username' => $username,
            'password' => $password
        ]);
    },
];

官方指南介绍了在Yii2 RESTful API(http://www.yiiframework.com/doc-2.0/guide-rest-authentication.html)中使用访问令牌的概念以及正确的设置方法。尽管如此,内置身份验证器HttpBasicAuth实际上使用的是用户名:密码

实际上, HTTP Basic Auth 中的访问令牌实际上是使用username:password编码的,请参阅wiki(http://en.wikipedia.org/wiki/Basic_access_authentication#Protocol)中的定义。

答案 1 :(得分:1)

Yii2 RESTful API使用access-token进行身份验证而不是username:password,如果您的用户表没有access_token列,请创建一个并更新您的用户;

Yii2基本模板的用户模型有access_token,如下所示:

private static $users = [ '100' => [ 'id' => '100', 'username' => 'admin', 'password' => 'admin', 'authKey' => 'test100key', 'accessToken' => '100-token', ], '101' => [ 'id' => '101', 'username' => 'demo', 'password' => 'demo', 'authKey' => 'test101key', 'accessToken' => '101-token', ], ];

然后,当您提出请求时,请使用此accessToken作为username并将password留空,请尝试。

另一种方法是,您可以使用use yii\filters\auth\QueryParamAuth;并使用curl http://192.168.4.126/news/126?access-token=100-token进行测试,两者都可以。

更多细节,你可以参考我的文章:

http://www.cnblogs.com/ganiks/p/yii2-restful-api-dev.html

最后,如果你真的想使用username:password,你可以重新构建yii2-rest,参考:

http://www.cnblogs.com/ganiks/p/yii2-restful-api-mechanism.html

答案 2 :(得分:0)

好的,现在我有我的休息api要求输入用户名和密码。但是,总是得到错误401。

要求输入用户名和密码,我必须更改: - &GT;模块 - &gt; v1 - &gt;控制器 - &gt; TesteController.php

<?php
namespace api\modules\v1\controllers;
//Formato json
use yii\filters\ContentNegotiator;
use yii\web\Response;
//Banco de dados
use yii\db\ActiveRecord;

//Segurança
use yii\filters\auth\CompositeAuth;
//use yii\filters\auth\QueryParamAuth; ####################### <<<<<<<<<---- QUERYPARAMS TO HTTPBASICAUTH
use yii\filters\auth\HttpBasicAuth;

//Rest api
use yii\rest\ActiveController;

class TesteController extends ActiveController
{
    public $modelClass = 'api\modules\v1\models\Teste';

    public function behaviors()
    {
        $behaviors = parent::behaviors();
        /*$behaviors['authenticator'] = [
            'class' => QueryParamAuth::className(),
        ];*/
        $behaviors['authenticator'] = [
            'class' => HttpBasicAuth::className(), //###### <<<<<-------- FROM QueryParamAuth::className(), to HttpBasicAuth::className()
        ];  
        $behaviors['bootstrap'] = [
            'class' => ContentNegotiator::className(),
        'formats' => [
            'application/json' => Response::FORMAT_JSON,
        ],
    ];  
        return $behaviors;  

        /*return [
        'bootstrap' => [
        'class' => ContentNegotiator::className(),
        'formats' => [
            'application/json' => Response::FORMAT_JSON,
        ],
        ],

            'authenticator' => [
        'class' => CompositeAuth::className(),
            ],
    ];*/
    }



    public function actionTestando(){
    echo "testado";
    }

}

用户是管理员,密码是123mudar! 即使通知正确的用户和密码,我也总是会收到未经授权的访问权。

由于