JWT 认证

1. JWT工作原理

"""
1) jwt = base64(头部).base(载荷).hash256(base64(头部).base(载荷).密钥)
2) base64是可逆的算法、hash256是不可逆的算法
3) 密钥是固定的字符串,保存在服务器
"""

2. 安装

官网

http://jpadilla.github.io/django-rest-framework-jwt/

安装

pip install djangorestframework-jwt

3. 用法

在您的中 settings.py ,添加 JSONWebTokenAuthentication 到 Django REST 框架的 DEFAULT_AUTHENTICATION_CLASSES

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',
    ),
}

# 设置token失效时间
import datetime 
JWT_AUTH = {
  # 过期时间
  'JWT_EXPIRATION_DELTA': datetime.timedelta(days=1),
  # 自定义认证结果:见下方序列化user和自定义response
  'JWT_RESPONSE_PAYLOAD_HANDLER': 'user.utils.jwt_response_payload_handler',
}
 

序列化 user  自己创建

from rest_framework import serializers
from . import models
class UserModelSerializers(serializers.ModelSerializer):
    class Meta:
        model = models.User
        fields = ['username']

自定义response

# 用处:你登陆成功之后 显示欢迎谁回来  在上面 要配置
from
.serializers import UserModelSerializers def jwt_response_payload_handler(token, user=None, request=None): return { 'status': 0, 'msg': 'ok', 'data': { 'token': token, 'user': UserModelSerializers(user).data } }

基于jwt的全局认证

import jwt
from rest_framework.exceptions import AuthenticationFailed
from rest_framework_jwt.authentication import jwt_decode_handler
from rest_framework_jwt.authentication import get_authorization_header
from rest_framework_jwt.authentication import BaseJSONWebTokenAuthentication

class JSONWebTokenAuthentication(BaseJSONWebTokenAuthentication):
    def authenticate(self, request):
        jwt_value = get_authorization_header(request)

        if not jwt_value:
            raise AuthenticationFailed('Authorization 字段是必须的')
        try:
            payload = jwt_decode_handler(jwt_value)
        except jwt.ExpiredSignature:
            raise AuthenticationFailed('签名过期')
        except jwt.InvalidTokenError:
            raise AuthenticationFailed('非法用户')
        user = self.authenticate_credentials(payload)

        return user, jwt_value

全局启用 settings

REST_FRAMEWORK = {
    # 认证模块
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'user.authentications.JSONWebTokenAuthentication',
    ),
}

局部启用禁用:任何一个cbv类的首行

# 局部禁用
authentication_classes = []

# 局部启用
from user.authentications import JSONWebTokenAuthentication
authentication_classes = [JSONWebTokenAuthentication]

多方式登陆

import re
from .models import User
from django.contrib.auth.backends import ModelBackend
class JWTModelBackend(ModelBackend):
    def authenticate(self, request, username=None, password=None, **kwargs):
        try:
            if re.match(r'^1[3-9]\d{9}$', username):
                user = User.objects.get(mobile=username)
            else:
                user = User.objects.get(username=username)
        except User.DoesNotExist:
            return None
        if user.check_password(password) and self.user_can_authenticate(user):
            return user

配置多方式登陆 settings

AUTHENTICATION_BACKENDS = ['user.utils.JWTModelBackend']

手动签发JWT:了解-可以拥有原生登陆基于Model类user对象签发JWT

from rest_framework_jwt.settings import api_settings

jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER

payload = jwt_payload_handler(user)
token = jwt_encode_handler(payload)

VUE

             # 页面  
         <div class="inp" v-if="login_type==0"> <input v-model = "username" type="text" placeholder="用户名 / 手机号码" class="user"> <input v-model = "password" type="password" name="" class="pwd" placeholder="密码"> <div id="geetest1"></div> <div class="rember"> <p> <input type="checkbox" class="no" v-model="remember"/> <span>记住密码</span> </p> <p>忘记密码</p> </div> <button class="login_btn" @click="loginHander">登录</button> <p class="go_login" >没有账号 <span>立即注册</span></p> </div>
<script>
export default {
  name: 'Login',
  data(){
    return {
        login_type: 0,
        username:"",
        password:"",
        remember:false,
    }
  },
  methods:{
    loginHander(){
        // 用户密码账号登录
        this.$axios.post(`${this.$settings.HOST}/user/login/`,{
            username:this.username,
            password:this.password,
        }).then(response=>{
            if(this.remember){
                // 记住登录状态
                sessionStorage.removeItem("user_token");
                sessionStorage.removeItem("user_id");
                sessionStorage.removeItem("user_name");
                localStorage.user_token = response.data.token;
                localStorage.user_id = response.data.id;
                localStorage.user_name = response.data.username;
            }else{
                // 不记住登录状态
                localStorage.removeItem("user_token");
                localStorage.removeItem("user_id");
                localStorage.removeItem("user_name");
                sessionStorage.user_token = response.data.token;
                sessionStorage.user_id = response.data.id;
                sessionStorage.user_name = response.data.username;
            }

            // 页面跳转
            let self = this;
            this.$alert("登录成功!","某某某网站",{
               callback(){
                    self.$router.push("/");
               }
            });

        }).catch(error=>{
            this.$message.error("对不起,登录失败!请确认密码或账号是否正确!");
        });
    },
   
};
</script>

 

posted @ 2020-04-11 22:45  流年中渲染了微笑  阅读(281)  评论(0编辑  收藏  举报