Skip to content

前端权限控制方案 #45

Open
Open
@palmerye

Description

SPA前端权限控制方案

SPA: 单页Web应用(single page web application)将所有web活动局限于一个html页面中,利用js通过hash或者浏览器history api来实现无刷新路由跳转,前后端通过ajax数据通信,避免了浏览器的刷新重新加载,为用户提供流程的操作体验。这意味着前端接管了路由层,需要通过调用前端自身的MVC模块,来渲染不同的页面。

Date: 2017/9/23
Author: yepanmeng

Base on:

  • Vue 框架
  • Vuex 状态管理机
  • Vue-router 路由
  • Axios http请求库

1.登陆事件Login

// 1.触发登陆事件
dispatch('login')
 
// actions
commit(types.LOGIN_SUCCESS, res.data.data)
...

2.获取Token,经Base64编码后存至sessionStorage

// mutations
const mutations = {
    [types.LOGIN_SUCCESS] (state, data) {
        state.authlock = false
	// 2.登陆成功回调拿到token,经Base64 编码后存入本地sessionStorage
        let token = Base64.encode(data + ':HIKDATAE')
        sessionStorage.setItem('userToken', token)
	// 路由跳转至目标页面
        router.push({name: 'xxx'})
    },
    [types.LOGOUT_SUCCESS] (state) {
        state.authlock = true
	// 登出成功回调,移除本地token
        sessionStorage.removeItem('userToken')
		router.push({name: 'Login'})
    }
}

3.所有HTTP Header Authorization 加上编码后的token(前后端可约定规则)

// Axios 请求钩子(request)
axios.interceptors.request.use(req => {
    let token = sessionStorage.getItem('user')     
    if (token) { 		
        // 3.token 存在,则在之后所有请求的http请求头 Authorization 带上base64编码后的token,后台拿到token后进行验证权限         
        req.headers.Authorization = `Basic ${token}`     
    }
    req.data = qs.stringify(req.data)     
    return req 
}, error => {
    return Promise.reject(error) 
})

浏览器http header

FEAuths

4.请求拦截:后台拿到token后对每个请求进行校验,若校验失败返回401,前端response钩子里统一catch error 跳转至登陆页面

// Axios 请求钩子(response)
axios.interceptors.response.use(res => {
    return res
}, error => {
	if (error.response) {
        switch (error.response.status) {
		// 4.所有接口response校验钩子,若token检验失败,后台返回 401 error code, 清除token信息并跳转到登录页面
        	case 401:
            	store.commit(types.LOGOUT)
            	router.replace({
            		path: '/login'
		})
	}
    }
    return Promise.reject(error)
})

5.路由跳转拦截:任意路由跳转时,在路由beforeEach钩子里校验本地是否存在token,若没有,则跳转至登陆页面

// 路由钩子(每个路由跳转前调起beforeEach钩子)
router.beforeEach((to, from, next) => {
  if (to.path === '/login') {
    sessionStorage.removeItem('userToken')
  }
  let user = sessionStorage.getItem('userToken')
  if (!user && to.path !== '/login') {
	// 若本地token不存在,则任意路由跳转的时候,重定向至login 登陆页面
    next({ path: '/login' })
  } else {
    next()
  }
})

6.登出Logout:清楚本地sessionStorage的token信息

// mutations
const mutations = {
	...
    [types.LOGOUT_SUCCESS] (state) {
        state.authlock = true
	// 登出成功回调,移除本地token
        sessionStorage.removeItem('userToken')
	router.push({name: 'Login'})
    }
}

流程示意图如下:

FEAuth

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Assignees

Labels

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions