laravel+dingo+jwt搭建api系统

laravel+dingo+jwt搭建api系统

一: 安装 laravel ( https://learnku.com/docs/laravel/8.x/installation/9354 )

//可能需要先安装一下国内的 Composer 加速镜像:
composer config -g repo.packagist composer https://mirrors.aliyun.com/composer/

//安装 laravel 项目(最新版本):
composer create-project --prefer-dist laravel/laravel la8(项目名称)

二: 安装 Dingo ( https://learnku.com/docs/dingo-api/2.0.0/Installation/1443 )

composer require dingo/api

三: 安装 JWT

composer require tymon/jwt-auth

生成 JWT_SECRET 写入.env(自动写入)
php artisan jwt:secret

四: 配置文件 config/app.php

//在 providers 数组中添加以下两个服务提供者:
	
"providers"=>[
    ...
    Dingo\Api\Provider\LaravelServiceProvider::class,
    Tymon\JWTAuth\Providers\LaravelServiceProvider::class,
],
	
//在 aliases 数组中给 JWT 以下两个类添加别名方便之后生成 token 时使用,(当然也可以使用 Auth 门面生成 token , 所以不添加也是可以的。) 
	
'aliases' => [
    ...
    'JWTAuth' => Tymon\JWTAuth\Facades\JWTAuth::class,
    'JWTFactory' => Tymon\JWTAuth\Facades\JWTFactory::class,
]

五: 生成 Dingo 和 JWT 的配置文件

php artisan vendor:publish --provider="Dingo\Api\Provider\LaravelServiceProvider"  //生成 Dingo 的 api.php 文件
【 实际上是 vendor/dingo/api/config/api.php 这个配置文件 】

php artisan vendor:publish --provider="Tymon\JWTAuth\Providers\LaravelServiceProvider"  //生成 JWT 的 jwt.php 文件
【 实际上是 vendor/tymon/jwt-auth/config/config.php 这个配置文件 】

六:修改 api.php 和 jwt.php 配置文件

//在 api.php 的 auth 数组中添加 api 权限验证类

'auth' => [
    'jwt' => Dingo\Api\Auth\Provider\JWT::class,  // api 权限验证类
],

//把 jwt.php providers 数组中的 token 生成类(Lcobucci)修改为 Namshi 如下:

'providers' => [
    //'jwt' => Tymon\JWTAuth\Providers\JWT\Lcobucci::class, // 使用 attempt() 方法生成 token (本人不推荐使用这方法)
    
    'jwt' => Tymon\JWTAuth\Providers\JWT\Namshi::class, //使用 formUser() 方法生成 token  
    
    .
	.
	.

七:修改 config/auth.php 配置文件

//把 defaults 数组中的默认守卫(网关)改为 api  如下:

'defaults' => [
    'guard' => 'api',//'web',
    'passwords' => 'users',
],

//把 guards 数组中的 api 守卫的驱动改为 jwt  如下:

'guards' => [
    ...
    'api' => [
        'driver' => 'jwt',   //'token',
        'provider' => 'users',
        'hash' => false,
    ],
],

八: 在 .env 中写入 Dingo 配置 ( 具体配置见: https://learnku.com/docs/dingo-api/2.0.0/Configuration/1444 )

#以下是我的配置:

API_STANDARDS_TREE=vnd  
API_SUBTYPE=laravel 
API_PREFIX=api 
#子域名  (前缀和子域名只能存在一个)可选
#API_DOMAIN=api.myapp.com 
API_VERSION=v1
API_NAME=api-demo
#API_CONDITIONAL_REQUEST=false 
#API_STRICT=false 
API_DEFAULT_FORMAT=json 
API_DEBUG=true

九: 在 .env 中配置数据库

#以下是我的配置:

DB_CONNECTION=mysql
DB_HOST=localhost
DB_PORT=3306
DB_DATABASE=la8
DB_USERNAME=root
DB_PASSWORD=123

十: 执行数据迁移

php artisan migrate

主要是生成 users 数据表

十一: 修改 Models/User.php 如下:

<?php

namespace App\Models;

use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Tymon\JWTAuth\Contracts\JWTSubject;   //

class User extends Authenticatable implements JWTSubject
{
    use HasFactory, Notifiable;

    public $table = 'users';

    const CREATED_AT = 'created_at';
    const UPDATED_AT = 'updated_at';

    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = [
        'name',
        'phone',  //注意我在数据表 users 中添加了 phone 字段
        'email',
        'password',
    ];

    /**
     * The attributes that should be hidden for arrays.
     *
     * @var array
     */
    protected $hidden = [
        'password',
        'remember_token',
    ];

    /**
     * The attributes that should be cast to native types.
     *
     * @var array
     */
    protected $casts = [
        'email_verified_at' => 'datetime',
    ];

    //实现 JWTSubject 以下两个接口函数
    public function getJWTIdentifier(){`在这里插入代码片`
        return $this->getKey();
    }

    public function getJWTCustomClaims(){
        return [];
    }

}

十二: 注册 BaseController.php 控制器目的是调整一下请求响应的数据格式。(目录 :/app/Http/Controllers/Api/V1/BaseController.php)

<?php

namespace App\Http\Controllers\Api\V1;

use Dingo\Api\Routing\Helpers;
use App\Http\Controllers\Controller;
use Dingo\Api\Exception\ValidationHttpException;

class BaseController extends Controller{
    // 接口帮助调用
    use Helpers;

    // 工具函数
    // 返回错误的请求
    protected function errorBadRequest($validator)
    {
        // github like error messages
        // if you don't like this you can use code bellow
        //
        //throw new ValidationHttpException($validator->errors());

        $result = [];
        $messages = $validator->errors()->toArray();
        if ($messages) {
            foreach ($messages as $field => $errors) {
                foreach ($errors as $error) {
                    $result[] = [
                        'field' => $field,
                        'code' => $error,
                    ];
                }
            }
        }
        //throw new ValidationHttpException($result);
        $this->responseValidationError($result);
    }

    // 请求成功时对数据进行格式处理
    public function responseSuccess($data) {
        return response()->json([
            'code' => '200',
            'data' => $data
        ]);
    }

    // 响应失败时返回自定义错误信息
    public function responseError($msg) {
        return response()->json([
            'code' => '400',
            'msg' => $msg
        ]);
    }

    // 响应校验失败时返回自定义的信息(基本用不上)
    public function responseValidationError($msgs) {
        return response()->json([
            'code' => '401',
            'msgs' => $msgs
        ]);
    }

    // 能用错误提示方法
    public function onError($msgs){
        return response()->json([
            'code' => 'error',
            'msgs' => $msgs
        ]);
    }

}

十三: 在 Models 中创建 Authorization.php 目的是为了获取格式化的 token 相关信息

<?php
    
    namespace App\Models;
    
    use Carbon\Carbon;
    
    class Authorization
    {
        protected $token;
    
        protected $payload;
    
        public function __construct($token = null)
        {
            $this->token = $token;
        }
    
        public function setToken($token)
        {
            $this->token = $token;
    
            return $this;
        }
    
        public function getToken()
        {
            if (! $this->token) {
                throw new \Exception('请设置token');
            }
    
            return $this->token;
        }
    
        public function getPayload()
        {
            if (! $this->payload) {
                $this->payload = \Auth::setToken($this->getToken())->getPayload();
            }
            
            return $this->payload;
        }
    
        public function getExpiredAt()
        {
            return Carbon::createFromTimestamp($this->getPayload()->get('exp'))
                ->toDateTimeString();
        }
    
        public function getRefreshExpiredAt()
        {
            return Carbon::createFromTimestamp($this->getPayload()->get('iat'))
                ->addMinutes(config('jwt.refresh_ttl'))
                ->toDateTimeString();
        }
    
        public function user()
        {
            return \Auth::authenticate($this->getToken());
        }
    
        public function toArray()
        {
            return [
                'token' => $this->getToken(),
                'token_type' => 'Bearer',
                'expired_at' => $this->getExpiredAt(),
                // 'refresh_expired_at' => $this->getRefreshExpiredAt(),
            ];
        }
    }

十四: 注册 AuthController.php 实现注册、登录、刷新token 和登出功能(目录: app/Http/Controllers/Api/V1/Auth/AuthController.php)

<?php
    
    namespace App\Http\Controllers\Api\V1\Auth;
    
    use App\Http\Controllers\Api\V1\BaseController;
    use Illuminate\Http\Request;
    use App\Models\Authorization;
    use App\Transformers\AuthorizationTransformer;
    use Illuminate\Support\Facades\Hash;
    use Dingo\Api\Exception\StoreResourceFailedException;
    use App\Models\User;
    use Auth;
    
    
    class AuthController extends BaseController
    {
        // 注册接口
        public function register(Request $request) {
            $isPhone = preg_match("/^1[3456789]\d{9}$/", $request->phone);
            $validator = $this->validator($request->all());
            if($isPhone != 1){
                return $this->responseError('请正确输入手机号');
            }
            if ($validator->fails()) {
                return $this->errorBadRequest($validator);
            }
    
            $user = $this->create($request->all());
            if ($user->save() == 1) {
                $token = \Auth::fromUser($user);
                if($token !="" || $token !=null) {
                    $authorization = new Authorization($token);
                    return $this->responseSuccess(['token' => $authorization->toArray(), 'user' => $user]);
                }
                User::find($user->id)->delete();
                return $this->responseError("用户注册失败,请重试!");
            } else {
                return $this->responseError("用户注册失败,请重试!");
            }
        }
    
        protected function validator(array $data) {
            return \Validator::make($data, [
                'name' => 'required',
                'phone' => 'required|unique:users',
                'email' => 'required|email|max:255|unique:users',
                'password' => 'required|min:6',
            ]);
        }
    
        protected function create(array $data) {
            return User::create([
                'name' => $data['name'],
                'phone' => $data['phone'],
                'email' => $data['email'],
                'password' =>  Hash::make($data['password']),
            ]);
        }
    
        // 登录接口
        public function login(Request $request)
        {
            $validator = \Validator::make($request->all(), [
                'phone' => 'required',
                'password' => 'required',
            ]);
    
            if ($validator->fails()) {
                return $this->errorBadRequest($validator);
            }
            $user = User::where('phone', $request->phone)->first();
            if ($user && Hash::check($request->get('password'), $user->password)){
                $token = \Auth::fromUser($user);
                if($token !="" || $token !=null) {
                    $authorization = new Authorization($token);
                    return $this->responseSuccess(['token' => $authorization->toArray(), 'user' => $user]);
                }
                return $this->responseError(trans('auth.incorrect'));
            }
            return $this->responseError("登录失败,请重试!");
        }
        
        //刷新token接口 (一个 token 只能刷新一次 ,并且需要在 token 的过期时间内进行刷新) 
        public function update()
        {
            $authorization = new Authorization(\Auth::refresh());
            return $this->responseSuccess(['token' => $authorization->toArray(), 'user' => $authorization->user()]);
        }
    
        // 注销接口
        public function destroy()
        {
            \Auth::logout();
            return $this->responseSuccess("logout");
        }
    
    }

十五: 在 routes/api.php 中管理路由

<?php

    use Illuminate\Http\Request;
    use Illuminate\Support\Facades\Route;
    
    /*
    |--------------------------------------------------------------------------
    | API Routes
    |--------------------------------------------------------------------------
    |
    | Here is where you can register API routes for your application. These
    | routes are loaded by the RouteServiceProvider within a group which
    | is assigned the "api" middleware group. Enjoy building your API!
    |
    */
    
    // Route::middleware('auth:api')->get('/user', function (Request $request) {
    //     return $request->user();
    // });
    
    //管理路由 
    $api = app('Dingo\Api\Routing\Router');
    
    $api->version('v1',[
        'namespace' => 'App\Http\Controllers\Api\V1'
    ], function ($api) {
         $api->group(['namespace' => 'Auth', "prefix" => 'auth'], function ($api) {
            $api->post('/register', 'AuthController@register');
            $api->post('/login', 'AuthController@login');
    
            $api->group(['middleware' => 'api.auth'], function ($api) {
                $api->post('/refresh', 'AuthController@update');
                $api->post('/logout', 'AuthController@destroy');
            });
        });
    
    });
    
    其中 : 刷新token 和 注销接口 请求的时候需要以下请求头:
    
    Authorization  : Bearer + "your token"

十六: 关于解决请求跨域问题

在最新版本的laravel(8.*)框架中已经提供了解决请求跨域的CORS扩展包( 我这里使用: "fruitcake/laravel-cors": "^2.0"1、 在 config/app.php 的 providers 中添加 CORS 服务提供者
	 'providers' => [
	    ...
	    Fruitcake\Cors\CorsServiceProvider::class,
	 ]
 
2、  在 app/Http/Kernel.php 添加 cors 路由中间件:
	
	检查一下是否存在以下记录再去添加 cors 路由中间件
	protected $middleware = [
	    ...
	    \Fruitcake\Cors\HandleCors::class,
	]
 
	protected $routeMiddleware = [
	    ...
	    'cors' =>   \Fruitcake\Cors\HandleCors::class,
	];
 
3、 在 routes/api.php 中添加路由 cors 中间件:
	$api = app('Dingo\Api\Routing\Router');
	    
	$api->version('v1',[
	    'namespace' => 'App\Http\Controllers\Api\V1',
	    'middleware' => [
	        'cors'
	    ],
	    // each route have a limit of 1000 of 1 minutes
	    'limit' => 1000, 'expires' => 1,
	], function ($api) {
	     $api->group(['namespace' => 'Auth', "prefix" => 'auth'], function ($api) {
	        $api->post('/register', 'AuthController@register');
	        $api->post('/login', 'AuthController@login');
	
	        $api->group(['middleware' => 'api.auth'], function ($api) {
	            $api->post('/refresh', 'AuthController@update');
	            $api->post('/logout', 'AuthController@destroy');
	        });
	    });
	
	});
     
 4、 在 config/cors.php 配置跨域相关信息:
 <?php

     return [
     
         /*
         |--------------------------------------------------------------------------
         | Cross-Origin Resource Sharing (CORS) Configuration
         |--------------------------------------------------------------------------
         |
         | Here you may configure your settings for cross-origin resource sharing
         | or "CORS". This determines what cross-origin operations may execute
         | in web browsers. You are free to adjust these settings as needed.
         |
         | To learn more: https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS
         |
         */
     
         'paths' => ['api/*', 'sanctum/csrf-cookie'],
     
         'allowed_methods' => ['*'],
     
         'allowed_origins' => ['*'],
     
         'allowed_origins_patterns' => [],
     
         'allowed_headers' => ['*'],
     
         'exposed_headers' => [],
     
         'max_age' => 0,
     
         'supports_credentials' => false,
     
     ];

十七: 请求注册用户接口
在这里插入图片描述

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值