3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

nuxtjsに認証機能を付ける

Posted at

ログインしたいなーっと思ったのでやってみた。

認証ルート

express-sessionをインストールする

express-sessionのインストール

$ npm install express-session --save

#ストアを作る

認証(login)してユーザ情報をストアに保存する。

store/auth.js
export const state = () => ({
  authUser: null
})

export const mutations = {
  SET_USER(state, authUser) {
    state.authUser = authUser
  }
}

export const actions = {
  async login({ commit }, { username, password }) {
    try {
      const { data } = await this.$axios.post('/auth/login', { username, password })
      commit('auth/SET_USER', data)
    } catch(error) {
      if (error.response && error.response.status === 401) {
        throw new Error(error.response.data.error)
      }
      throw error
    }
  },
  async logout({ commit }) {
    await this.$axios.post('/auth/logout')
    commit('auth/SET_USER', null)
  }
}

セッションに保存しているユーザ情報をストアに保存する。
nuxtServerInitアクション

store/index.js
export const actions = {
  nuxtServerInit({ commit }, { req }) {
    if (req.session && req.session.authUser) {
      commit('auth/SET_USER', req.session.authUser)
    }
  }
}

apiを作る

sessionの設定を記述する。

nuxt.config.js
import bodyParser from 'body-parser'
import session from 'express-session'

export default {
  serverMiddleware: [
    bodyParser.json(),
    session({
      secret: 'super-secret-key',
      resave: false,
      saveUninitialized: true,
      cookie: { maxAge: 60000 }
    }),
    '~/api/auth.js'
  ]
}

ユーザ、パスワードを認証してユーザ情報をセッションに保存する。

api/auth.js
const express = require('express')
const app = express()

app.post('/login', (req, res) => {
  const username = req.body.username
  const password = req.body.password

  if (username === 'demo' && password === 'demo') {
    req.session.authUser = { username }
    return res.json({ username })
  }

  res.status(401).json({ error: '認証失敗' })
})

app.post('/logout', (req, res) => {
  delete req.session.authUser
  res.json({ ok: true })
})

module.exports = {
  path: '/api/auth',
  handler: app
}

middlewareを作る

ストアにユーザ情報が保存されていなければログインページにリダイレクトする。
middlewareプロパティ

middleware/auth.js
export default ({ store, redirect }) => {
  if (!store.state.auth.authUser) {
    return redirect('/login')
  }
}

middlewareプロパティにauthを設定する。

pages/index.vue
<template>
  <div>
    ログイン成功 <button @click="logout">ログアウト</button>
  </div>
</template>

<script>
import { mapActions } from 'vuex'

export default {
  middleware: 'auth'
  methods: {
    ...mapActions('auth', { postLogout: 'logout' }),
    async logout() {
      await this.postLogout()
      this.$router.push('/login')
    }
  }
}
</script>

ログインページを作る

pages/login.vue
<template>
  <div>
    <form @submit.prevent="login" :class="{ error: isError }">
      <input v-model="username" type="text" name="username" placeholder="ユーザ名" />
      <input v-model="password" type="password" name="password" placeholder="パスワード" />
      <button type="submit">ログイン</button>
    </form>
  </div>
</template>

<script>
import { mapActions } from 'vuex'

export default {
  data: () => ({
    username: '',
    password: '',
    isError: false
  }),
  methods: {
    ...mapActions('auth', { postLogin: 'login' }),
    async login() {
      try {
        await this.postLogin({ username: this.username, password: this.password })
        this.isError = false
        this.$router.push('/')
      } catch(e) {
        this.isError = true
      }
    }
  }
}
</script>

<style lang="scss" scoped>
.error {
  input {
    background: salmon;
    border-color: red;
  }
}
</style>

その他

他にも外部認証API(JWT)なるものがあるのか。
後でやってみようかな?気になるし。。。

3
1
7

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?