One day, a problem occurred to me: 1. Can I really control the permissions? 2. Can real permission control be achieved only on the front end? 3. How to cooperate with the background if necessary? This may be a platitude of the problem, but still want to sort out, wrong place hope we point out.

What is permission control

Permission control can be roughly divided into two dimensions:

  • Vertical dimension: The permissions that control which urls a user can access
  • Horizontal dimension: control the user access to a specific URL, which data access permissions (e.g Common users, administrators, and super administrators access the same URL and obtain different data.

Web permission control scheme List

  • There is no separation between the front and back ends: Take Java as an example, the back end renders the data with corresponding permissions through templates such as JSP, freemark, and Thmeleaf, and then renders the data in the browser
  • Separation of front and rear ends:
    • In SPA single-page application, routes are controlled by the front end, and the front end controls the permission of hash routes through JS
    • SSR server rendering, Node middle layer as a proxy route, determine the permission to render a specific route to the browser side

SPA front-end permission control scheme

SPA: Single Page Web Application limits all Web activities to a single HTML page, uses JS to implement refresh-free route hopping via hash or browser history API, and communicates data from front to back via Ajax. It avoids browser refresh and reload and provides users with operation experience of flow. This means the front end takes over the routing layer and needs to render different pages by calling the front end’s own MVC module.

Base on:

  • Vue front-end MVVM framework
  • Vuex status management machine
  • Vue – the router routing
  • Axios HTTP request library

1. Login event

// 1. Trigger the login event
dispatch('login')
 
// actions
commit(types.LOGIN_SUCCESS, res.data.data)
...
Copy the code

2. Obtain the Token and save it to sessionStorage after Base64 encoding

// mutations
const mutations = {
    [types.LOGIN_SUCCESS] (state, data) {
        state.authlock = false
	// 2. Login succeeds, callback the token, and store the token in the local sessionStorage after Base64 encoding
        let token = Base64.encode(data + ':HIKDATAE')
        sessionStorage.setItem('userToken', token)
	// Route redirects to the destination page
        router.push({name: 'xxx'})
    },
    [types.LOGOUT_SUCCESS] (state) {
        state.authlock = true
	// The local token was removed after a successful logout callback
        sessionStorage.removeItem('userToken')
		router.push({name: 'Login'}}})Copy the code

3. All HTTP Header Authorization plus encoded tokens (front-end and back-end assignable rules)

// Axios request hook (request)
axios.interceptors.request.use(req= > {
    let token = sessionStorage.getItem('user')     
    if (token) { 		
        // 3. If the token exists, the base64 encoded token is added to the HTTP request header Authorization of all subsequent requests, and the background verifies the permission after the token is obtained
        req.headers.Authorization = `Basic ${token}`     
    }
    req.data = qs.stringify(req.data)     
    return req 
}, error => {
    return Promise.reject(error) 
})
Copy the code

Browser HTTP header

4. Request interception: the background verifies each request after getting the token. If the verification fails, 401 will be returned, and the front-end response hook will jump to the login page with catch error

// Axios requests the hook (response)
axios.interceptors.response.use(res= > {
    return res
}, error => {
	if (error.response) {
        switch (error.response.status) {
		// 4. Response check hook for all interfaces. If the token check fails, the background returns 401 Error code to clear the token information and jump to the login page
        	case 401:
            	store.commit(types.LOGOUT)
            	router.replace({
            		path: '/login'}}})return Promise.reject(error)
})
Copy the code

5. Route redirect interception: Before any route redirect, check whether the local token exists in the route beforeEach hook. If not, the local token is redirected to the login page

// route hook (raises beforeEach hook beforeEach route jump)
router.beforeEach((to, from, next) = > {
  if (to.path === '/login') {
    sessionStorage.removeItem('userToken')}let user = sessionStorage.getItem('userToken')
  if(! user && to.path ! = ='/login') {
	// If the local token does not exist, any route redirects you to the login page
    next({ path: '/login'})}else {
    next()
  }
})
Copy the code

6. Logout: Clears the token information of the local sessionStorage

// mutations
const mutations = {
	...
    [types.LOGOUT_SUCCESS] (state) {
        state.authlock = true
	// The local token was removed after a successful logout callback
        sessionStorage.removeItem('userToken')
	router.push({name: 'Login'}}})Copy the code

The process diagram is as follows:

What is a real security clearance? There is still a long way to go…


Synced to personal blog – hard or soft

Github welcome star 🙂