Laravel——Api认证之Passport使用

2,828 阅读2分钟

目前,前后端分离时越来越多了,后端只需要提供一个Api接口解可以了,但是,登录问题怎么解决呢?下面就来介绍如何使用laravel有效解决登录问题。

思路流程

  1. 由于在前端页面,每个用户肯定都有自己单独的模块,所以我们后端需要返回各自用户的数据。
  2. 用户首先进行登录,后台利用Passport官方包,给该用户返回一个access_token(暗号)
  3. 用户获取到access_token(暗号),然后存在本地的localstorage里或者是vuex的state里(前提时用vue的,其他框架同理)。
  4. 然后在用户模块访问后台的时候按要求带上access_token访问。
  5. 后台就可以根据access_token查到对应的用户,查出数据,返回给前端。

安装

  • 使用composer安装Passport:
composer require laravel/passport
  • 接下来,将 Passport 的服务提供者注册到配置文件 config/app.php 的 providers 数组中:
Laravel\Passport\PassportServiceProvider::class,
  • 而Passport服务时官方包,有自带的数据库迁移目录,所以直接可以用命令执行迁移来自动创建存储各种信息的数据表
php artisan migrate
  • 然后创建密码授权客户端
php artisan passport:client --password
# 创建了client_id和client_secret,前端登录验证的时候必须把这两个玩意带着哟
  • 创建了密码授权客户端就可以按以下要求获取access_token了。以vue+axios举例

(这里为了防止不太会axios的小伙伴,在main.js进行配置一下。)

import axios from 'axios'
Vue.prototype.axios = axios
//安装好axios包之后,在根目录的main.js里添加上面的两行代码,注意放到引入Vue的下面。

你肯定会问传到后台的data client_idclient_secret是什么? 说简单点,其实就是表示你前端要用到这个passport来验证的一个暗号。

  • 这个时候你就需要打以下命令获取这两玩意。
php artisan passport:keys
# 获取到了,然后记住这两个东西,没有记住,也可以在数据库里的oauth_clients表里去看哟

以上需要跑的命令基本就跑完了 , 接下来就时配置方面的了。

配置

  • 首先, 得让安装的Passport服务在认证服务提供AuthServiceProviderboot方法中调用Passport::routes函数。如果令牌需要有效期和刷新时间看下图:
 public function boot()
    {
        $this->registerPolicies();  //注册

        Passport::routes(); //认证的路由
        Passport::tokensExpireIn(Carbon::now()->addHours(3));   //令牌有效期3小时
        Passport::refreshTokensExpireIn(Carbon::now()->addDays(30));    //令牌刷新时间30
    }

如果觉得时间过长或者过短,您还可以使用addMinutes()或者时addMonths()都可以的。

  • 最后,将配置文件 config/auth.php中授权看守器 guardsapidriver 选项改为 passport。此调整会让你的应用程序在在验证传入的 API 的请求时使用 Passport 的 TokenGuard 来处理:
'guards' => [
    'web' => [
        'driver' => 'session',
        'provider' => 'users',
    ],

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

设置中间件和路由

  • 首先需要在 app/Http/Kernel.php$routeMiddleware 变量中添加新的中间件:
protected $routeMiddleware = [
    'client.credentials' => \Laravel\Passport\Http\Middleware\CheckClientCredentials::class,
];
  • 然后在需要的模块路由routes/api.php前面加上这个中间件。
//用户
 Route::get('/customer', 'customerController@index')->middleware('client.credentials');

前端的登录测试

后端已经基本都配置好了,那么再就需要前端进行登录按要求发送请求给后端了。

    //前面已经说了,我们会用到client_id和client_secret这个时候就要派上用场了哟。
    //请看以下html的代码
    <template>   
    <input type="email" v-model="userInfo.email" placeholder="请输入邮箱">
     <input type="password" v-model="userInfo.password" placeholder="请输入密码">
    <button @click.prevent="submit">登 录</button>
    </template>  
    
    //请看vue里的代码
    <script>
    export default {
        data() {
            return {
                userInfo: {
                    email: '',
                    password: ''
                }
            }
        },
        methods: {
            submit() {
                //将数据配置好
                const data = {
                    grant_type: 'password', //oauth的模式
                    client_id: 1,   //上面所说的client_id
                    client_secret: '5wq3G7wv0ZuK7Qj6aFtwZaX6XyfLLa8hLSDDJyAB',//同上
                    username: this.userInfo.email,
                    password: this.userInfo.password,
                }
                this.axios.post('http://your domain/oauth/token', data)
                    .then(res => {
                        if(res.status == 200) { //如果成功了
                           //将收到的token_type和access_token存到localStorage里
                            localStorage.token_type = res.data.token_type
                            localStorage.token_token = res.data.access_token
                            //登录成功跳转到你想跳转的地址
                            ...
                            }
                    })
            }
        }
    }
    </script>

通过这样的请求,只要后端配置好了,基本就能收到以下的json

当然从我们上面的代码可以看出,我们也已经将重要的东西access_tokentoken_type存了起来啦。

axios的配置

终于把令牌access_token和令牌类型token_type拿到手了。那么后面,我们前端只要涉及到api认证的请求(我们这里拿个人中心做例子)就应该把这两个玩意带着发送给后端,这样后端就可以分辨是哪个用户的请求了,也就可以返回相应的信息了。

好了,这个时候就需要配置一下axios了哟,把以后的请求都带上这两玩意就是了,简单、舒服。请看以下的配置,我们这里单独创建一个http.js重新配置了axios。

//#创建http.js文件
import axios from 'axios'
import router from '@/router'

// axios 配置
axios.defaults.timeout = 5000;
// axios.defaults.baseURL = 'https://api.github.com';

// http request 拦截器
axios.interceptors.request.use(
    config => { //将所有的axios的header里加上token_type和access_token
        config.headers.Authorization = `${localStorage.token_type} ${localStorage.access_token}`;
        return config;
    },
    err => {
        return Promise.reject(err);
    });

// http response 拦截器
axios.interceptors.response.use(
    response => {
        return response;
    },
    error => {
        // 401 清除token信息并跳转到登录页面
        if (error.response.status == 401) {
            alert('登录信息已失效,请重新登录')
            router.replace({    //如果失败,跳转到登录页面
                name: 'login'
            })
        }
        return Promise.reject(error.response.data)
    });

export default axios;       //然后再次export出去,嘿嘿 main.js那里就得改改咯
//#main.js文件
//将原来上面配置的  import axios from 'axios'
//改成
import axios from './http'  //这里我的http.js是和main.js同一目录。

个人用户页面测试

都配置好啦,接下来,拿用户中心页面来获取用户的信息了。

<script>
    export default {
        data() {
            return {
                user[]
            }
        },
        created() {
            this.getUser()
        },
        methods: {
            getUser() {
                this.axios.get('http://your domain/api/customer')
                    .then(res => {
                        console.log(res)
                        this.user = res.data    //将得到的用户信息,传给user。
                    })
            }
        }
    }
</script>

哇,终于获取到登录的那个用户的用户信息了哟。不过......

后台怎么解析token拿到用户信息。

还有最后的一个问题, 后台根据怎么根据前端发送的access_token来查询到用户信息发送给前端呢。

打开你的User模型User.php,通常放在Http目录下。 在文件里的上面加上use Laravel\Passport\HasApiTokens;然后User类里,也别忘了加上 use Notifiable,HasApiTokens;这个就是用来根据token来获取user信息的。

#CustomerController@index方法里。
    $user = auth('api')->user();
    return $user;       //成功将用户信息返回给前端啦。

就这样完美结束啦。欢迎吐槽~