Code Monkey home page Code Monkey logo

vue-axios-github's Introduction

Travis

一个项目学会前端实现登录拦截

一个项目学会vue全家桶+axios实现登录、拦截、登出功能,以及利用axios的http拦截器拦截请求和响应。

点击这里查看👉 Demo

页面打不开?可能你需要翻墙。点击查看翻墙推荐

前言

该项目是利用了Github 提供的personal token作为登录token,通过token访问你的Repository List。通过这个项目学习如何实现一个前端项目中所需要的 登录及拦截、登出、token失效的拦截及对应 axios 拦截器的使用。

准备

你需要先生成自己的 Github Personal Token(生成Token)。 Token 生成后 访问 Demo,即可查看你的Repository List。

项目结构

.
├── README.md
├── dist  // 打包构建后的文件夹
│   ├── build.js
│   └── build.js.map
├── index.html
├── package.json
├── src
│   ├── App.vue
│   ├── assets
│   │   ├── css.css
│   │   ├── icon.css
│   │   └── logo.png
│   ├── constant
│   │   └── api.js  // 配置api接口文件
│   ├── http.js // 封装fetch、post请求及http 拦截器配置文件
│   ├── index.vue
│   ├── login.vue
│   ├── main.js
│   ├── repository.vue
│   ├── router.js // 路由配置文件
│   └── store
│       ├── store.js  
│       └── types.js  // vuex types
└── webpack.config.js

技术栈

  • Vue 2.0
  • vue-router
  • vuex
  • axios
  • vue-material

登录拦截逻辑

第一步:路由拦截

首先在定义路由的时候就需要多添加一个自定义字段requireAuth,用于判断该路由的访问是否需要登录。如果用户已经登录,则顺利进入路由, 否则就进入登录页面。

const routes = [
    {
        path: '/',
        name: '/',
        component: Index
    },
    {
        path: '/repository',
        name: 'repository',
        meta: {
            requireAuth: true,  // 添加该字段,表示进入这个路由是需要登录的
        },
        component: Repository
    },
    {
        path: '/login',
        name: 'login',
        component: Login
    }
];

定义完路由后,我们主要是利用vue-router提供的钩子函数beforeEach()对路由进行判断。

router.beforeEach((to, from, next) => {
    if (to.meta.requireAuth) {  // 判断该路由是否需要登录权限
        if (store.state.token) {  // 通过vuex state获取当前的token是否存在
            next();
        }
        else {
            next({
                path: '/login',
                query: {redirect: to.fullPath}  // 将跳转的路由path作为参数,登录成功后跳转到该路由
            })
        }
    }
    else {
        next();
    }
})

每个钩子方法接收三个参数:

  • to: Route: 即将要进入的目标 路由对象
  • from: Route: 当前导航正要离开的路由
  • next: Function: 一定要调用该方法来 resolve 这个钩子。执行效果依赖 next 方法的调用参数。
    • next(): 进行管道中的下一个钩子。如果全部钩子执行完了,则导航的状态就是 confirmed (确认的)。
    • next(false): 中断当前的导航。如果浏览器的 URL 改变了(可能是用户手动或者浏览器后退按钮),那么 URL 地址会重置到 from 路由对应的地址。
    • next('/') 或者 next({ path: '/' }): 跳转到一个不同的地址。当前的导航被中断,然后进行一个新的导航。

确保要调用 next 方法,否则钩子就不会被 resolved。

完整的方法见/src/router.js

其中,to.meta中是我们自定义的数据,其中就包括我们刚刚定义的requireAuth字段。通过这个字段来判断该路由是否需要登录权限。需要的话,同时当前应用不存在token,则跳转到登录页面,进行登录。登录成功后跳转到目标路由。

登录拦截到这里就结束了吗?并没有。这种方式只是简单的前端路由控制,并不能真正阻止用户访问需要登录权限的路由。还有一种情况便是:当前token失效了,但是token依然保存在本地。这时候你去访问需要登录权限的路由时,实际上应该让用户重新登录。 这时候就需要结合 http 拦截器 + 后端接口返回的http 状态码来判断。

第二步:拦截器

要想统一处理所有http请求和响应,就得用上 axios 的拦截器。通过配置http response inteceptor,当后端接口返回401 Unauthorized(未授权),让用户重新登录。

// http request 拦截器
axios.interceptors.request.use(
    config => {
        if (store.state.token) {  // 判断是否存在token,如果存在的话,则每个http header都加上token
            config.headers.Authorization = `token ${store.state.token}`;
        }
        return config;
    },
    err => {
        return Promise.reject(err);
    });

// http response 拦截器
axios.interceptors.response.use(
    response => {
        return response;
    },
    error => {
        if (error.response) {
            switch (error.response.status) {
                case 401:
                    // 返回 401 清除token信息并跳转到登录页面
                    store.commit(types.LOGOUT);
                    router.replace({
                        path: 'login',
                        query: {redirect: router.currentRoute.fullPath}
                    })
            }
        }
        return Promise.reject(error.response.data)   // 返回接口返回的错误信息
    });

完整的方法见/src/http.js.

通过上面这两步,就可以在前端实现登录拦截了。登出功能也就很简单,只需要把当前token清除,再跳转到首页即可。

运行及构建

# install dependencies
npm install

# serve with hot reload at localhost:8080
npm run dev

# build for production with minification
npm run build

vue-axios-github's People

Contributors

superman66 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

vue-axios-github's Issues

如何让部分请求自定义拦截器

axios的interceptors全局的拦截器所以的请求都会被处理,如果我有一个请求不想用到这个拦截器想自定义回调的话,需要怎么做呢

我之前也用vueResource使用过,后面发现有点问题.

按照这个思路
是通过判断vuex里面的token是否存在来允许是否进入该路由.
我当时的需求是通过判断权限.可以说也是从vuex里面拿的数据
但有个问题就是
当按了F5刷新.
这时候进入router.forEach是比 app.beforeCreated要早执行的
这时候是不存在store里面的相关信息.所以就直接跳去login.
也是说每次按F5都要重新登陆一遍.
不知道你的会不会有这种情况.

vuex 浏览器刷新就没掉了

if (store.state.token) { // 通过vuex state获取当前的token是否存在 next(); }

所以应该要放到sessionStorage或者localStorage里吧?

后端401时,axios没能拦截到未授权信息

// http response 拦截器 axios.interceptors.response.use( response => { return response; }, error => { if (error.response) { switch (error.response.status) { case 401: // 返回 401 清除token信息并跳转到登录页面 store.commit(types.LOGOUT); router.replace({ path: 'login', query: {redirect: router.currentRoute.fullPath} }) } } return Promise.reject(error.response.data) // 返回接口返回的错误信息 });
error.response undefined

关于token存值的疑问

为什么在router.js 里面要根据 localStrorage 里面有没有 token 重新给state赋值 token

https://github.com/superman66/vue-axios-github/blob/master/src/router.js#L37

我的疑问

不能直接在 Line 48 这样判断吗?

if (localStrorage.getItem('token')) {
    next();
}

我的理解

Line 37的做法其实就是每次重载页面把 token 存在了 state 里面,是为了方便存在 state 里面的token 以后使用 ?

如果有时间请帮忙解答一下我的疑惑

谢谢,学习了

因为都是团队合作写项目,这一块权限的配置,都是leader在做。学习了

不会出现循环引用吗?

入口main.js中import了http,而http中import了router,router中import了repository,repository中import了http

Vue.prototype.axios = axios;报错

错误提示为:Cannot set property axios of #<Vue$3> which has only a getter at eval ,都是按照readme文档来搭建的。然后提示这个错误

在一个页面有多个请求返回401的情况下 登入会有点问题

比如我在某个页面有两个请求,现在我把localStorage里面的token手动改掉刷新,问题就来了,因为http的请求拦截在401的情况下
image总是会把fullPath当做redirect传递过去 两次的请求返回都是401且返回时间不在同一个时间点导致前面一个401到登入页来了 后面一个401又把登入页面的fullPath给到redirect。这时的登入页会有两个redirect组成的路由这种情况怎么处理

你好!关于刷新页面,Vuex实例store中保存的token为什么要重新获取。

问题产生:
我在登录的时候如你一样去把token,user放入了state中,我设想的情况时,既然store挂载的是一个vue实例,那么不论什么情况,只要不重建vue实例,store中的数据就不该丢失。但是我就是在刷新的时候,store中的数据会清空。这和我预期不符。参考你的代码,有一段是刷新之后重新获取token的代码。(router.js文件中38行),想必你能为我解答这个疑惑!

token 401判断

这个token 是sessionId 吧
每次http请求, cookie都会带上sessionId
验证没通过 接口也能返回401

如果http头的authorization 带上 sid,
cookie 的sid 后台是不是就不用判断了,
那要后台修改判断方式吗, 会不会降低安全性, 因为cookie字段可以用httpOnly保护起来,

而存储在vuex 或者 sessionStorage中, 给了xss机会 ;

嵌套路由时,子路由需要重复设置meta:{requireAuth:true}

{ path: '/parent', name: 'parent', component: Parent, meta: { requireAuth: true }, children: [ { name: 'child', path: 'child', component: Child } ] }
当访问/parent/child的时候并没有执行权限验证,所以建议在beforeEach中的判断由to.meta.requireAuth改为to.matched.some(r => r.meta.requireAuth),这样的话父路由设置requireAuth后子路由就不用设置了
个人愚见,错误之处还请指正😝

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.