Django+drf+jwt+vue

1.传统的登录鉴权跟基于 Token 的鉴权有什么区别?

  • 以 Django 的账号密码登录为例来说明传统的验证鉴权方式是怎么工作的,当我们登录页面输入账号密码提交表单后,会发送请求给服务器,服务器对发送过来的账号密码进行验证鉴权,验证鉴权通过后,把用户信息记录在服务器端( django_session 表中),同时返回给浏览器一个 sessionid 用来唯一标识这个用户,浏览器将 sessionid 保存在 cookie 中,之后浏览器的每次请求都一并将 sessionid 发送给服务器,服务器根据 sessionid 与记录的信息做对比以验证身份
  • Token 的鉴权方式就清晰很多了,客户端用自己的账号密码进行登录,服务端验证鉴权,验证鉴权通过生成 Token 返回给客户端,之后客户端每次请求都将 Token 放在 header 里一并发送,服务端收到请求时校验 Token 以确定访问者身份
  • session 的主要目的是给无状态的 HTTP 协议添加状态保持,通常在浏览器作为客户端的情况下比较通用。而 Token 的主要目的是为了鉴权,同时又不需要考虑 CSRF 防护以及跨域的问题,所以更多的用在专门给第三方提供 API 的情况下,客户端请求无论是浏览器发起还是其他的程序发起都能很好的支持。所以目前基于 Token 的鉴权机制几乎已经成了前后端分离架构或者对外提供 API 访问的鉴权标准,得到广泛使用

2.drf 使用 jwt

2.1安装

pip install djangorestframework-jwt==1.10.0
安装完成后数据库迁移python manage.py migrate

2.2修改setting

REST_FRAMEWORK = {
    'DEFAULT_PERMISSION_CLASSES': (
        'rest_framework.permissions.IsAuthenticated',
    ),
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
        'rest_framework.authentication.SessionAuthentication',
        'rest_framework.authentication.BasicAuthentication',
    ),
}

INSTALLED_APPS = [
	...
    'rest_framework.authtoken'

]
# jwt载荷中的有效期设置
JWT_AUTH = {
    #token 有效期
    'JWT_EXPIRATION_DELTA': datetime.timedelta(hours=8),
    'JWT_ALLOW_REFRESH': True,
     #续期有效期(该设置可在24小时内带未失效的token 进行续期) 
    'JWT_REFRESH_EXPIRATION_DELTA': datetime.timedelta(hours=24),
   
}

2.3添加urls

#urls.py
from rest_framework_jwt.views import obtain_jwt_token
urlpatterns = [
    ...
    url(r'^login/$', obtain_jwt_token),
]

2.4添加管理员账号

python manage.py createsuperuser
在这里插入图片描述

2.5测试

在这里插入图片描述
vue中
在这里插入图片描述

在这里插入图片描述

3.vue 使用token

  • 用户使用用户名密码来请求服务器
  • 服务器进行验证用户的信息
  • 服务器通过验证发送给用户一个token
  • 客户端存储token,并在每次请求时附送上这个token值(添加在请求头中)
  • 服务端验证token值,并返回数据
  • 若token值过期,客户端清空token,跳转登录页

3.1获取token,保存到vuex => store 和localStorage

#在store.js中
import Vue from "vue"
import Vuex from "vuex"

Vue.use(Vuex)

const store = new Vuex.Store({
	    state: {
	    	...
	        token: localStorage.getItem('token') ? localStorage.getItem('token') : ''
	    },
	    mutations: {
	        changeLogin(state, token) {
	            state.token = token;
	            localStorage.setItem('token', token);
        },
 
    }
})
export default store

#在login.vue中
import { mapMutations } from "vuex";
export default {
  data() {
    return {
      formValidate: {
        username: "",
        password: "",
      },
    };
  },
  methods: {
    ...mapMutations(["changeLogin"]),
    handleSubmit() {
      if (
        this.formValidate.username == "" ||
        this.formValidate.password == ""
      ) {
        alert("账号或密码不能为空");
      } else {
        this.axios
          .post("http://127.0.0.1:8000/login/", this.formValidate)
          .then((res) => {
            // console.log(res);
            this.changeLogin({ token: res.data });

            this.$router.push({
              name: "pcm",
            });
          })
          .catch(function (error) {
            alert("密码错误,重新输入");
          });
      }
    },
  },
};

3.2建立router全局守卫

#在router.js中
//全局守卫
router.beforeEach((to, from, next) => {
    if (to.path === '/login') {
        next();
      } else {
        let token = localStorage.getItem('token');
     
        if (token === 'null' || token === '') {
          next('/login');
        } else {
          next();
        }
      }
})

3.3 添加请求头

官方文档https://jpadilla.github.io/django-rest-framework-jwt/#usage

在这里插入图片描述
这里照着官方文档
在这里插入图片描述
带着尖括号,一直报错{"detail":"Error decoding signature."},去掉尖括号就好了,我整个人都不好了

// 添加请求拦截器,在请求头中加token
axios.interceptors.request.use(
    config => {
      if (localStorage.getItem('token')) {
        config.headers.Authorization = localStorage.getItem('token');
      }
   
      return config;
    },
    error => {
      return Promise.reject(error);
    });

3.4当前端拿到状态码为401,就清除token信息,并跳转登录页面

// 拦截401错误,token过期,返回自定义错误
axios.interceptors.response.use(function (response) {
    // 对响应数据做点什么
    return response;
}, function (error) {
   
    // 对响应错误做点什么
    if (error.response.status === 401) {
        console.log("401")
        localStorage.removeItem('token');
        router.replace({
          path: '/login'
        })
        return response
    }
    return Promise.reject(error);
});
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值