{"id":13536374,"url":"https://github.com/superman66/vue-axios-github","last_synced_at":"2025-04-15T03:49:51.191Z","repository":{"id":50481034,"uuid":"82163712","full_name":"superman66/vue-axios-github","owner":"superman66","description":"Vue 全家桶 + axios 前端实现登录拦截、登出、拦截器等功能","archived":false,"fork":false,"pushed_at":"2020-06-09T08:24:34.000Z","size":598,"stargazers_count":2689,"open_issues_count":8,"forks_count":728,"subscribers_count":96,"default_branch":"master","last_synced_at":"2025-04-15T03:49:41.472Z","etag":null,"topics":["axios","login-oauth","vue-router","vuejs2","vuex"],"latest_commit_sha":null,"homepage":"http://superman66.github.io/vue-axios-github/","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/superman66.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-02-16T09:33:32.000Z","updated_at":"2025-04-10T08:41:29.000Z","dependencies_parsed_at":"2022-08-30T22:52:09.238Z","dependency_job_id":null,"html_url":"https://github.com/superman66/vue-axios-github","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/superman66%2Fvue-axios-github","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/superman66%2Fvue-axios-github/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/superman66%2Fvue-axios-github/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/superman66%2Fvue-axios-github/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/superman66","download_url":"https://codeload.github.com/superman66/vue-axios-github/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":249003943,"owners_count":21196794,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["axios","login-oauth","vue-router","vuejs2","vuex"],"created_at":"2024-08-01T09:00:38.044Z","updated_at":"2025-04-15T03:49:51.175Z","avatar_url":"https://github.com/superman66.png","language":"JavaScript","funding_links":[],"categories":["Demo示例"],"sub_categories":[],"readme":"[![Travis](https://img.shields.io/travis/superman66/vue-axios-github.svg)](https://travis-ci.org/superman66/vue-axios-github)\n# 一个项目学会前端实现登录拦截\n\n\u003e 一个项目学会vue全家桶+axios实现登录、拦截、登出功能，以及利用axios的http拦截器拦截请求和响应。\n\n点击这里查看👉 [Demo](https://github.com/superman66/vue-axios-github)\n\n页面打不开？可能你需要翻墙。[点击查看翻墙推荐](https://github.com/superman66/mac/issues/4)\n## 前言\n该项目是利用了Github 提供的personal token作为登录token，通过token访问你的Repository List。通过这个项目学习如何实现一个前端项目中所需要的\n登录及拦截、登出、token失效的拦截及对应 axios 拦截器的使用。\n\n**准备**\n\n你需要先生成自己的 Github Personal Token（[生成Token](https://github.com/settings/tokens/new)）。\nToken 生成后 访问 [Demo](http://chenhuichao.com/vue-axios-github/)，即可查看你的Repository List。\n\n## 项目结构\n\n```\n.\n├── README.md\n├── dist  // 打包构建后的文件夹\n│   ├── build.js\n│   └── build.js.map\n├── index.html\n├── package.json\n├── src\n│   ├── App.vue\n│   ├── assets\n│   │   ├── css.css\n│   │   ├── icon.css\n│   │   └── logo.png\n│   ├── constant\n│   │   └── api.js  // 配置api接口文件\n│   ├── http.js // 封装fetch、post请求及http 拦截器配置文件\n│   ├── index.vue\n│   ├── login.vue\n│   ├── main.js\n│   ├── repository.vue\n│   ├── router.js // 路由配置文件\n│   └── store\n│       ├── store.js  \n│       └── types.js  // vuex types\n└── webpack.config.js\n```\n\n### 技术栈\n* Vue 2.0\n* vue-router\n* vuex\n* axios\n* vue-material\n\n### 登录拦截逻辑\n\n#### 第一步：路由拦截\n首先在定义路由的时候就需要多添加一个自定义字段`requireAuth`，用于判断该路由的访问是否需要登录。如果用户已经登录，则顺利进入路由，\n否则就进入登录页面。\n```javascript\nconst routes = [\n    {\n        path: '/',\n        name: '/',\n        component: Index\n    },\n    {\n        path: '/repository',\n        name: 'repository',\n        meta: {\n            requireAuth: true,  // 添加该字段，表示进入这个路由是需要登录的\n        },\n        component: Repository\n    },\n    {\n        path: '/login',\n        name: 'login',\n        component: Login\n    }\n];\n```\n定义完路由后，我们主要是利用`vue-router`提供的钩子函数`beforeEach()`对路由进行判断。\n\n```javascript\nrouter.beforeEach((to, from, next) =\u003e {\n    if (to.meta.requireAuth) {  // 判断该路由是否需要登录权限\n        if (store.state.token) {  // 通过vuex state获取当前的token是否存在\n            next();\n        }\n        else {\n            next({\n                path: '/login',\n                query: {redirect: to.fullPath}  // 将跳转的路由path作为参数，登录成功后跳转到该路由\n            })\n        }\n    }\n    else {\n        next();\n    }\n})\n```\n每个钩子方法接收三个参数：\n\n* to: Route: 即将要进入的目标 路由对象\n* from: Route: 当前导航正要离开的路由\n* next: Function: 一定要调用该方法来 resolve 这个钩子。执行效果依赖 next 方法的调用参数。\n  * next(): 进行管道中的下一个钩子。如果全部钩子执行完了，则导航的状态就是 confirmed （确认的）。\n  * next(false): 中断当前的导航。如果浏览器的 URL 改变了（可能是用户手动或者浏览器后退按钮），那么 URL 地址会重置到 from 路由对应的地址。\n  * next('/') 或者 next({ path: '/' }): 跳转到一个不同的地址。当前的导航被中断，然后进行一个新的导航。\n\n**确保要调用 next 方法，否则钩子就不会被 resolved。**\n\u003e 完整的方法见`/src/router.js`\n\n其中，`to.meta`中是我们自定义的数据，其中就包括我们刚刚定义的`requireAuth`字段。通过这个字段来判断该路由是否需要登录权限。需要的话，同时当前应用不存在token，则跳转到登录页面，进行登录。登录成功后跳转到目标路由。\n\n登录拦截到这里就结束了吗？并没有。这种方式只是简单的前端路由控制，并不能真正阻止用户访问需要登录权限的路由。还有一种情况便是：当前token失效了，但是token依然保存在本地。这时候你去访问需要登录权限的路由时，实际上应该让用户重新登录。\n这时候就需要结合 http 拦截器 + 后端接口返回的http 状态码来判断。\n\n#### 第二步：拦截器\n要想统一处理所有http请求和响应，就得用上 axios 的拦截器。通过配置`http response inteceptor`，当后端接口返回`401 Unauthorized（未授权）`，让用户重新登录。\n\n```javascript\n// http request 拦截器\naxios.interceptors.request.use(\n    config =\u003e {\n        if (store.state.token) {  // 判断是否存在token，如果存在的话，则每个http header都加上token\n            config.headers.Authorization = `token ${store.state.token}`;\n        }\n        return config;\n    },\n    err =\u003e {\n        return Promise.reject(err);\n    });\n\n// http response 拦截器\naxios.interceptors.response.use(\n    response =\u003e {\n        return response;\n    },\n    error =\u003e {\n        if (error.response) {\n            switch (error.response.status) {\n                case 401:\n                    // 返回 401 清除token信息并跳转到登录页面\n                    store.commit(types.LOGOUT);\n                    router.replace({\n                        path: 'login',\n                        query: {redirect: router.currentRoute.fullPath}\n                    })\n            }\n        }\n        return Promise.reject(error.response.data)   // 返回接口返回的错误信息\n    });\n```\n\u003e完整的方法见`/src/http.js`.\n\n通过上面这两步，就可以在前端实现登录拦截了。`登出`功能也就很简单，只需要把当前token清除，再跳转到首页即可。\n\n\n## 运行及构建\n``` bash\n# install dependencies\nnpm install\n\n# serve with hot reload at localhost:8080\nnpm run dev\n\n# build for production with minification\nnpm run build\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsuperman66%2Fvue-axios-github","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsuperman66%2Fvue-axios-github","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsuperman66%2Fvue-axios-github/lists"}