jwt 认证

Posted kai-

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了jwt 认证相关的知识,希望对你有一定的参考价值。

jwt 认证示意图

jwt 优势

1 没有数据库写操作,高效

2 服务器不存 token,低耗

3 签发检验都是算法,集群

技术图片

技术图片

技术图片

技术图片



jwt 认证算法:签发与检验

  1. jwt 三段式:头 . 体 . 签名 (head.payload.sgin)

  2. 头和体是可逆加密,让服务器可以反解除 user 对象,签名是不可逆加密,保证整个token的安全性的

  3. 头体签名三部分,都是采用 json 格式的字符串,进行加密,可逆加密一般采用 base64 算法,不可逆加密一般采用 hash(md5) 算法

  4. 头中的内容是基本信息:公司信息,项目组信息,token 采用的加密方式信息

    {
       "company": "公司信息",
       ...
    }
  5. 体中的内容是关键信息:用户主键,用户名,签发是客户端信息(设备号,地址),过期时间

    {
       "user_id": 1,
       ...
    }
  6. 签名中的内容是安全信息:头的加密结果 + 体的加密结果 + 服务器不对外公开的安全吗 进行 md5 加密

    {
       "head": "头的加密字符串",
       "payload": "体的加密字符串",
       "secret_key": "安全码"
    }


签发

根据登陆请求提交来的 账号 + 密码 + 设备信息 签发 token

  1. 用基本信息存储 json 字典,采用 base64 算法加密得到 头字符串
  2. 用关键信息存储 json 字典,采用 base64 算法加密得到 体字符串
  3. 用头、体加密字符串再加安全码信息存储 json 字典,采用 hash md5 算法加密得到 签名字符串

校验

根据客户端带 token 的请求,反解除 user 对象

  1. 将 token按“ . ”拆分为三段字符串,第一段头加密字符串,一般不需要做任何处理
  2. 第二段体加密字符串,要反解出用户主键,通过主键从 User 表中就能得到登陆用户,过期时间和设备信息都是安全信息,确保 token 没过期,且是同一设备来的
  3. 再用 第一段 + 第二段 + 服务器安全吗 不可逆 md5 加密,与第三段字符串进行碰撞校验,通过后才能代表第二段校验得到的 user 对象就是合法的登陆用户


drf 项目的 jwt 认证开发流程(重点)

  1. 用账号密码访问登陆接口,登陆接口逻辑中调用 签发 token 算法,得到 token,返回给客户端,客户端自己存到 cookies 中
  2. 校验 token 的算法应该写在认证类中(在认证类中调用),全局配置给认证组件,所有视图类请求,都会校验,所以请求带来了 token,就会反解出 user 对象,在视图类中用 request.user 就能访问登陆的用户

注意:登陆接口需要做 认证 + 权限 两个局部禁用



drf-jwt 框架基本使用

安装

pip install djangorestframework-jwt

签发 token(登陆接口):视图类已经写好了,配置一下路由就行(urls.py)

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

# Postman请求:/api/login/,提供username和password即可

校验 token (认证组件):认证类已经写好了,全局配置一下组件就行了(settings.py)

# drf-jwt的配置
import datetime
JWT_AUTH = {
    # 配置过期时间
    'JWT_EXPIRATION_DELTA': datetime.timedelta(days=7),
}


# drf配置(把配置放在最下方)
REST_FRAMEWORK = {
    # 自定义三大认证配置类们
    'DEFAULT_AUTHENTICATION_CLASSES': ['rest_framework_jwt.authentication.JSONWebTokenAuthentication'],
    # 'DEFAULT_PERMISSION_CLASSES': [],
    # 'DEFAULT_THROTTLE_CLASSES': [],
}

设置需要登陆才能访问的接口进行测试(views.py)

from rest_framework.permissions import IsAuthenticated
class UserCenterViewSet(GenericViewSet, mixins.RetrieveModelMixin):
    # 设置必须登录才能访问的权限类
    permission_classes = [IsAuthenticated, ]

    queryset = models.User.objects.filter(is_active=True).all()
    serializer_class = serializers.UserCenterSerializer

测试访问登陆认证接口(Postman)

"""
1)用 {"username": "你的用户", "password": "你的密码"} 访问 /api/login/ 接口等到 token 字符串

2)在请求头用 Authorization 携带 "jwt 登录得到的token" 访问 /api/user/center/1/ 接口访问个人中心
"""



token 刷新机制(了解)

drf-jwt 直接提供刷新功能

"""
1)运用在像12306这样极少数安全性要求高的网站
2)第一个token由登录签发
3)之后的所有正常逻辑,都需要发送两次请求,第一次是刷新token的请求,第二次是正常逻辑的请求
"""

settings.py

import datetime

JWT_AUTH = {
    # 配置过期时间
    'JWT_EXPIRATION_DELTA': datetime.timedelta(minutes=5),

    # 是否可刷新
    'JWT_ALLOW_REFRESH': True,
    # 刷新过期时间
    'JWT_REFRESH_EXPIRATION_DELTA': datetime.timedelta(days=7),
}

urls.py

from rest_framework_jwt.views import ObtainJSONWebToken, RefreshJSONWebToken
urlpatterns = [
    url('^login/$', ObtainJSONWebToken.as_view()),  # 登录签发token接口
    url('^refresh/$', RefreshJSONWebToken.as_view()),  # 刷新toekn接口
]

postman

# 接口:/api/refresh/
# 方法:post
# 数据:{"token": "登录签发的token"}

以上是关于jwt 认证的主要内容,如果未能解决你的问题,请参考以下文章

webapi JWT 认证

JWT 认证成功,但是邮递员返回 404

重学SpringCloud系列八之微服务网关安全认证-JWT篇

对JWT认证流程的误解

调用 API 时使用 JWT 承载认证

Spring cloud微服务安全实战-6-2JWT认证之认证服务改造