Django+drf+jwt+vue

文章目录
1.传统的登录鉴权跟基于 Token 的鉴权有什么区别?
2.drf 使用 jwt
2.1安装
2.2修改setting
2.3添加urls
2.4添加管理员账号
2.5测试
3.vue 使用token
3.1获取token,保存到vuex => store 和localStorage
3.2建立router全局守卫
3.3 添加请求头
3.4当前端拿到状态码为401,就清除token信息,并跳转登录页面
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添加管理员账号

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 添加请求头

官方文档Django REST framework JWT

带着尖括号,一直报错{"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、付费专栏及课程。

余额充值