1. 在后端编写JWTUtils.java
public class JWTUtils {

    // 注意:在真正的开发中SING是很复杂的,这里只做演示
    private static final String SING = "ADSD#$F";

    /*
     * 生成Token
     */
    public static String generateToken(Map<String, String> withClaims) {
        // 创建Map集合
        HashMap<String, Object> map = new HashMap<>();
        // 创建日历
        Calendar instance = Calendar.getInstance();
        // 设置过期时间(这里设置1小时过期测试)
        instance.add(Calendar.SECOND, 60 * 60);
        // 创建JWT
        JWTCreator.Builder builder = JWT.create();
        // 添加存放信息
        withClaims.forEach(builder::withClaim);
        // 指定令牌过期时间
        String token = builder.withExpiresAt(instance.getTime())
        // 设置签名(指定密钥方式)
                .sign(Algorithm.HMAC256(SING)); 
        return token;
    }

    /*
     * 验证Token
     */
    public static DecodedJWT verifyToken(String token) {
        DecodedJWT verify = JWT.require(Algorithm.HMAC256(SING)).build().verify(token);
        return verify;
    }

    /*
     * 获取当前Token
     */
    public static String getCurrentToken() {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        String token = request.getHeader("token");
        return token;
    }
   
}
  1. axios.js作如下配置
'use strict'

import Vue from 'vue'
import axios from 'axios'

const config = {
  // baseURL: 'http://localhost:8081/reagent',
  // timeout: 60 * 1000,
  // withCredentials: true,
  // changeOrigin: true
}
/*====================重点开始=========================*/
const _axios = axios.create(config)

//异步请求前在header里加入token
_axios.interceptors.request.use(
  config => {
    // 判断是否存在token,如果存在的话,则每个http header都加上token
    let token = sessionStorage.getItem('token')
    if (!config.headers.hasOwnProperty('token') && token) {
      config.headers.token = token
    }
    return config
  },
  function (error) {
    // 对请求错误做些什么
    return Promise.reject(error)
  }
)

//异步请求后,判断token是否过期
_axios.interceptors.response.use(
  response => {
    if (response.data.status === 403) {
      this.$message.error(Response.data.message)
      sessionStorage.removeItem('token')
      this.$router.push('/login')
    } else {
      return response
    }
  },
  error => {
    return Promise.reject(error)
  }
)
/*====================重点结束=========================*/

Plugin.install = function (Vue, options) {
  Vue.axios = _axios
  window.axios = _axios
  Object.defineProperties(Vue.prototype, {
    axios: {
      get () {
        return _axios
      }
    },
    $axios: {
      get () {
        return _axios
      }
    }
  })
}

Vue.use(Plugin)

export default Plugin

  1. 对store作如下配置(这里是index.js)
import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
  state: {
    // 存储token
    token: sessionStorage.getItem('token') ? sessionStorage.getItem('token') : ''
  },
  mutations: {
    // 设置token,并将token存入localStorage
    setToken (state, user) {
      state.token = user.token
      sessionStorage.setItem('token', user.token)
    },
    //清除token,并将token存入localStorage
    delToken (state) {
      state.token = ''
      sessionStorage.removeItem('token')
    }
  },
  actions: {},
  modules: {}
})
  1. 配置路由导航守卫
import Vue from 'vue'
import VueRouter from 'vue-router'

Vue.use(VueRouter)

const routes = [
  {
    path: '/',
    redirect: '/index'
  },
  {
    path: '/index',
    name: 'index',
    component: () => import('@/views/index')
  },
  {
    path: '/login',
    name: 'login',
    component: () => import('@/views/login')
  }
]

const router = new VueRouter({
  routes
})
const originalPush = VueRouter.prototype.push
VueRouter.prototype.push = function push (location) {
  return originalPush.call(this, location).catch(err => err)
}

// 挂载路由导航守卫
router.beforeEach((to, from, next) => {
// 如果是登录页则放行
  if (to.path === '/login') return next()
  // 查看token是否存在
  const token = sessionStorage.getItem('token')
  if (!token) return next('/login')
  next()
})

export default router

  1. 将后台传过来的token设置到sessionStorage中并保存到Header
<template>
  <div>
    <!--头部信息-->
    <el-row class="header" type="flex">
      <el-col :span="12" :offset="3">
        <el-link href="#/index" :underline="false" icon="el-icon-house">首页</el-link>
      </el-col>
      <!--if-->
      <el-col :span="12" :offset="14" v-if="indexData.userToken===''">
        <el-link href="#/login" :underline="false">登录</el-link>
        |
        <el-link href="#/sign" :underline="false">注册</el-link>
      </el-col>
      <!--else-->
      <el-col :span="12" :offset="14" v-else>
        <el-dropdown>
          <span class="el-dropdown-link">
            {{ indexData.userToken.username }}
            <i class="el-icon-arrow-down el-icon--right"></i>
          </span>
          <el-dropdown-menu slot="dropdown">
            <el-dropdown-item>修改密码</el-dropdown-item>
            <el-dropdown-item v-if="indexData.userToken.rid==='1'">
              <el-link href="#/admin" :underline="false">后台管理</el-link>
            </el-dropdown-item>
            <el-dropdown-item v-if="indexData.userToken.rid==='2'">
              <el-link href="#/admin" :underline="false">店铺管理</el-link>
            </el-dropdown-item>
            <el-dropdown-item v-if="indexData.userToken.rid==='3'">
              <el-link @click="shop.shopDialog=true" :underline="false">商家入驻</el-link>
            </el-dropdown-item>
            <el-dropdown-item>
              <el-link @click="loginOutBox" :underline="false">退出登录</el-link>
            </el-dropdown-item>
          </el-dropdown-menu>
        </el-dropdown>
      </el-col>
    </el-row>
    <!--Logo与搜索-->
    <el-row class="header_container" type="flex">
      <el-col :span="12" :offset="1">
        <a href="#/index" title="试剂耗材采购管理平台">
          <el-image class="image" :src="indexData.logoUrl"></el-image>
        </a>
      </el-col>
      <el-col :span="12" :offset="9">
        <el-input v-show="false"
                  type="text"
                  style="width: 300px"
                  prefix-icon="el-icon-search"
                  placeholder="请输入商家名称"
                  v-model="indexData.searchInfo"></el-input>
        <el-button v-show="false" type="success" @click="searchEvent">查询</el-button>
      </el-col>
    </el-row>
    <hr>
    <!--主体内容-->
    <div class="login_container">
      <div class="images">
        <el-image :src="backimage" fit="none"></el-image>
      </div>
      <div class="login_box">
        <div class="title">
          试剂采购平台登录
        </div>
        <div class="login_form">
          <el-form :model="loginForm" status-icon>
            <el-form-item class="login_item">
              <el-input type="text"
                        prefix-icon="el-icon-user"
                        placeholder="用户名"
                        v-model="loginForm.username"></el-input>
            </el-form-item>
            <el-form-item>
              <el-input type="password"
                        prefix-icon="el-icon-lock"
                        placeholder="密码"
                        v-model="loginForm.password"
                        show-password></el-input>
            </el-form-item>
          </el-form>
          <el-button class="login_bth"
                     type="success"
                     @click="logincheck">立即登录
          </el-button>
          <div class="login_sgin">
          <span class="login_text">还没有账户?
            <el-link class="login_link" type="primary" href="#/sign">
              立即注册
            </el-link>
          </span>
          </div>
        </div>
      </div>
    </div>
    <!--页脚-->
    <div class="footer">
      <div class="footer_text">
        <el-link>关于我们</el-link>
        |
        <el-link>合作伙伴</el-link>
        |
        <el-link>广告服务</el-link>
        |
        <el-link>广告服务</el-link>
        |
        <el-link>联系我们</el-link>
        |
        <el-link>法律声明</el-link>
      </div>
      <div class="footer_banquan">
        © 2020-现在 Reagent.com 版权所有
      </div>
    </div>
  </div>
</template>

<script>
import backimage from '@/assets/images/logo/logo2.png'
import logo from '@/assets/images/logo/logo1.png'

export default {
  name: 'login',
  data () {
    return {
      //主页数据
      indexData: {
        logoUrl: logo,
        isLogin: true,
        userToken: ''
      },
      //中心背景图片
      backimage: backimage,
      //登录表单
      loginForm: {
        username: '',
        password: ''
      }
    }
  },
  created () {
    this.getToken()
  },
  methods: {
    /*公共*/
    // 获取Token
    async getToken () {
      if (sessionStorage.getItem('token') !== '') {
        const { data: res } = await axios.get('/getToken')
        this.indexData.userToken = res.data
      } else {
        return false
      }
    },
    // 退出登录
    loginOutBox () {
      this.$confirm('确定退出登录吗?', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        this.$store.commit('delToken')
        this.indexData.userToken = ''
        this.$message.success('退出成功!')
        this.$router.push('/index')
      }).catch(() => {
        return false
      })
    },
    /*非公共*/
    // 登录处理
    logincheck () {
      var _this = this
      if (this.loginForm.username === '') {
        this.$message({
          type: 'warning',
          message: '用户名不能为空!',
          duration: 1000
        })
        return false
      } else if (this.loginForm.password === '') {
        this.$message({
          type: 'warning',
          message: '密码不能为空!',
          duration: 1000
        })
        return false
      }
      axios.post('/logincheck', {
        username: this.loginForm.username,
        password: this.loginForm.password
      }).then(response => {
        if (response.data.status === 200) {
          this.$message.success(response.data.message)
          // 重点语句(设置token)
          this.$store.commit('setToken', { token: response.data.data })
          this.$router.push('/index')
        } else {
          this.$message.error(response.data.message)
          this.loginForm.username = ''
          this.loginForm.password = ''
        }
      }).catch(error => {
        this.$message.error('服务器未连接')
      })
    }
  }
}
</script>

<style scoped>
@import '../assets/css/login.css';
@import "../assets/css/index.css";
</style>
Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐