maf*_*tis 0 authentication oauth-2.0 laravel vue.js laravel-passport
我已经在laravel中使用passport api进行了登录功能,并且状态为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);
}
}
Run Code Online (Sandbox Code Playgroud)
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>
Run Code Online (Sandbox Code Playgroud)
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");
})
})
}
Run Code Online (Sandbox Code Playgroud)
general.js (imported in script above)
export function setAuthorization(token) {
axios.defaults.headers.common["Authorization"] = `Bearer ${token}`
}
Run Code Online (Sandbox Code Playgroud)
................................................... ................................................... ................................................... .....
假设您已经通过接受凭证对象的登录操作定义了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));
},
};
Run Code Online (Sandbox Code Playgroud)
在对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),
);
...
Run Code Online (Sandbox Code Playgroud)
然后,我们定义登录组件,成功登录后会将其重定向到仪表板页面
<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
});
},
},
}
Run Code Online (Sandbox Code Playgroud)
最后,我们定义路线及其守卫
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: '/' },
],
});
Run Code Online (Sandbox Code Playgroud)
现在,只有具有访问令牌的用户才能访问仪表板路线以及您将来可能定义的任何子路线。(无需进一步检查,因为此路线的任何子级都会执行该后卫)。
如果有人尝试在没有访问令牌的情况下访问仪表板路线,则会重定向到登录页面
如果有人尝试使用访问令牌访问登录页面或登录页面,则会将其重定向回仪表板。
现在,如果在我们将来的任何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);
},
);
...
Run Code Online (Sandbox Code Playgroud)
我相信上述所有步骤都足以帮助您更好地了解如何使用访问令牌。当然,您还应该将令牌存储在浏览器的localStorage上,这样用户在遇到页面刷新和令牌从内存中清除时就不必登录。并且至少通过将路由器的EnterEnter函数移动到单独的文件中来重构它们,以避免重复。
| 归档时间: |
|
| 查看次数: |
4304 次 |
| 最近记录: |