# 权限验证

## 权限处理逻辑图
界于我司大部分中后台项目都是从OA跳转授权，我们设计了一个如下的登陆授权逻辑，其逻辑图如下：
![](../.vuepress/public/img/auth&permission.png)

## 场景分析
### 登陆授权

* 访问user/auth页面，进入授权流程
* 在auth页面的query中会携带可由OA授权的userId、mk、name等信息
* 携带以上参数，调用服务端授权接口，获取接口相应数据
* 如果接口返回认证失败，则跳转至OA
* 若接口响应成功，并返回用户信息、token等内容，则继续进行下一步操作，获取菜单、权限，并跳转到相应的页面
```javascript
// views/user/Auth.vue
export default {
  name: 'Auth',
  created() {
    let authInfo = this.$route.query
    this.$store.dispatch('getAuthToken', authInfo).then(() => {
      if (authInfo.token) {
        this.$store.dispatch('getMenus').then(() => {
          this.$notify({
            title: '成功',
            message: '自动授权登录成功！',
            type: 'success'
          })
          this.$router.replace((Date.now() % 2) ? '/welcome1' : '/welcome2')
        })
      } else {
        // 跳转至OA
        location.replace('http://oa.2345.cn')
      }
    })
  }
}
```
项目中推荐的菜单数据结构如下
```javascript
const menu = [
  {
    name: '页面排版',
    icon: 'el-icon-document',
    children: [
      {
        path: '/form/listForm',
        name: '卡片列表',
      },
      {
        path: '/form/tabForm',
        name: '查询表格',
      }
    ]
  }
]
```


### 路由跳转验证
* 跳转的路由不存在，会重定向至 /excption/exc404
* 路由存在，但在用户菜单中不存在，此类情况正常情况下应不存在，可能由用户手动更改路由触发，此时会更新一次菜单，在次检测，如果仍然不存在，则重定向至 /excption/exc403
* 目标路由免验证或者验证通过，则跳转至目标页面

```javascript
// router/index.js
router.beforeEach((to, from, next) => {
  document.title = to.name || 'Octopus Pro'
  // 路由验证
  if (!to.matched || !to.matched.length) {
    next('/exception/exc404')
  } else if (to.meta.exemption) {
    next()
  } else if (!checkPermissionMenu(to.path, store.state.userMenu)) {
    // 如果menu不存在，则获取一下
    store.dispatch('getMenus').then(() => {
      if (checkPermissionMenu(to.path, store.state.userMenu)) {
        next()
      } else {
        next('/exception/exc403')
      }
    })
  } else {
    next()
  }
})
```

### 求请访问性验证
* 服务器验证成功，页面接受到响应，正常处理数据
* 服务器验证登录失效，跳转至OA
* 服务器验证无权限，则更新权限menu或者跳转至403页面
```javascript
axiosRequest.interceptors.response.use(res => {
  // 在这里对返回的数据进行处理
  const code = Number(res.data.code)
  if (code !== 0) {
    if (code !== 403) {
      // 无权限
      // 更新menu 或 跳转至403页面
    } else if (code === 401) { 
      // 未登录 
      // 跳转至OA   
    } else {
      Message({
        type: 'error',
        message: res.data.msg || '服务器请求出错！'
      })
    }
    return Promise.reject(new Error(res.data.msg || '服务器错误'))
  }
  return res.data.data
}, (err) => {
  Message({
    type: 'error',
    message: '服务器请求出错！'
  })
  return Promise.reject(err)
})
```
