Laravel 护照和 Vue 登录

标签 laravel authentication vue.js oauth-2.0 laravel-passport

我已经使用 passport api 在 laravel 中创建了登录功能,我的状态为 200,问题是我不知道如何登录用户并在成功后重定向到主页请求(我正在使用 vuejs 组件)

代码

Controller

public function login(Request $request)
    {
        $credentials = [
            'email' => $request->email,
            'password' => $request->password
        ];

        if (Auth::attempt($credentials)) {
            // $token = auth()->user()->createToken('AppName')->accessToken;
            // $success['token'] =  $token;
            // $success['name'] =  auth()->user()->name;
            // $success['id'] =  auth()->user()->id;
          $user = Auth::user();
            $success['token'] = $user->createToken('AppName')->accessToken;
            $success['user'] = $user;
            return response()->json(['success'=>$success], 200);
        } else {
            return response()->json(['error' => 'UnAuthorised'], 401);
        }
    }

组件脚本

<script>
    import {login} from '../../helpers/Auth';

    export default {
        name: "login",
        data() {
            return {
                form: {
                    email: '',
                    password: ''
                },
                error: null
            };
        },
        methods: {
            authenticate() {
                this.$store.dispatch('login');

                axios.post('/api/auth/login', this.form)
                .then((response) => {
                    setAuthorization(response.data.access_token);
                    res(response.data);
                })
                .catch((err) =>{
                    rej("Wrong email or password");
                })

            }
        },
        computed: {
            authError() {
                return this.$store.getters.authError;
            }
        }
    }
</script>

Auth.js(在上面的脚本中导入)

import { setAuthorization } from "./general";

export function login(credentials) {
    return new Promise((res, rej) => {
        axios.post('/api/auth/login', credentials)
            .then((response) => {
                setAuthorization(response.data.access_token);
                res(response.data);
            })
            .catch((err) =>{
                rej("Wrong email or password");
            })
    })
}

general.js(在上面的脚本中导入)

export function setAuthorization(token) {
    axios.defaults.headers.common["Authorization"] = `Bearer ${token}`
}

问题

  1. 请求成功后如何登录我的用户?

................................................ ..................................................... ..................................................... …………

最佳答案

假设你已经定义了一个带有登录操作的 vuex auth 模块 接受凭据对象。

如果成功,它会收到一个响应,其中包含我们的 API 授予用户的 access_token。

我们存储/提交 token 并更新 axios 设置以在我们发出的以下每个请求中使用该 token 。

import axios from 'axios';

const state = {
    accessToken: null,
};

const mutations = {
    setAccessToken: (state, value) => {
        state.accessToken = value;
    },
};

const getters = {
    isAuthenticated: (state) => {
        return state.accessToken !== null;
    },
};

const actions = {
    /**
     * Login a user
     * 
     * @param context {Object} 
     * @param credentials {Object} User credentials
     * @param credentials.email {string} User email
     * @param credentials.password {string} User password
     */
    login(context, credentials) {
        return axios.post('/api/login', credentials)
            .then((response) => {
                // retrieve access token
                const { access_token: accessToken } = response.data;

                // commit it
                context.commit('setAccessToken', accessToken);

                return Promise.resolve();
            })
            .catch((error) => Promise.reject(error.response));
    },
};

在向我们的 API 发出每个请求之前,我们需要发送我们收到的 token 并存储在我们的 auth 模块中,因此我们在 main.js 上定义了一个全局 axios 请求拦截器

import store from '@/store';

...

axios.interceptors.request.use(
    (requestConfig) => {
        if (store.getters['auth/isAuthenticated']) {
            requestConfig.headers.Authorization = `Bearer ${store.state.auth.accessToken}`;
        }
        return requestConfig;
    },
    (requestError) => Promise.reject(requestError),
);

...

然后我们定义我们的登录组件,在成功登录时将我们重定向到仪表板页面

<template>
    <div>
        ...
        <form @submit.prevent="submit">
            ...
            <button>Submit</button>
        </form>
        ...
    </div>
</template>

<script>
import { mapActions } from 'vuex';

export default {
    data() {
        return {
            credentials: {
                email: '',
                password: '',
            },
        };
    },
    methods: {
        ...mapActions('auth', [
            'login',
        ]),
        submit() {
            this.login({ ...this.credentials })
                .then(() => {
                    this.$router.replace('/dashboard');
                })
                .catch((errors) => {
                    // Handle Errors
                });
        },
    },
}

最后我们定义我们的路线和他们的守卫

import store from '@/store'

export default new Router({
    mode: 'history',
    routes: [
        {
            path: '/',
            name: 'landing',
            component: Landing,
            // User MUST NOT BE authenticated
            beforeEnter: (to, from, next) => {
                const isAuthenticated = store.getters['auth/isAuthenticated'];

                if (isAuthenticated) {
                    return next({
                        name: 'dashboard',
                    });
                }

                return next();
            },
        },
        {
            path: '/login',
            name: 'login',
            component: Login,
            // User MUST NOT BE authenticated
            beforeEnter: (to, from, next) => {
                const isAuthenticated = store.getters['auth/isAuthenticated'];

                if (isAuthenticated) {
                    return next({
                        name: 'dashboard',
                    });
                }

                return next();
            },
        },
        {
            path: '/dashboard',
            name: 'dashboard',
            component: Dashboard,
            // User MUST BE authenticated
            beforeEnter: (to, from, next) => {
                const isAuthenticated = store.getters['auth/isAuthenticated'];

                if (!isAuthenticated) {
                    return next({
                        name: 'login',
                    });
                }

                return next();
            },
        },
        { path: '*', redirect: '/' },
    ],
});

现在只有拥有访问 token 的用户才能访问仪表板路由以及您将来可能定义的任何子路由。 (不需要进一步检查,因为这条路线的任何 child 都会执行那个守卫)。

如果有人试图在没有访问 token 的情况下访问仪表板路由,将被重定向到登录页面

如果有人尝试使用访问 token 访问登陆或登录页面,将被重定向回仪表板。

现在如果在我们 future 的任何 API 请求中我们的 token 无效会发生什么?

我们在 main.js 上添加了一个全局 axios 响应拦截器,每当我们收到 401 未经授权的响应时,我们都会清除当前 token 并重定向到登录页面

import store from '@/store';

...

axios.interceptors.response.use(
    response => response,
    (error) => {

        if (error.response.status === 401) {
            // Clear token and redirect
            store.commit('auth/setAccessToken', null);
            window.location.replace(`${window.location.origin}/login`);
        }

        return Promise.reject(error);
    },
);

...

最后的话

我相信以上所有步骤足以帮助您更好地了解如何使用访问 token 。当然,您还应该将 token 存储在浏览器的本地存储中,这样用户就不必在页面刷新和 token 从内存中清除时重新登录。并且至少重构路由器 beforeEnter 函数,将它们移动到一个单独的文件中以避免重复。

关于Laravel 护照和 Vue 登录,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51881667/

相关文章:

PHPUnit/Lumen 总是返回 404

casasController.php 第 51 行中的 Laravel 5.2 FatalErrorException

html - 服务器上的身份验证错误

javascript - Vuejs 类型错误 : Cannot use 'in' operator to search for

php - 如何仅在 LIKE 查询 Laravel 中找到整个单词?

Laravel/Sanctum 用户获取问题,使用 auth-next

用于登录的身份验证过滤器和 servlet

ios - 在哪里可以找到有关 iOS 应用程序中安全网络的教程?

vue.js - Vuetify v-data-table 拖放

javascript - 如何获取组件中的列表值?