我已经使用 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}`
}
问题
- 请求成功后如何登录我的用户?
................................................ ..................................................... ..................................................... …………
最佳答案
假设你已经定义了一个带有登录操作的 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/