Я пытаюсь выяснить, почему мое приложение nuxt не выходит из системы должным образом. Когда я выхожу из системы, нажимая кнопку «Выйти», и я переоцениваю sh страницу, на которой я все еще авторизован.
Мое приложение - это докернизированный django / DRF + nuxt с отдельной настройкой внешнего интерфейса + бэкэнда.
Я искал в журналах и вижу в django Unauthorized: /api/auth/token/destroy/
Я не уверен, почему я вижу эту ошибку. Это проблема с django настройками или кодом внешнего интерфейса?
макеты / по умолчанию. vue
<template>
<div class="mt-2">
<b-navbar toggleable="md" type="dark" variant="info">
<b-navbar-toggle target="nav-collapse"></b-navbar-toggle>
<b-collapse is-nav id="nav-collapse">
<b-navbar-nav>
<b-nav-item to="/">Events</b-nav-item>
<b-nav-item to="/monitor">Monitor</b-nav-item>
<b-nav-item to="/configuration">Configuration</b-nav-item>
<b-nav-item to="/reports">Reports</b-nav-item>
</b-navbar-nav>
<b-navbar-nav class="ml-auto" v-if="$store.state.loggedIn">
<b-nav-text>{{ $store.state.user.username }}</b-nav-text>
<b-nav-item @click="logout()">Logout</b-nav-item>
</b-navbar-nav>
<b-navbar-nav class="ml-auto" v-if="!$store.state.loggedIn">
<b-nav-item to="/login">Login</b-nav-item>
</b-navbar-nav>
</b-collapse>
</b-navbar>
<div class="mt-2">
<nuxt/>
</div>
</div>
</template>
<script>
export default {
methods: {
logout () {
this.$store.dispatch('logout')
this.$router.push('/')
}
}
}
</script>
сервер / аутентификация. js
const axios = require('axios')
const app = require('express')()
const API_URI = process.env.API_URI
app.post('/login/', async (req, res) => {
try {
const result = await axios.post(API_URI + '/auth/token/create/', req.body)
req.session.authToken = result.data.auth_token
await req.session.save()
return res.json({"OK": true})
} catch (e) {
console.log(e)
return res.status(401).json({ error: 'Bad credentials' })
}
})
app.post('/logout/', async (req, res) => {
delete req.session.authToken
await req.session.save()
axios.post(API_URI + '/auth/token/destroy/')
return res.status(200).json({ ok: true })
})
module.exports = {
path: '/auth',
handler: app
}
выход из системы. vue
export default {
state: () => ({
loggedIn: false,
user: null
}),
actions: {
async nuxtServerInit ({ commit }, { req, app }) {
console.log('nuxtServerInit', req.session.authToken)
if (req.session.authToken) {
const data = await app.$axios.$get('/api/auth/me/')
commit('SET_USER', data)
} else {
commit('SET_USER', null)
}
},
async login ({ commit }, creds) {
await this.$axios.$post('/auth/login/', creds)
const data = await this.$axios.$get('/api/auth/me/')
commit('SET_USER', data)
},
logout ({ commit }) {
this.$axios.$post('/auth/logout/')
commit('SET_USER', null)
}
},
mutations: {
SET_USER (state, user) {
if (user) {
state.loggedIn = true
state.user = user
} else {
state.loggedIn = false
state.user = null
}
}
}
}
API. js
const proxy = require('http-proxy-middleware')
const app = require('express')()
// API_URI should end in /api/, and we remove that part in the URL.
app.use(proxy({
target: process.env.API_URI,
prependPath: false,
changeOrigin: true,
auth: false,
logLevel: 'debug',
onProxyReq(proxyReq, req, res) {
if (req.session.authToken) {
proxyReq.setHeader('Authorization', 'Token ' + req.session.authToken)
}
// workaround for bodyParser incompat
// https://stackoverflow.com/questions/25207333/socket-hang-up-error-with-nodejs/25651651#25651651
if (req.body) {
let bodyData = JSON.stringify(req.body)
// in case if content-type is application/x-www-form-urlencoded -> we need to change to application/json
proxyReq.setHeader('Content-Type','application/json')
proxyReq.setHeader('Content-Length', Buffer.byteLength(bodyData))
// stream the content
proxyReq.write(bodyData)
}
},
async onProxyRes(proxyRes, req, res) {
// if the API returns a 401, the token can be considered invalid. Delete the token.
if (proxyRes.statusCode === 401) {
delete req.session.authToken
await req.session.save()
}
}
}))
module.exports = {
path: '/api',
handler: app
}
settings.py
INSTALLED_APPS = [
"django.contrib.admin",
"django.contrib.auth",
"django.contrib.contenttypes",
"django.contrib.sessions",
"django.contrib.messages",
"django.contrib.staticfiles",
"rest_framework",
"rest_framework.authtoken",
"corsheaders",
"djoser",
'django_celery_beat',
'django_celery_results',
"accounts",
]
MIDDLEWARE = [
"django.middleware.security.SecurityMiddleware",
"django.contrib.sessions.middleware.SessionMiddleware",
"corsheaders.middleware.CorsMiddleware",
"django.middleware.common.CommonMiddleware",
"django.middleware.csrf.CsrfViewMiddleware",
"django.contrib.auth.middleware.AuthenticationMiddleware",
"django.contrib.messages.middleware.MessageMiddleware",
"django.middleware.clickjacking.XFrameOptionsMiddleware",
]
REST_FRAMEWORK = {
"DEFAULT_AUTHENTICATION_CLASSES": (
"rest_framework.authentication.BasicAuthentication",
"rest_framework.authentication.SessionAuthentication",
"rest_framework.authentication.TokenAuthentication",
),
"DEFAULT_PAGINATION_CLASS": "rest_framework.pagination.PageNumberPagination",
"PAGE_SIZE": 100,
}