Laravel RESTful API

Installation

首先使用 composer 安装 Laravel 5.7。

composer create-project --prefer-dist laravel/laravel laravel-passport

然后运行如下命令启动内置 web 服务器。

php artisan serve

打开浏览器访问 http://localhost:8000/ 就能看到 Laravel 欢迎页面。

Authentication

安装完成之后,先修改 .env 文件中的数据库配置。

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=homestead
DB_USERNAME=homestead
DB_PASSWORD=secret

然后在命令行中运行下面两条命令。

php artisan make:auth
php artisan migrate

打开浏览器访问 http://localhost:8000/,你就会发现右上角多了 LOGIN 和 REGISTER 两个链接。

登录页面:http://localhost:8000/login

注册页面:http://localhost:8000/register

这一步我们注册了一个用户 Victor Tang。

mysql> select * from users;
+----+-------------+----------------------+-------------------+--------------------------------------------------------------+----------------+---------------------+---------------------+
| id | name        | email                | email_verified_at | password                                                     | remember_token | created_at          | updated_at          |
+----+-------------+----------------------+-------------------+--------------------------------------------------------------+----------------+---------------------+---------------------+
|  1 | Victor Tang | tanghengzhi@live.com | NULL              | $2y$10$6skKXJPSjMWUHEsNVcVAeuxCgrUTf.JPMIfTpRyp723BGC1jZhCSW | NULL           | 2019-01-07 13:33:07 | 2019-01-07 13:33:07 |
+----+-------------+----------------------+-------------------+--------------------------------------------------------------+----------------+---------------------+---------------------+
1 row in set (0.00 sec)

API Authentication (Passport)

首先使用 composer 安装 Passport。

composer require laravel/passport

然后执行下面的命令创建需要的表。

php artisan migrate
Migration table created successfully.
Migrating: 2014_10_12_000000_create_users_table
Migrated:  2014_10_12_000000_create_users_table
Migrating: 2014_10_12_100000_create_password_resets_table
Migrated:  2014_10_12_100000_create_password_resets_table
Migrating: 2016_06_01_000001_create_oauth_auth_codes_table
Migrated:  2016_06_01_000001_create_oauth_auth_codes_table
Migrating: 2016_06_01_000002_create_oauth_access_tokens_table
Migrated:  2016_06_01_000002_create_oauth_access_tokens_table
Migrating: 2016_06_01_000003_create_oauth_refresh_tokens_table
Migrated:  2016_06_01_000003_create_oauth_refresh_tokens_table
Migrating: 2016_06_01_000004_create_oauth_clients_table
Migrated:  2016_06_01_000004_create_oauth_clients_table
Migrating: 2016_06_01_000005_create_oauth_personal_access_clients_table
Migrated:  2016_06_01_000005_create_oauth_personal_access_clients_table

执行下面的命令生成 Encryption keys 并创建 Personal access client 和 Password grant client。

php artisan passport:install
Encryption keys generated successfully.
Personal access client created successfully.
Client ID: 1
Client secret: d0m5V3kRf8e4ZnmOtivHILNDSp3AouxkScXp0Ikp
Password grant client created successfully.
Client ID: 2
Client secret: Jksb3tYCbta0Y4pD4mO7lwUPyAFpj2oo9IEpfQZG

然后在 App\User model 中添加 Laravel\Passport\HasApiTokens trait。

use Laravel\Passport\HasApiTokens;
use Illuminate\Notifications\Notifiable;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Foundation\Auth\User as Authenticatable;

class User extends Authenticatable
{
    use HasApiTokens, Notifiable;
}

在 AuthServiceProvider 的 boot() 方法中调用 Passport::routes() 方法。

/**
 * Register any authentication / authorization services.
 *
 * @return void
 */
public function boot()
{
    $this->registerPolicies();

    Passport::routes();
}

最后修改 config/auth.php 配置文件中的 api 认证方式为 passport。

'guards' => [
    'web' => [
        'driver' => 'session',
        'provider' => 'users',
    ],

    'api' => [
        'driver' => 'passport',
        'provider' => 'users',
    ],
],

Authorization Code Grant

首先创建 Passport Client。

php artisan passport:client
 Which user ID should the client be assigned to?:
 > 1

 What should we name the client?:
 > tanghengzhi

 Where should we redirect the request after authorization? [http://localhost/auth/callback]:
 > http://127.0.0.1:8000/callback

New client created successfully.
Client ID: 3
Client secret: ArBmsXOLFwm39A23L29banA1PS3jd7doo9dqDnKX

然后获取 Access Token。

Authorization Code Grant

Implicit Grant

首先启用 Implicit Grant。

/**
 * Register any authentication / authorization services.
 *
 * @return void
 */
public function boot()
{
    $this->registerPolicies();

    Passport::routes();

    Passport::enableImplicitGrant();
}

然后获取 Access Token。

Implicit Grant

Password Credentials Grant

首先创建 passport client。

php artisan passport:client --password
What should we name the password grant client? [Laravel Password Grant Client]:
 > 

Password grant client created successfully.
Client ID: 4
Client secret: AcwwOugmcdk9nlJlnazQxfOjwSNHQmqoFMBHe9Zg

然后获取 Access Token。

Password Credentials Grant

Client Credentials Grant

获取 Access Token。

Client Credentials Grant

参考:

https://laravel.com/docs/5.7
https://laravel.com/docs/5.7/authentication
https://laravel.com/docs/5.7/passport

451 total views, no views today

RESTful API 设计 – OPTIONS

很常见的跨域问题,不常见的 OPTIONS 请求。


对于经常遇到的跨域访问的问题,只需要在Nginx配置文件里加入以下配置,即可开启跨域。

add_header Access-Control-Allow-Origin *;

* 表示任何域名都可以访问,如果要在生产环境使用,建议换成具体的域名,比如 Access-Control-Allow-Origin: http://domain.com。

但是对于一些不安全的请求,比如 PUT,DELETE 请求,或者 Content-Type: application/json 的 POST 请求,浏览器必须首先使用 OPTIONS 方法发起一个预检请求(preflight request),从而获知服务端是否允许该跨域请求。服务器确认允许之后,才发起实际的 HTTP 请求。

由于在设计 RESTful API 的时候并没有考虑到 OPTIONS 请求的情况,所以只能在 Nginx 中对 OPTIONS 请求进行统一配置。

if ($request_method = 'OPTIONS') { 
	add_header Access-Control-Allow-Origin *; 
	add_header Access-Control-Allow-Methods GET,POST,PUT,DELETE,OPTIONS;
	add_header Access-Control-Allow-Headers Content-Type;
	return 204; 
}

最终的 Nginx 配置是这样的。

add_header Access-Control-Allow-Origin *;

location / {
    if ($request_method = 'OPTIONS') { 
	add_header Access-Control-Allow-Origin *; 
	add_header Access-Control-Allow-Methods GET,POST,PUT,DELETE,OPTIONS;
	add_header Access-Control-Allow-Headers Content-Type;
	return 204; 
    }

    try_files $uri $uri/ /index.php$is_args$args;
}

参考:

https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Access_control_CORS

https://tools.ietf.org/html/rfc7231#section-4.3.7

246 total views, 2 views today

Yii2 RESTful 实践

安装 Yii

创建工作目录

mkdir yii2-rest
cd yii2-rest

创建 composer.json

{
    "require": {
        "yiisoft/yii2": "~2.0.0"
    },
    "repositories": [
        {
            "type": "composer",
            "url": "https://asset-packagist.org"
        }
    ]
}

然后运行 composer install 命令。

写一个 Hello World

创建 web/index.php

<?php

// comment out the following two lines when deployed to production
defined('YII_DEBUG') or define('YII_DEBUG', true);
defined('YII_ENV') or define('YII_ENV', 'dev');

require(__DIR__ . '/../vendor/autoload.php');
require(__DIR__ . '/../vendor/yiisoft/yii2/Yii.php');

$config = require __DIR__ . '/../config.php';
(new yii\web\Application($config))->run();

创建 config.php

<?php

return [
    'id' => 'yii2-rest',
    // the basePath of the application will be the `yii2-rest` directory
    'basePath' => __DIR__,
    // this is where the application will find all controllers
    'controllerNamespace' => 'api\controllers',
    // set an alias to enable autoloading of classes from the 'api' namespace
    'aliases' => [
        '@api' => __DIR__,
    ],
];

创建 controllers/SiteController.php

<?php

namespace api\controllers;

use yii\web\Controller;

class SiteController extends Controller
{
    public function actionIndex()
    {
        return 'Hello World!';
    }
}

然后运行如下命令启动内置 web 服务器。

vendor/bin/yii serve --docroot=./web

在浏览器中打开 http://localhost:8080 应该就可以看到 “Hello World!”

创建一个 REST API

首先添加 MySQL 数据库配置。

'components' => [
    'db' => [
        'class' => 'yii\db\Connection',
        'dsn' => 'mysql:host=127.0.0.1;dbname=rest_api',
        'username' => 'root',
        'password' => '123456',
        'charset' => 'utf8mb4',
    ],
]

然后使用 Yii Migrate 创建表。

vendor/bin/yii migrate/create --appconfig=config.php create_post_table --fields="title:string,body:text"
vendor/bin/yii migrate/up --appconfig=config.php

创建 models/Post.php

<?php

namespace api\models;

use yii\db\ActiveRecord;

class Post extends ActiveRecord
{ 
    public static function tableName()
    {
        return '{{post}}';
    }
}

创建 controller/PostController.php

<?php

namespace api\controllers;

use yii\rest\ActiveController;

class PostController extends ActiveController
{
    public $modelClass = 'api\models\Post';

    public function behaviors()
    {
        // remove rateLimiter which requires an authenticated user to work
        $behaviors = parent::behaviors();
        unset($behaviors['rateLimiter']);
        return $behaviors;
    }
}

启用 JSON 输入

'request' => [
    'parsers' => [
       'application/json' => 'yii\web\JsonParser',
    ]
],

配置URL规则

'urlManager' => [
    'enablePrettyUrl' => true,
    'enableStrictParsing' => true,
    'showScriptName' => false,
    'rules' => [
        ['class' => 'yii\rest\UrlRule', 'controller' => 'post'],
    ],
],

现在我们就可以提供如下 REST API :

GET    /posts   - 列出所有帖子
GET    /posts/1 - 显示 ID 为 1 的帖子
POST   /posts   - 创建一个帖子
UPDATE /posts/1 - 更新 ID 为 1 的帖子
PATCH  /posts/1 - 更新 ID 为 1 的帖子
DELETE /posts/1 - 删除 ID 为 1 的帖子

参考:

https://www.yiiframework.com/doc/guide/2.0/zh-cn/tutorial-yii-as-micro-framework

https://github.com/tanghengzhi/yii2-rest

333 total views, no views today