Vue.js / Laravel - 正确处理注销
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/52021405/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Vue.js / Laravel - Handle logout correctly
提问by oliverbj
I am currently trying to create a simple SPA using Vue and Laravel. I've got the basics to work - users can register and login.
我目前正在尝试使用 Vue 和 Laravel 创建一个简单的 SPA。我已经掌握了工作的基础知识 - 用户可以注册和登录。
I just can't figure out how to create a logout function.
我只是不知道如何创建注销功能。
This is what I currently have:
这是我目前拥有的:
AuthController.php
:
AuthController.php
:
public function logout()
{
$accessToken = auth()->user()->token();
$refreshToken = DB::table('oauth_refresh_tokens')
->where('access_token_id', $accessToken->id)
->update([
'revoked' => true
]);
$accessToken->revoke();
return response()->json(['status' => 200]);
}
routes/api.php
:
routes/api.php
:
Route::middleware('auth:api')->group(function () {
Route::post('/logout', 'API\AuthController@logout');
Route::get('/get-user', 'API\AuthController@getUser');
});
Right now, this is what I have tried to do:
现在,这就是我试图做的:
Layout.vue
:
Layout.vue
:
methods: {
logout() {
axios.post('/api/logout').then(response => {
this.$router.push("/login")
}).catch(error => {
location.reload();
});
}
}
Which calls my logout function in Auth.js
:
其中调用我的注销功能Auth.js
:
logout() {
localStorage.removeItem('token')
localStorage.removeItem('expiration')
}
However, when users click on the logout function, they are not logged out immediately (redirected to the login page) - they can still browse "user only pages".
但是,当用户点击注销功能时,他们并没有立即注销(重定向到登录页面)——他们仍然可以浏览“仅限用户的页面”。
I have to refresh the page before I am properly logged out.
我必须在正确注销之前刷新页面。
Can anyone assist me with this? Is this even the right approach to a "secure" logout function?
任何人都可以帮助我吗?这甚至是“安全”注销功能的正确方法吗?
采纳答案by dziraf
Never used Laravel myself, but you should be able to handle logouts client side without needing to do anything in your backend. At the moment you remove auth token from local storage, so the user loses access to data that requires you to be logged in to get.
我自己从未使用过 Laravel,但您应该能够处理注销客户端,而无需在后端执行任何操作。在您从本地存储中删除身份验证令牌的那一刻,因此用户无法访问需要您登录才能获取的数据。
You probably call your getUser
when you refresh the page and that's why you are only logged out then - you send empty token to your backend server, it can't find a user that's associated to it and returns an empty/default guest object. What's left to do is clear your user state after removing the token in your logout()
function or send a request to your /get-user
endpoint.
您可能会getUser
在刷新页面时调用您的,这就是为什么您当时只是注销 - 您将空令牌发送到后端服务器,它找不到与其关联的用户并返回一个空/默认来宾对象。剩下要做的是在删除logout()
函数中的令牌或向/get-user
端点发送请求后清除您的用户状态。
回答by racl101
For my logout links I'd like to make a request to Laravel to invalidate the current user's (Passport JWT) token.
对于我的注销链接,我想向 Laravel 发出请求,以使当前用户的(Passport JWT)令牌无效。
Here's how I'm doing it:
这是我的做法:
In my backend:
在我的后端:
AuthController.php
AuthController.php
I have a logout method:
我有一个注销方法:
...
public function logout(Request $request) {
$request->user()->token()->revoke();
return response()->json([
'message' => 'Successfully logged out'
]);
}
routes/api.php
routes/api.php
I have a route that can only be accessed by being authenticated.
我有一条只能通过身份验证才能访问的路由。
Route::group(['middleware' => 'auth:api'], function() {
...
Route::get('/logout', 'AuthController@logout');
});
My frontend:
我的前端:
For this I'm using Vue's single file components
为此,我使用 Vue 的单文件组件
App.vue
App.vue
<template>
<nav>
<ul>
...
<li v-if="isLoggedIn">
<a id="logout-link" href="#" @click.prevent="logout">Logout</a>
</li>
</ul>
</nav>
...
</template>
<script>
export default {
...
methods: {
logout(evt) {
if(confirm("Are you sure you want to log out?")) {
axios.get('api/logout').then(response => {
localStorage.removeItem('auth_token');
// remove any other authenticated user data you put in local storage
// Assuming that you set this earlier for subsequent Ajax request at some point like so:
// axios.defaults.headers.common['Authorization'] = 'Bearer ' + auth_token ;
delete axios.defaults.headers.common['Authorization'];
// If using 'vue-router' redirect to login page
this.$router.go('/login');
})
.catch(error => {
// If the api request failed then you still might want to remove
// the same data from localStorage anyways
// perhaps this code should go in a finally method instead of then and catch
// methods to avoid duplication.
localStorage.removeItem('auth_token');
delete axios.defaults.headers.common['Authorization'];
this.$router.go('/login');
});
}
}
}
}
</script>
The point of this approach then is to invalidate the token on the back end upon logging out. Nevertheless, it might not be necessary to do this if the token has short expiration dates.
这种方法的重点是在注销时使后端的令牌无效。然而,如果令牌的到期日期很短,则可能没有必要这样做。
回答by StoeV_No1
That's a bit old, however, I've just started with Laravel/Vue and managed to do this quite simple. Using the integrated auth from Laravel, you could just simulate the logout from app.blade.php like so:
这有点旧,但是,我刚刚开始使用 Laravel/Vue 并设法做到这一点非常简单。使用来自 Laravel 的集成身份验证,您可以像这样模拟从 app.blade.php 注销:
<b-dropdown-item href="#" onclick="event.preventDefault(); document.getElementById('logout-form').submit();">Sign Out</b-dropdown-item> //that's instead of a regular <a> tag
<b-form id="logout-form" action="logout" method="POST" style="display: none;">
<input type="hidden" name="_token" :value="csrf">
</b-form>
You'll need to have the csrf token passed through data in your script in order for it to work like so:
您需要让 csrf 令牌通过脚本中的数据传递,以便它像这样工作:
export default {
data() {
return {
csrf: document.querySelector('meta[name="csrf-token"]').getAttribute('content')
}
},
methods: {
submit : function(){
this.$refs.form.submit();
}
}
}
As well as adding a meta csrf in your head (blade.php file) like so:
以及在您的头脑中添加一个元 csrf(blade.php 文件),如下所示:
<meta name="csrf-token" content="{{ csrf_token()}}">
I'm assuming you'll be using the logout in your navbar .vue file
我假设您将在导航栏 .vue 文件中使用注销
回答by Erubiel
Try redirecting with javascript on a successful logout:
在成功注销时尝试使用 javascript 重定向:
window.location.replace("desiredURL");