1、通过Composer安装Passport

composer require laravel/passport

2、在配置文件app.php中的providers数组中注册Passport服务:

Laravel\Passport\PassportServiceProvider::class,

3、生成用于存放客户端和访问令牌的数据表

php artisan migrate

4、创建token所需的加密键

php artisan passport:install

5、添加LaravelPassportHasApiTokens trait 到 AppUser 模型

namespace App;

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


class User extends Authenticatable
{
    use HasApiTokens,Notifiable;
    ......    
}

6、在 AuthServiceProvider 的 boot 方法中调用 Passport::routes 方法

        Passport::routes(
             //只开放 /oauth/token);
            function(RouteRegistrar $router){
                $router->forAccessTokens();
            },
            ['prefix' => 'api']

7、设置 api 认证 guard 的 driver 选项为 passport

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

8、配置更短的令牌生命周期,可以使用 tokensExpireIn 和 refreshTokensExpireIn 方法

    Passport::tokensExpireIn(Carbon::now()->addDays(15));
    Passport::refreshTokensExpireIn(Carbon::now()->addDays(30));

9、创建ApiController


namespace App\Http\Controllers\Api;

use App\Http\Traits\ApiResponse;
use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\AuthenticatesUsers;
use Illuminate\Http\Request;

class ApiController extends Controller
{
    use  AuthenticatesUsers;
    use ApiResponse;

    public function __construct()
    {
        $this->middleware('api');
    }

    //调用认证接口获取授权码
    protected function authenticateClient(Request $request)
    {
        $credentials = $this->credentials($request);

        $data = $request->all();
        if ($request->refresh_token) {
            $request->request->add([
                'grant_type' => $data['grant_type'],
                'client_id' => $data['client_id'],
                'client_secret' => $data['client_secret'],
                'refresh_token' => $data['refresh_token'],
                'scope' => ''
            ]);
        } else {
            $request->request->add([
                'grant_type' => $data['grant_type'],
                'client_id' => $data['client_id'],
                'client_secret' => $data['client_secret'],
                'email' => $data['email'],
                'password' => $data['password'],
                'scope' => ''
            ]);
        }

        $proxy = Request::create(
            'oauth/token',
            'POST'
        );

        $response = \Route::dispatch($proxy);

        return $response;
    }
    /*
     *重写AuthenticatesUsers部分功能函数来实现整个完整的授权流程
     */
    protected function authenticated(Request $request)
    {
        return $this->authenticateClient($request);
    }

    protected function sendLoginResponse(Request $request)
    {
        $this->clearLoginAttempts($request);

        return $this->authenticated($request);
    }

    protected function sendFailedLoginResponse(Request $request)
    {
        $msg = $request['errors'];
        $code = $request['code'];
        return $this->failed($msg,$code);
    }
}

10、创建LoginController

<?php
/**
 * Created by PhpStorm.
 * User: hzh
 * Date: 2018/5/1
 * Time: 14:17
 */
namespace App\Http\Controllers\Api;

use App\Http\Controllers\Api\ApiController;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use App\User;
use Illuminate\Support\Facades\Auth;
use Laravel\Passport\Token;
use Validator;


class LoginController extends ApiController
{
    protected $successStatus = 200;

    public function __construct()
    {
        $this->middleware('auth:api')->only([
            'logout'
        ]);
    }

    // 登录用户名标示为email字段
    public function username()
    {
        return 'email';
    }

    public function login(Request $request){

        $user = $request->only(['password','email']);
        if(count($user) != 2)return response()->json(['error_code'=>203,'error'=>'Missing Parameter']);
        if(Auth::attempt(['email' => request('email'), 'password' => request('password')])){
            $user = Auth::user();
            $success['token'] =  $user->createToken('Imagingbay')->accessToken;
            $success['email'] =  $user->email;
            $success['uid'] =  $user->id;
            return response()->json(['error_code'=>0,'data' => $success], 200)->withHeaders(
                [
                    'Accept' => 'application/json',
                    'Authorization' => 'Bearer '.$success['token']
                ]
            );
        }
        else{
            return response()->json(['error_code'=>202,'error'=>'Unauthorised'], 401);
        }
    }

    /**
     * Register api
     *
     * @return \Illuminate\Http\Response
     */
    public function register(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'email' => 'required|string|email|max:255|unique:user_ordinary|min:4',
            'password' => 'required|string|min:6|confirmed',
            'password_confirmation' => 'required|same:password',
        ]);

        if ($validator->fails()) {
            return response()->json(['error'=>$validator->errors()], 401);
        }

        $input = $request->all();
        $input['password'] = bcrypt($input['password']);
        $user = User::create($input);
        $success['token'] =  $user->createToken('Imagingbay')->accessToken;
        $success['email'] =  $user->email;
        $success['uid'] =  $user->id;

        return response()->json(['error_code'=>0,'data'=>$success], $this->successStatus);
    }

    /*
     * 注销账号
     */
    public function logout(Request $request)
    {
        'status_code' => 200, 'data' => null]);

        $user = $this->guard()->user();
        if (empty($user)) {
            return response()->json(['message' => '暂未登录', 'error_code' => 20403, 'data' => null]);
        }

        // 获取当前登陆用户的token并且将其删除
        $token = Auth::guard('api')->user()->token();
        if (empty($token)) {
            return response()->json(['message' => '暂无有效令牌', 'error_code' => 20403, 'data' => null]);
        }

        if (!empty($token->delete())) {
            return response()->json(['message' => '退出成功', 'error_code' => 0, 'data' => null]);
        } else {
            return response()->json(['message' => '退出失败', 'error_code' => 0, 'data' => null]);
        }
    }


    /**
     * details api
     *
     * @return \Illuminate\Http\Response
     */
    public function getDetails()
    {
        $user = Auth::user();
        return response()->json(['success' => $user], $this->successStatus);
    }

}

11、添加两个监听器

        'Laravel\Passport\Events\AccessTokenCreated' => [
            'App\Listeners\RevokeOldTokens',
        ],

        'Laravel\Passport\Events\RefreshTokenCreated' => [
            'App\Listeners\PruneOldTokens',
        ],
        //执行php artisan event:generate创建监听器

12、在AppListenersRevokeOldTokens的handle中删除失效token:

        DB::table('oauth_access_tokens')
            ->where('id', '<>', $event->tokenId)
            ->where('user_id', $event->userId)
            ->where('client_id', $event->clientId)
            ->delete();

13、构建路由

Route::group([
    'prefix'=>'/v1',
    'middleware' => ['api'],
], function () {
    Route::post('user/login','Api\LoginController@login');
    Route::post('user/register','Api\LoginController@register');
});
Route::group([
    'prefix'=>'/v1',
    'middleware' => ['auth:api'],
    //指定需要传入有效访问令牌的 auth:api 中间件
], function () {
    Route::get('user/logout','Api\LoginController@logout');
    Route::get('user/info','User\IndexController@getInfo');//显示个人信息
});

测试:

1、注册
注册
2、登录
登录
3、获取用户信息
获取用户信息
4、注销
注销

我的个人博客:逐步前行STEP

我把一个字段设默认值为0 需要审核操作 通过设为1 不通过设为2

$states = [
                'on'  => ['value' => 1, 'text' => '通过', 'color' => 'success'],
                'off' => ['value' => 2, 'text' => '不通过', 'color' => 'danger'],
            ];

使用switch控件,不改变状态时显示为通过,但实际提交状态值为0

为了达到默认执行审核通过的效果,需在模型的保存回调中对状态值0进行修改:

public static function boot()
    {
        parent::boot();
        static::saving(function ($model) {
            //修改状态值
            if($model->shelf_status == 0){
                $model->shelf_status = 1;
            }
        });
    }

这样不操作switch,默认提交的状态值为1

项目中有一些图片布局需要按木桶布局排列,而前端工程师是个新手,不会用JS实现,只能在后端处理,直接返回处理好的图片尺寸,达到木桶布局的效果。
木桶布局就是将图片按行、等高排列,并且保证每一行图片排列正好占满,边距相等,效果如下:
这里写图片描述
实现木桶布局的图片尺寸处理主要有以下步骤:
1、设置行高、行宽、边距
2、获取图片高、宽
3、将每个图片高度设置为行高,并等比例缩放图片宽度
4、遍历图片尺寸数组,从第一个图片开始,累计图片宽度,并将图片放入一个数组,当加上第n+1个图片的宽度后,累计宽度与行宽的差大于行高,从第n+1个图片开始重新累计图片宽度,并重新第n+1个开始放入新的数组中,以此获取多个包含着若干图片宽度之和与行宽相近的数组,将它们整成二维数组以便下一步处理。
5、将预处理好的二维数组,再次遍历,先计算图片处理后的宽度之width和与行宽row_width之比ratio,再用行高row_height与该ratio相除,获取等比例width等比例缩小成row_width得到的图片高度height,这个height就是图片实际应该设置的高,接下来按height通过等比例缩放来获取图片实际应该设置的宽度img_width,并更新原数组中的宽度。
6、处理后的数组就差不多是可实现木桶布局的图片尺寸了,但由于之前的计算中,由于可能浮点数运算然后四舍五入导致出现误差,所有还需要矫正一下,累计每一个图片组的宽度之和,计算与行宽的误差over_width,然后通过为每组最后一个图片增减over_width,矫正误差。
上面步骤主要是为了讲解原理,所以分了好几次遍历来进行不同处理,实际代码实现时,可以合并处理步骤。
下面是我写的一个demo源码:

......
//artimages 是图片数组
foreach($artimages as $k=>$artimage){
            if(!empty($artimage['production'])){
                $tmp['url'] = $artimage['url'];
                $tmp['id'] = $artimage['id'];
                list($tmp['w'],$tmp['h'])=getimagesize(storage_path('app').'/'.$artimage['path']);
                array_push($image_arr,$tmp);
            }
        }

        foreach($image_arr as $k=>$image){
            $image_arr[$k]['w'] = intval($image['w'] * (300/number_format($image['h'],2,'.','')));
            $image_arr[$k]['h'] = intval($row_height);
        }

        $result = [];
        $tmp_width = 0;
        $i = 0;
        foreach($image_arr as $k=>$image){
            if($row_width < ($tmp_width + $image['w'] + $space_width)){
                if(abs($row_width - ($tmp_width + $image['w'] + $space_width)) > $row_height){

                    $count = count($result[$i]);//一组图片数量
                    //当前组图片累计的宽度 与 预设行宽 之比
                    $ratio = number_format(($tmp_width-$count*$space_width)/($row_width-($count+1)*$space_width),2,'.','');

                    /*
                     * 调整该组图片应设行高
                     */
                    $tmp_height = intval(300 / $ratio);
                    $width = 0;
                    foreach( $result[$i] as $index => $val){
                        $result[$i][$index]['h'] = $tmp_height;
                        $result[$i][$index]['w'] = intval($val['w'] * ($tmp_height / $val['h']));
                        $width += $result[$i][$index]['w'] + $space_width;
                    }

                    $over_width = $row_width - intval($width + $space_width);//当前行宽误差
                    $result[$i][$index]['w'] += $over_width;//消除误差
                    $tmp_width = 0;
                    $i ++;//接下来的图放入下行
                }
            }
            $result[$i][] = $image;
            $tmp_width += $image['w'] + $space_width;//记录新宽度

        }
        return $result;

1、创建用户:


CREATE USER 'username'@'host' IDENTIFIED BY 'password';

2、程序中使用的mysql账号应该遵循最小权限原则,不允许夸库查询,故设置专门的账号供程序使用:


grant select,update,delete,insert on database_name.* to 'username'@'%' identified by 'passwd' with grant option;

设置对一个数据库的全部权限:
grant all privileges on database_name.* to 'username'@'%' identified by 'passwd' with grant option;    

3、设置完后将权限信息从内存中写入数据库:


flush privileges;

4、取消用户权限:


revoke all on *.* from username;