前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Laravel Vue 前后端分离 使用token认证

Laravel Vue 前后端分离 使用token认证

作者头像
mafeifan
发布2018-09-10 12:01:37
4K0
发布2018-09-10 12:01:37
举报
文章被收录于专栏:finleyMafinleyMa

在做前后台分离的项目中,认证是必须的,由于http是无状态的。前台用户登录成功后,后台给前台返回token。之后前台给后台发请求每次携带token。

原理也非常简单:

  1. 前天在请求头中添加 Authorization,如下

image.png

  1. 后台取到值,然后去用户表的api_token列进行匹配,如果查到说明验证成功,并且返回相关信息。

Laravel本身自带几种验证方式,下面介绍下token认证的实现的方法。

前台在向后台发起请求时要携带一个token

后台需要做一个返回当前登录用户的信息的api,地址是 /api/user

  1. 先添加路由,当给 route/api.php 添加
代码语言:javascript
复制
Route::middleware('auth:api')->get('/user', function (Request $request) {
    echo $request->user();
});

如果浏览器直接访问 http://mydomain.com/api/user 会返回 401 Unauthorized 原因是在config/auth.php中有下面的关键配置

代码语言:javascript
复制
    'guards' => [
        'web' => [
            'driver' => 'session',
            'provider' => 'users',
        ],

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

可以看到通过api访问走的是token认证,这里没有提供token所以就认证失败返回401了。

  1. 'driver' => 'token' 实际调用的是\vendor\laravel\framework\src\Illuminate\Auth\TokenGuard.php 上面说到我们需要在request里提供api_token参数,为了区别是哪个用户,需要在user表添加api_token字段

image.png

  1. 认证过程调用的是getTokenForRequest方法
代码语言:javascript
复制
    public function getTokenForRequest()
    {
        $token = $this->request->query($this->inputKey);

        if (empty($token)) {
            $token = $this->request->input($this->inputKey);
        }

        if (empty($token)) {
            $token = $this->request->bearerToken();
        }

        if (empty($token)) {
            $token = $this->request->getPassword();
        }

        return $token;
    }

这个bearerToken实际找header中是否存在Authorization

代码语言:javascript
复制
    public function bearerToken()
    {
        $header = $this->header('Authorization', '');

        if (Str::startsWith($header, 'Bearer ')) {
            return Str::substr($header, 7);
        }
    }
  1. 先给user表添加api_token字段 php artisan make:migration add_api_token_to_users --table=users 内容
代码语言:javascript
复制
class AddApiTokenToUsers extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::table('users', function (Blueprint $table) {
            $table->string('api_token', 60)->unique();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::table('users', function (Blueprint $table) {
            $table->dropColumn('api_token');
        });
    }
}
  1. 打开navicat进到user表里,更新users的api_token。

image.png

  1. 打开postman

image.png 注意这里的header,key是Authorization,值就是Bearer+空格+刚才数据库里设的api_token

这样就能返回内容啦,修改其他用户的token能返回相应的用户信息,说明认证成功,功能基本完成! 下面完善细节

  1. 完善逻辑 修改 \app\Http\Controllers\Auth\RegisterController.php
代码语言:javascript
复制
    protected function create(array $data)
    {
        return User::create([
            'name' => $data['name'],
            'email' => $data['email'],
            'password' => bcrypt($data['password']),
            // 添加这行
            'api_token' => str_random(60),
        ]);
    }

User Model 的 $fillable也改下

代码语言:javascript
复制
    protected $fillable = [
        'name', 'email', 'password', 'api_token',
    ];
  1. 如果在前台页面,发起请求时如何给后台传这个Authorization header? 方法如下 注意,下面的是Laravel5.4的修改方法。新版本可能有细微区别,只要知道原理就能自己改了。

打开 \resources\assets\js\bootstrap.js 参照着csrf-token。合适的地方添加下面的代码

代码语言:javascript
复制
let token     = document.head.querySelector('meta[name="csrf-token"]');
let api_token = document.head.querySelector('meta[name="api-token"]');

if (token) {
    // 这个要参考axios的文档
    window.axios.defaults.headers.common['X-CSRF-TOKEN'] = Laravel.csrfToken =token.content;
    // 如果用的jquery
    // Fix jquery ajax crossDomain without Token
    // jQuery.ajaxPrefilter(function (options, originalOptions, jqXHR) {
    //     // if (options.crossDomain) {
    //     jqXHR.setRequestHeader('Authorization', api_token.content);
    //     jqXHR.setRequestHeader('X-CSRF-TOKEN', token.content);
    //     //}
    // });
} else {
    console.error('CSRF token not found: https://laravel.com/docs/csrf#csrf-x-csrf-token');
}


if (api_token) {
    window.axios.defaults.headers.common['Authorization'] = api_token.content;
} else {
    console.error('Authorization token not found: https://laravel.com/docs/csrf#csrf-x-csrf-token');
}

最后修改公共视图模版中 \views\layouts\app.blade.php

代码语言:javascript
复制
    <meta name="csrf-token" content="{{ csrf_token() }}">
    <meta name="api-token" content="{{ Auth::check() ? 'Bearer '.Auth::user()->api_token : 'Bearer ' }}">

总结: 本质上给用户表添加api_token,后台根据这个字段判断是否是有效的用户,无效返回401,有效返回查询结果。 优点是容易理解,缺点太简单,安全也不够。 为了安全,可以实现下面的功能:

  1. 每次登录成功后刷新api_token为新值 其实 Laravel 官方提供了一个 Laravel Passport 的包。Laravel Passport is an OAuth2 server and API authentication package 。 具体使用请等更新。

问题: 如何修改默认的api_token列?

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2018.01.19 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档