小记——Vuex实现前端拦截

之前讲过后端拦截的实现,后端拦截与前端拦截的区别:发生拦截的位置不同,一个在后端,一个在前端。
后端拦截时请求肯定是已经到达了服务端,后端已经要做处理了。后端拦截的逻辑是对session判断,是否包含用户信息,没有就执行重定向请求,方法是response.sendRedirect(“/xxx”),这个过程一直是后端在操纵,最后返回给浏览器。
前端拦截是前端框架分别利用状态管理和路由,判断登录状态和重定向请求,比如Vue.js利用Vuex保存一个浏览器用户状态,当用户状态是未登录时,使用vue-router重定向到"/login"。这个过程是发生在前端的,只有必须要请求后端时才向服务端发送请求("/login")。
前端拦截的实现代码来自博客Vue + Spring Boot 项目实战(六):前端路由与登录拦截器

仅仅靠下面的前端拦截实现是不可行的,存在绕过风险,这里暂不讨论。详细请参考博客Vue + Spring Boot 项目实战(十四):用户认证方案与完善的访问拦截的第二部分:完善的访问拦截。

引入Vuex:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
state: {
user: {
username: window.localStorage.getItem('user' || '[]') == null ? '' : JSON.parse(window.localStorage.getItem('user' || '[]')).username
}
},
mutations: {
login (state, user) {
state.user = user
window.localStorage.setItem('user', JSON.stringify(user))
}
}
})

配置vue-router,修改router/index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import Vue from 'vue'
import Router from 'vue-router'
import AppIndex from '@/components/home/AppIndex'
import Login from '@/components/Login'

Vue.use(Router)

export default new Router({
mode: 'history',
routes: [
{
path: '/login',
name: 'Login',
component: Login
},
{
path: '/index',
name: 'AppIndex',
component: AppIndex,
meta: {
requireAuth: true
}
}
]
})

配置main.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
import Vue from 'vue'
import App from './App'
import router from './router'
import store from './store'
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'

var axios = require('axios')
axios.defaults.baseURL = 'http://localhost:8443/api'
Vue.prototype.$axios = axios
Vue.config.productionTip = false

Vue.use(ElementUI)

router.beforeEach((to, from, next) => {
if (to.meta.requireAuth) {
if (store.state.user.username) {
next()
} else {
next({
path: 'login',
query: {redirect: to.fullPath}
})
}
} else {
next()
}
}
)

/* eslint-disable no-new */
new Vue({
el: '#app',
render: h => h(App),
router,
store,
components: { App },
template: '<App/>'
})

配置Login.vue(已删除UI部分,只保留了js脚本)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
export default {
name: 'Login',
data () {
return {
loginForm: {
username: 'admin',
password: '123'
},
responseResult: []
}
},
methods: {
login () {
var _this = this
console.log(this.$store.state)
this.$axios
.post('/login', {
username: this.loginForm.username,
password: this.loginForm.password
})
.then(successResponse => {
if (successResponse.data.code === 200) {
// var data = this.loginForm
_this.$store.commit('login', _this.loginForm)
var path = this.$route.query.redirect
this.$router.replace({path: path === '/' || path === undefined ? '/index' : path})
}
})
.catch(failResponse => {
})
}
}
}

后端拦截可参考本人另外的博客:
后端登录拦截/过滤
这两篇博客均是学习Vue + Spring Boot 项目实战(六):前端路由与登录拦截器的解决心得。