Laravel护照和Vue登录

时间:2018-08-16 16:32:49

标签: laravel authentication vue.js oauth-2.0 laravel-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);
        }
    }

component script

<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 (imported in script above)

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 (imported in script above)

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

问题

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

............................................... ................................................... ................................................... ........

1 个答案:

答案 0 :(得分:3)

说您已经通过登录操作定义了vuex auth模块 接受凭据对象。

如果成功,它将收到包含我们授予用户的API的access_token的响应。

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

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的每次请求之前,我们需要发送收到的令牌并将其存储在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: '/' },
    ],
});

现在,只有具有访问令牌的用户才能访问仪表板路线以及您将来可能定义的任何子路线。 (无需进一步检查,因为此路线的任何子级都会执行该后卫)。

如果有人尝试在没有访问令牌的情况下访问仪表板路线,则会重定向到登录页面

如果有人尝试使用访问令牌访问登录页面或登录页面,则会被重定向回仪表板。

现在如果在我们将来的任何API上请求我们的令牌无效怎么办?

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

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);
    },
);

...

最后一句话

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