Введение. Laravel - это самая быстрорастущая среда PHP, которую используют тысячи разработчиков по всему миру для быстрого создания надежных веб-приложений. Vue, с другой стороны, представляет собой легкую интерфейсную структуру, которую можно использовать для создания сложных одностраничных приложений.

Объединив возможности этих великолепных фреймворков, разработчики могут с легкостью создавать очень мощные приложения. Хорошей новостью является то, что интегрировать vue в laravel легко, поскольку laravel имеет встроенную поддержку vue.

Это руководство проведет вас через процесс предоставления аутентификации для вашего одностраничного приложения vue (SPA), чтобы иметь возможность доступа к конечным точкам API в laravel, требующем аутентификации.

Ресурсы: В этом руководстве были использованы следующие ресурсы.

  • NodeJS 8.9.1
  • Laravel 5.5
  • jwt-auth 0.5.12
  • NPM 5.6.0
  • VueJS 2.5.7
  • Vue-роутер
  • Vue-axios
  • @ websanova / vue-auth

Настройка

  • Создайте проект laravel, выполнив следующую команду на своем терминале.
composer create-project laravel/laravel lara-vue-auth –prefer-dist
  • Перейдите в каталог проекта, выполнив следующую команду на своем терминале.
cd lara-vue-auth
  • Затем вам нужно будет установить зависимости javascript, выполнив следующую команду на своем терминале.
npm install
  • Затем укажите учетные данные своей базы данных в файле .env и создайте базу данных для использования с вашим приложением (если она еще не существует).
  • Затем запустите миграцию базы данных, чтобы создать таблицу users и таблицу password_resets, выполнив следующую команду на своем терминале.
php artisan migrate
  • Установите некоторые библиотеки vue, которые нам понадобятся. Выполните следующую команду на своем терминале.
npm install --save-dev vue-axios vue-router vue-loader vue-template-compiler
  • Создайте файл с именем App.vue в resources / assets / js и поместите в него следующее содержимое.
<template>
    <div class="panel panel-default">
        <div class="panel-heading">
            <nav>
                <ul class="list-inline">
                    <li>
                        <router-link :to="{ name: 'home' }">Home</router-link>
                    </li>
                    <li class="pull-right">
                        <router-link :to="{ name: 'login' }">Login</router-link>
                    </li>                    <li class="pull-right">
                        <router-link :to="{ name: 'register' }">Register</router-link>
                    </li>
                </ul>
            </nav>
        </div>
        <div class="panel-body">
            <router-view></router-view>
        </div>
    </div>
</template>
  • Создайте еще один файл с именем Home.vue, но теперь в resources / assets / js / components и поместите в него следующий код.
<template>
    <h1>Laravel 5 Vue SPA Authentication</h1>
</template>
  • Затем замените содержимое файла resouces / assets / js / app.js приведенным ниже кодом.
import Vue from 'vue';
import VueRouter from 'vue-router';
import App from './App.vue';
import Home from './components/Home.vue';

Vue.use(VueRouter);

const router = new VueRouter({
    routes: [
        {
            path: '/',
            name: 'home',
            component: Home
        },
    ]
});

new Vue({
    el: '#app',
    router: router,
    render: app => app(App)
});
  • Затем замените содержимое файла шаблона resources / views / welcome.blade.php приведенным ниже кодом.
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta name="csrf-token" content="{{ csrf_token() }}">
    <title>Laravel</title>

    <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">

</head>
<body>
    <div class="container">
        <div id="app"></div>
    </div>
    <script src="/js/app.js"></script>
</body>
</html>

Теперь запустите следующую команду на своем терминале.

npm run watch

потом

php artisan serve

Зайдите в свой браузер и посетите http: // localhost: 8000. Если у вас все прошло хорошо, вы сможете увидеть свою домашнюю страницу.

Создание компонентов Vue

Давайте создадим необходимые нам компоненты vue.

Создайте файл с именем Register.vue в каталоге resources / assets / js / components и поместите в него следующий код.

<template>
    <div>
        <div class="alert alert-danger" v-if="error && !success">
            <p>There was an error, unable to complete registration.</p>
        </div>
        <div class="alert alert-success" v-if="success">
            <p>Registration completed. You can now <router-link :to="{name:'login'}">sign in.</router-link></p>
        </div>
        <form autocomplete="off" @submit.prevent="register" v-if="!success" method="post">
            <div class="form-group" v-bind:class="{ 'has-error': error && errors.name }">
                <label for="name">Name</label>
                <input type="text" id="name" class="form-control" v-model="name" required>
                <span class="help-block" v-if="error && errors.name">{{ errors.name }}</span>
            </div>
            <div class="form-group" v-bind:class="{ 'has-error': error && errors.email }">
                <label for="email">E-mail</label>
                <input type="email" id="email" class="form-control" placeholder="[email protected]" v-model="email" required>
                <span class="help-block" v-if="error && errors.email">{{ errors.email }}</span>
            </div>
            <div class="form-group" v-bind:class="{ 'has-error': error && errors.password }">
                <label for="password">Password</label>
                <input type="password" id="password" class="form-control" v-model="password" required>
                <span class="help-block" v-if="error && errors.password">{{ errors.password }}</span>
            </div>
            <button type="submit" class="btn btn-default">Submit</button>
        </form>
    </div>
</template>

Создайте еще один файл с именем Login.vue в том же каталоге и поместите в него следующий код.

<template>
    <div>
        <div class="alert alert-danger" v-if="error">
            <p>There was an error, unable to sign in with those credentials.</p>
        </div>
        <form autocomplete="off" @submit.prevent="login" method="post">
            <div class="form-group">
                <label for="email">E-mail</label>
                <input type="email" id="email" class="form-control" placeholder="[email protected]" v-model="email" required>
            </div>
            <div class="form-group">
                <label for="password">Password</label>
                <input type="password" id="password" class="form-control" v-model="password" required>
            </div>
            <button type="submit" class="btn btn-default">Sign in</button>
        </form>
    </div>
</template>

Также создайте еще один файл с именем Dashboard.vue в том же каталоге и поместите в него следующий код.

<template>
    <h1>Laravel 5 – Our Cool Dashboard</h1>
</template>

Затем замените содержимое файла resources / assets / js / app.js приведенным ниже кодом.

import Vue from 'vue';
import VueRouter from 'vue-router';
import axios from 'axios';
import VueAxios from 'vue-axios';
import App from './App.vue';
import Dashboard from './components/Dashboard.vue';
import Home from './components/Home.vue';
import Register from './components/Register.vue';
import Login from './components/Login.vue';
Vue.use(VueRouter);
Vue.use(VueAxios, axios);
axios.defaults.baseURL = 'http://localhost:8000/api';
const router = new VueRouter({
    routes: [{
        path: '/',
        name: 'home',
        component: Home
    },{
        path: '/register',
        name: 'register',
        component: Register
    },{
        path: '/login',
        name: 'login',
        component: Login
    }]
});

@ websanova / vue-auth

Это библиотека, отвечающая за обработку аутентификации на стороне клиента. Он внедряет объект $ auth, который предоставляет несколько вспомогательных функций, таких как register (), который обрабатывает регистрацию пользователя, login (), который обрабатывает логин пользователя, user (), который обеспечивает доступ к текущим данным пользователя, logout () с ручками выхода из системы, и пара других функций.

Установите @ websanova / vue-auth.

npm install @websanova/vue-auth

Измените app.js, чтобы он выглядел как код ниже.

import Vue from 'vue';
import VueRouter from 'vue-router';
import axios from 'axios';
import VueAxios from 'vue-axios';
import App from './App.vue';
import Dashboard from './components/Dashboard.vue';
import Home from './components/Home.vue';
import Register from './components/Register.vue';
import Login from './components/Login.vue';
Vue.use(VueRouter);
Vue.use(VueAxios, axios);
axios.defaults.baseURL = 'http://localhost:8000/api';
const router = new VueRouter({
    routes: [{
        path: '/',
        name: 'home',
        component: Home
    },{
        path: '/register',
        name: 'register',
        component: Register,
        meta: {
            auth: false
        }
    },{
        path: '/login',
        name: 'login',
        component: Login,
        meta: {
            auth: false
        }
    },{
        path: '/dashboard',
        name: 'dashboard',
        component: Dashboard,
        meta: {
            auth: true
        }
    }]
});
Vue.router = router
Vue.use(require('@websanova/vue-auth'), {
   auth: require('@websanova/vue-auth/drivers/auth/bearer.js'),
   http: require('@websanova/vue-auth/drivers/http/axios.1.x.js'),
   router: require('@websanova/vue-auth/drivers/router/vue-router.2.x.js'),
});
App.router = Vue.router
new Vue(App).$mount('#app');

В приведенный выше код мы включили только что установленную библиотеку и дали ей некоторые настройки для работы.

auth: require(‘@websanova/vue-auth/drivers/auth/bearer.js’)

В приведенной выше строке настраивается vue-auth для использования драйвера носителя, который в основном добавляет токен аутентификации в заголовок нашего запроса во время запросов, а также читает и анализирует токен из ответов нашего сервера.

http: require(‘@websanova/vue-auth/drivers/http/axios.1.x.js’)

Опция выше настраивает vue-auth для использования http-драйвера axios, поскольку мы используем axios для наших http-запросов.

router: require(‘@websanova/vue-auth/drivers/router/vue-router.2.x.js’)

В приведенной выше строке настраивается vue-auth для использования драйвера для vue-router, поскольку это то, что мы используем в нашем приложении.

Мы также добавили в наши маршруты параметр meta.

 ...
meta: {
    auth: true
}
...

Свойство auth указывает, требуется ли авторизация для доступа к маршруту. Итак, мы указали, что для доступа к нашей панели инструментов необходима авторизация; а также указали, что зарегистрированные пользователи не должны иметь доступ к входу в систему и регистрировать маршруты, задав для свойства auth значение false.

Посетите @ websanova / vue-auth, чтобы узнать больше об этой библиотеке.
А теперь беги

npm run watch 

и попробуйте получить доступ к панели управления из вашего браузера. Это должно перенаправить вас на страницу входа.

Jwt-auth

В дальнейшем нам нужно будет установить библиотеку jwt-auth в laravel. Это библиотека, которая обрабатывает аутентификацию через наш api.

Чтобы установить, выполните следующую команду на своем терминале.

composer require tymon/jwt-auth

Затем добавьте службу JWTAuthServceProvider в массив поставщиков и фасад JWTAuth в массив псевдонимов в config / app.php

...
'providers' => [
    ...
    Tymon\JWTAuth\Providers\JWTAuthServiceProvider::class,
]
...
'aliases' => [
    ...
    'JWTAuth' => Tymon\JWTAuth\Facades\JWTAuth::class,
]

Опубликуйте конфигурацию.

php artisan vendor:publish --provider="Tymon\JWTAuth\Providers\JWTAuthServiceProvider"

Сгенерируйте ключ в опубликованной конфигурации

php artisan jwt:generate

Примечание: если эта ошибка приводит к ошибке, проверьте эту ссылку, чтобы исправить ее.

Отредактируйте app / Http / Kernel.php, добавив jwt.auth и jwt.refresh в массив промежуточного программного обеспечения маршрута приложения.

protected $routeMiddleware = [
    ...
    'jwt.auth' => \Tymon\JWTAuth\Middleware\GetUserFromToken::class,
    'jwt.refresh' => \Tymon\JWTAuth\Middleware\RefreshToken::class,
];

Регистрация

Прежде чем мы углубимся в это, давайте создадим контроллер и добавим требуемый маршрут в наш routes / api.php .

Во-первых, давайте создадим контроллер для аутентификации.

php artisan make:controller AuthController

Добавьте маршрут.

Route::post(‘auth/register’, ‘AuthController@register’);

Давайте также создадим FormRequest для обработки проверки для каждого запроса на регистрацию.

php artisan make:request RegisterFormRequest

Давайте отредактируем наш класс RegisterFormRequest, чтобы отразить приведенный ниже код.

...
class RegisterFormRequest extends FormRequest
{
    public function authorize()
    {
         return true;
    }
    public function rules()
    {
        return [
            'name' => 'required|string|unique:users',
            'email' => 'required|email|unique:users',
            'password' => 'required|string|min:6|max:10',
        ];
    }
}

Давайте теперь создадим метод, который будет обрабатывать регистрацию пользователей в нашем AuthController.

public function register(RegisterFormRequest $request)
{
    $user = new User;
    $user->email = $request->email;
    $user->name = $request->name;
    $user->password = bcrypt($request->password);
    $user->save();
    return response([
        'status' => 'success',
        'data' => $user
       ], 200);
 }

Класс RegisterFormRequest обеспечивает соответствие каждого запроса правилам, установленным в его методе rules (). Затем метод register () собирает вводимые пользователем данные из переменной $ request, шифрует пароль пользователя и сохраняет данные пользователя в нашей базе данных.

Теперь давайте перейдем к vue и соединим точки. Перейдите в файл Register.vue и добавьте приведенный ниже код в конец файла.

<script> 
    export default {
        data(){
            return {
                name: '',
                email: '',
                password: '',
                error: false,
                errors: {},
                success: false
            };
        },
        methods: {
            register(){
                var app = this
                this.$auth.register({
                    data: {
                        name: app.name,
                        email: app.email,
                        password: app.password
                    }, 
                    success: function () {
                        app.success = true
                    },
                    error: function (resp) {
                        app.error = true;
                        app.errors = resp.response.data.errors;
                    },
                    redirect: null
                });                
            }
        }
    }
</script>

Теперь попробуем зарегистрировать пользователя. Запустить

npm run watch

Зайдите в свой браузер, заполните форму и нажмите «Зарегистрироваться». Если все прошло хорошо, вы сможете зарегистрировать пользователя.

Авторизация

Вернитесь к AuthController и добавьте метод login ().

public function login(Request $request)
{
    $credentials = $request->only('email', 'password');
    if ( ! $token = JWTAuth::attempt($credentials)) {
            return response([
                'status' => 'error',
                'error' => 'invalid.credentials',
                'msg' => 'Invalid Credentials.'
            ], 400);
    }
    return response([
            'status' => 'success'
        ])
        ->header('Authorization', $token);
}

Также добавьте методы user () и refresh ().

public function user(Request $request)
{
    $user = User::find(Auth::user()->id);
    return response([
            'status' => 'success',
            'data' => $user
        ]);
}
public function refresh()
{
    return response([
            'status' => 'success'
        ]);
}

user () используется для выборки пользовательских данных, а метод refresh () используется для обновления текущего токена при проверке его допустимости.

Добавьте приведенный ниже код в файл routes / api.php.

Route::post('auth/login', 'AuthController@login');
Route::group(['middleware' => 'jwt.auth'], function(){
  Route::get('auth/user', 'AuthController@user');
});
Route::group(['middleware' => 'jwt.refresh'], function(){
  Route::get('auth/refresh', 'AuthController@refresh');
});

Давайте подключимся к vue. Перейдите в свой Login.vue и добавьте в файл следующий код.

<script>
  export default {
    data(){
      return {
        email: null,
        password: null,
        error: false
      }
    },
    methods: {
      login(){
        var app = this
        this.$auth.login({
            params: {
              email: app.email,
              password: app.password
            }, 
            success: function () {},
            error: function () {},
            rememberMe: true,
            redirect: '/dashboard',
            fetchUser: true,
        });       
      },
    }
  } 
</script>

Это должно сработать. На этом этапе вы сможете войти в систему после запуска

npm run watch

Выйти

Вернемся к нашему AuthController, давайте добавим метод logout ().

public function logout()
{
    JWTAuth::invalidate();
    return response([
            'status' => 'success',
            'msg' => 'Logged out Successfully.'
        ], 200);
}

Этот метод гарантирует, что пользователь вышел из серверной части нашего приложения, тем самым аннулируя токен аутентификации, который также очищается со стороны клиента.

Давайте также добавим маршрут в наш routes / api.php.

Route::group(['middleware' => 'jwt.auth'], function(){
   ...
   Route::post('auth/logout', 'AuthController@logout');
});

Давайте изменим наш App.vue.

<template>
    <div class="panel panel-default">
        <div class="panel-heading">
            <nav>
                <ul class="list-inline">
                    <li>
                        <router-link :to="{ name: 'home' }">Home</router-link>
                    </li>
                    <li v-if="!$auth.check()" class="pull-right">
                        <router-link :to="{ name: 'login' }">Login</router-link>
                    </li>
                    <li v-if="!$auth.check()" class="pull-right">
                        <router-link :to="{ name: 'register' }">Register</router-link>
                    </li>
                    <li v-if="$auth.check()" class="pull-right">
                        <a href="#" @click.prevent="$auth.logout()">Logout</a>
                    </li>
                </ul>
            </nav>
        </div>
        <div class="panel-body">
            <router-view></router-view>
        </div>
    </div>
</template>

$ auth.check () используется, если пользователь вошел в систему, а $ auth.logout () выполняет выход пользователя из системы.

Запустить

npm run watch 

и попробуйте. Все должно работать нормально.

Заключение

В этом руководстве мы продемонстрировали, как аутентифицировать запросы api для приложения laravel на основе vue с одной страницей.
Полный исходный код этого руководства можно найти на github.