我正在尝试使用身份验证创建一个简单的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);
答案 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! 即使通知正确的用户和密码,我也总是会收到未经授权的访问权。
由于