Auth in nuxtjs
Bài đăng này đã không được cập nhật trong 3 năm
Hôm trước mình có chia sẽ bài viết về JWT trong django, hôm nay mình sẽ hướng dẫn xử dụng api này để login bằng nuxtjs
Cài đặt
Giả sử các bạn đã cài sẵn nuxtjs, bây giờ chúng ta đi cài đặt những packages cần thiết Thêm vào file package.json:
"@nuxtjs/auth": "^4.8.1",
"@nuxtjs/axios": "^5.0.0",
Ở đây mình sử dụng 2 gói có sẵn của nuxtjs là
auth
vàaxios
sau khi thêm vào các bạn chạy npm install
để down load thư viện mới về:
Trong file nuxt.config.js
config như sau:
...
modules: [
// Doc: https://github.com/nuxt-community/axios-module#usage
'@nuxtjs/axios',
// Doc: https://github.com/bootstrap-vue/bootstrap-vue
'bootstrap-vue/nuxt',
'@nuxtjs/dotenv',
'@nuxtjs/auth',
],
/*
** Axios module configuration
*/
axios: {
baseURL: process.env.API_URL || ' http://localhost:8000/api/',
debug: process.env.DEBUG || false,
proxyHeaders: false,
credentials: false,
},
auth: {
strategies: {
local: {
endpoints: {
login: {
url: 'accounts/token/',
method: 'post',
propertyName: 'access',
},
user: {
url: 'accounts/me/',
method: 'get',
propertyName: 'users'
},
tokenRequired: true,
logout: false
}
},
watchLoggedIn: true,
redirect: {
login: '/login',
logout: '/',
callback: '/login',
home: '/'
}
}
},
...
mình giải thích một chút:
đầu tiên là config của
axios
, chỗ này cần config cáibase url
, tất cả request sẽ nhận base này, ko cần phải gọifull url
đến một api nữa.
auth
thì cân có 2 api làget access token
vàapi me
, sau khi login module này sẽ tự động gọi api me để lấy thông tin người dùng về (để hiển thì tên user đã login chẳng hạn).
Code thôi
Login
Tạo một file Notification.vue
trong thư mục components
có nội dung như sau:
<template>
<div class="notification is-danger bg-danger">
{{ message }}
</div>
</template>
<style>
.notification {
padding: 11px;
margin: 10px 0px;
}
</style>
<script>
export default {
name: 'Notification',
props: ['message']
}
</script>
file này đơn giản chỉ là thông báo ra khi có lỗi mà thôi
Tạo một file login.vue
trong thư mục pages
có nội dung như sau:
<template>
<div class="app flex-row align-items-center">
<div class="container">
<b-row class="justify-content-center login">
<b-col md="6">
<b-card-group>
<b-card no-body class="p-4">
<b-card-body>
<h1>Login</h1>
<Notification :message="error" v-if="error"/>
<p class="text-muted">Sign In to your account</p>
<b-input-group class="mb-3">
<b-input-group-prepend>
<b-input-group-text><i class="icon-user"></i></b-input-group-text>
</b-input-group-prepend>
<input type="text" class=" form-control" v-model="username"
placeholder="username">
</b-input-group>
<b-input-group class="mb-4">
<b-input-group-prepend>
<b-input-group-text><i class="icon-lock"></i></b-input-group-text>
</b-input-group-prepend>
<input type="password" class="form-control" v-model="password" placeholder="Password">
</b-input-group>
<b-row>
<b-col cols="6">
<b-button variant="primary" class="px-4" @click="login">Login</b-button>
</b-col>
</b-row>
</b-card-body>
</b-card>
</b-card-group>
</b-col>
</b-row>
</div>
</div>
</template>
<script>
import Notification from '~/components/Notification'
export default {
name: 'Login',
layout: 'clean',
components: {
Notification,
},
data() {
return {
username: '',
password: '',
error: null
}
},
methods: {
async login() {
try {
const response = await this.$axios.post('accounts/token/', {
username: this.username,
password: this.password
});
await this.$auth.setToken('local', "Bearer " + response.data.access);
await this.$auth.setRefreshToken('local', response.data.refresh);
await this.$auth.setUserToken(response.data.access);
} catch (e) {
this.error = 'Username or Password not valid'
}
}
}
}
</script>
Mình có sử dụng
bootstrap-vue
nên cứ pháp html có hơi khác form bình thường một chút. các bạn có thể xem thêm về package này, hoặc bỏ đi viết luôn code html thuần vào cũng được.
File login này có 1 form login, chắc ai cũng biết cái này rồi mình sẽ không nói lại nữa.
ở đây mình có custon lại phương thức login mặc định của module auth
một chút, vì auth
hiện tại không hỗ trợ refresh token
.
đến đây chúng ta đã xong phần login rồi, login xong nó sẽ redirect về trang /
của project, bạn có thể thay đổi trong file nuxt.config.js
phần redirect
.
Lấy thông tin users
Tạo một file là index.js
trong phần store để lấy thông tin của users khi đã login thành công:
export const getters = {
isAuthenticated(state) {
return state.auth.loggedIn
},
loggedInUser(state) {
return state.auth.user
}
};
Trong file header của vue:
<template>
<b-nav-item-dropdown right no-caret>
<template slot="button-content">
<img src="~static/img/avatars/6.jpg" class="img-avatar" alt="">
<span class="hidden-sm hidden-xs">{{ loggedInUser.username }}</span>
</template>
<b-dropdown-header tag="div" class="text-center"><strong>Account</strong></b-dropdown-header>
<b-dropdown-item @click="logout"><i class="fa fa-lock"></i>Logout</b-dropdown-item>
</b-nav-item-dropdown>
</template>
<script>
import {mapGetters} from 'vuex'
export default {
name: 'header-dropdown',
computed: {
...mapGetters(['loggedInUser'])
},
methods: {
async logout() {
await this.$auth.logout();
this.$router.push('/login');
},
},
}
</script>
Tạm thời các bạn chỉ cần quan tâm đến phần js thôi, cái bên trên là code html, có thể thay đổi theo ý muốn của mọi người.
Khi users đã login xong thì chúng ta có thể lấy thông tin users qua biến loggedInUser
Refresh token
Tiếp theo đến phần refresh token, Tạo một file axios.js
trong thư mục plugins
có nội dung như sau:
export default function ({$axios, app}) {
$axios.onError(error => {
const statusCode = error.response.status;
// refresh token if it expired
if (statusCode === 403) {
const originalRequest = error.config;
if (!originalRequest._retry) {
originalRequest._retry = true;
return $axios.post('accounts/refresh-token/', {'refresh': app.$auth.getRefreshToken('local')})
.then((response) => {
originalRequest.headers['Authorization'] = 'Bearer ' + response.data.access;
app.$auth.setToken('local', "Bearer " + response.data.access);
return $axios(originalRequest);
});
}
}
return Promise.reject(error);
});
}
Trong file nuxt.config.js
thêm vào nội dung sau:
/*
** Plugins to load before mounting the App
*/
plugins: [
....
'~plugins/axios',
....
],
Vậy là xong rồi, khi token hết hạn nó sẽ tự động gọi lại để lấy lại token mới.
Tham khảo
All rights reserved