试着给VuePress添加登录授权支持,基于v-dialogs

背景介绍

VuePress是个不错的能基于Markdown快速构建静态网站的框架,初步来说,对外访问都是透明的。
但是可能因为一些保密需要,有些站点的文档,我们希望控制一下访问,所以我们借着别人的轮子记录下怎么给VuePress实现简单版本的全局登录验证弹窗。

给项目添加弹窗插件

npm i v-dialogs -D

新建Login.vueHelper.js

Login.vue

这是构建一个登录框,基于v-dialogs插件的。

里面有一个简单的表单判断,代码里面预埋了一些username和password,有符合的就放过了,你也可以换成你接口的逻辑。

# .vuepress\login\Login.vue

<template>
  <div class="login-form">
    <div class="form-header">账号</div>
    <div>
      <input type="text" class="form-control" v-model="username">
    </div>
    <div class="form-header">密码</div>
    <div>
      <input type="password" class="form-control" v-model="password">
    </div>

    <div class="btn-row">
      <button class="btn" @click="login">
        登录
      </button>
    </div>
  </div>
</template>

<script>

import { STORAGE_KEY } from './helper'

export default {
  data () {
    return {
      username: '',
      password: ''
    }
  },
  methods: {
    login () 
    {
      if (this.username && this.password) 
      {
        var userAndWords = { 'user1': 'password1', 'user2' : 'password2'}
        var isMatchUser = false
        for(var key in userAndWords)
        {
           var tempUser = key;
           var tempPassword = userAndWords[key]
           if(this.username === tempUser && this.password === tempPassword)
           {
              isMatchUser = true
              break;
           }
        }

        if(isMatchUser)
        {
            const data = JSON.stringify({
              name: this.username,
              time: new Date().getTime()
            })
            window.localStorage.setItem(STORAGE_KEY, data)
            this.$emit('close', true)
        }
        else{
          this.$dlg.alert('抱歉,账号密码不对', {
          messageType: 'warning'
        })
        }
      } 
      else {
        this.$dlg.alert('请输入账号密码', {
          messageType: 'warning'
        })
      }
    }
  }
}
</script>

<style lang="stylus">
.login-form
  padding: 1rem
  display flex
  flex-direction column
  box-sizing border-box
  .btn-row
    margin-top 1rem
  .btn
    padding 0.6rem 2rem
    outline none
    background-color #60C084
    color white
    border 0
  .form-header
    color #666
    margin-bottom 0.5rem
  .form-control
    padding 0.6rem
    border 2px solid #ddd
    width 100%
    margin-bottom 0.5rem
    box-sizing border-box
    outline none
    transition border 0.2s ease
    &:focus
      border 2px solid #aaa
</style>

账号和密码验证通过之后,我们往STORAGE_KEY写入了一个数据,以便后续刷新页面检查之前登录结果,详细判断见下文。

helper.js

这是一个用来判断是否登录验证通过的函数,如果返回true就算是验证通过,返回false那就没验证通过了。

# .vuepress\login\helper.js

export const STORAGE_KEY = 'user_auth_xxxxxxxxxxxx'

// Do user authorization verify
export function checkAuth () 
{
  var auth = JSON.parse(localStorage.getItem(STORAGE_KEY))
  return auth && Object.keys(auth).length
}

这个是判断是否登录过的函数,说直白点,就是上面的登录成功后,会往这个key里面写一个对象值,每次调用页面之前,先走这个函数做一个检查,如果拿出来的auth是你觉得合法的,你就true通过,不然就一直继续弹登录框了。

其实这里,我们也可以根据自己的需要,给拿到的auth对象进一步做判断,当然要怎么搞就看你自己了。比如我会加一个过期时间,一个小时过期:

export function checkAuth () 
{
  var auth = JSON.parse(localStorage.getItem(STORAGE_KEY))
  console.log(auth)
  if(auth && auth.time){
    var preTime = new Date(auth.time)
    var nowTime = new Date().setHours(-1)
    if(nowTime > preTime)
    {
        return false;
    }
    return auth && Object.keys(auth).length
  }
  else
  {
    return false;
  }
}

嵌入新增的文件到VuePress

找到.vuepress下面的enhanceApp.js,如果没有可以新建一个。

import { checkAuth } from './login/helper'
import Login from './login/Login'

export default ({
  Vue,
  options,
  router,
  siteData
}) => {
  Vue.mixin({
    // 请确保只在 beforeMount 或者 mounted 访问浏览器 / DOM 的 API
    mounted() {
      const doCheck = () => {
        if (!checkAuth()) {
          this.$dlg.modal(Login, {
            width: 400,
            height: 350,
            title: '请登录您的账号',
            singletonKey: 'user-login',
            maxButton: false,
            closeButton: false,
            callback: data => {
              if (data === true) {
                // do some stuff after login
              }
            }
          })
        }
      }

      if (this.$dlg) {
        doCheck()
      } else {
        import('v-dialogs').then(resp => {
          Vue.use(resp.default)
          this.$nextTick(() => {
            doCheck()
          })
        })
      }
    }
  })
}

其中Vue.mixin是对全局混入插入,因为v-dialogs插件在注册的过程中需要使用到document这个对象,所以这里一定要在beforeMount或者mounted时间来做。

posted @ 2020-09-08 00:28  TaylorShi  阅读(2463)  评论(0编辑  收藏  举报