Yii2 REST API不返回预期结果

D M*_*ler 2 php rest json yii yii2

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

我正在使用Yii Framework 2的高级模板.我从来没有为yii编程,所以我正在学习.

我的代码:

〜/ api - > config - > 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,
];
Run Code Online (Sandbox Code Playgroud)

- > modules - > v1 - > controllers - > 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";
    }
}
Run Code Online (Sandbox Code Playgroud)

- > modules - > v1 - > controllers - > 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();
    }
}
Run Code Online (Sandbox Code Playgroud)

- > modules - > v1 - > models - > 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(),
        ];
    }
}
Run Code Online (Sandbox Code Playgroud)

- > modules - > v1 - > models - > User.php

<?php

namespace api\modules\v1\models;

use common\models\User as CommonUser;

class User extends CommonUser
{

}
Run Code Online (Sandbox Code Playgroud)

- > modules - > v1 - > Module.php

<?php
namespace api\modules\v1;

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

    public function init()
    {
        parent::init();        
    }
}
Run Code Online (Sandbox Code Playgroud)

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

curl -D- -u admin:123mudar! -H "Content-Type:application/json" 'http://www.domain.com/v1/testa/api/web/v1/testes'
Run Code Online (Sandbox Code Playgroud)

我有:

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}
Run Code Online (Sandbox Code Playgroud)

即使我正在使用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);
Run Code Online (Sandbox Code Playgroud)

Vic*_*ong 5

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

快速解决方案

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

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

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