JWT frequency module and

JWT

jwt basic introduction

Full name: json web token

As technology advances, the popularity of distributed web applications, users logged in through the session management costs higher and higher, so slowly developed into a token way to do login identity verification, then redis the cached user token to get through information, after jwt with the emergence of a more simple and convenient way of checking, without going through redis cache, but directly out token stored user information, as well as token check availability, single sign-on based on simpler.

token format

Three stages - the first payload signatures - Head and payload encryption uses a reversible base64, MD5 signature using the irreversible encryption

token content

Head (basic information, can also be empty): encryption, company information, team information, ...
payload (core information): user information, expiration date, ...
signature (security): Head encryption results results + + MD5 encrypted payload server secret key encryption result

Security

Security depends mainly on the part of that signature, such as Django server key is the only security

Certification rules

Background must protect the security of the server secret key (it is the only security jwt's)
background issuance of token -> Front storage -> Send a request that requires authentication with a token -> background check to get a legitimate user

Use jwt

Authentication modules package, log in successfully returns the encrypted token, there parsing token functionality

First install jwt.

pip install djangorestframework-jwt

jwt three main functions

Three views interfaces

jwt default implementation of the function is too simple, it is generally not directly interface to provide him with a view

url(r'^login1/$', obtain_jwt_token),

#签发token,接收username和password
obtain_jwt_token = ObtainJSONWebToken.as_view()

#校验token,验证token,对的原样返回,错的报错
refresh_jwt_token = RefreshJSONWebToken.as_view()

#刷新token,使用要配置'JWT_ALLOW_REFRESH': False,允许刷新为True,token过期,刷新为有效时间
verify_jwt_token = VerifyJSONWebToken.as_view()

jwt Configuration

JWT_AUTH = {
    'JWT_EXPIRATION_DELTA': datetime.timedelta(days=7),

    # 'JWT_ALLOW_REFRESH': True,
    # 'JWT_REFRESH_EXPIRATION_DELTA': datetime.timedelta(days=7),

    'JWT_AUTH_HEADER_PREFIX': 'JWT',
}

Token issuance process

user-->jwt_payload_handler-->payload-->jwt_encode_handler-->token

#全局钩子,登录之后在序列化类里面做校验的时候就直接签发token。
   def validate(self, attrs):
        user = authenticate(**attrs)
        if not user:
            raise ValidationError({'user':'信息有误'})
        payload = jwt_payload_handler(user)
        token = jwt_encode_handler(payload)

        self.user = user
        self.token = token

        return attrs

jwt global certification

# drf的配置
REST_FRAMEWORK = {
    # 异常模块
    'EXCEPTION_HANDLER': 'utils.exception.exception_handler',

    # 认证模块
    'DEFAULT_AUTHENTICATION_CLASSES': [
        # jwt认证类
        'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
    ],
    # 权限模块
    'DEFAULT_PERMISSION_CLASSES': [
        # 'rest_framework.permissions.IsAuthenticated',
        # 自定义权限类
    ],
    # 频率设置
    'DEFAULT_THROTTLE_RATES': {
        'three': '3/min',
    },
}

# 修改auth模块的用户表指向
AUTH_USER_MODEL = 'api.User'


# drf-jwt配置
import datetime
JWT_AUTH = {
    'JWT_EXPIRATION_DELTA': datetime.timedelta(days=7),

    # 'JWT_ALLOW_REFRESH': True,
    # 'JWT_REFRESH_EXPIRATION_DELTA': datetime.timedelta(days=7),

    'JWT_AUTH_HEADER_PREFIX': 'JWT',
}

Multiple logins

class LoginAPIView(APIView):
    authentication_classes = []
    permission_classes = []
    def post(self, request, *args, **kwargs):
        serializer = serializers.LoginSerializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        return APIResponse(msg='login success', data={
            'username': serializer.user.username,
            'token': serializer.token
        })

serializers:

from rest_framework_jwt.serializers import jwt_payload_handler, jwt_encode_handler
class LoginSerializer(ModelSerializer):
    username = CharField(write_only=True)
    password = CharField(write_only=True)
    class Meta:
        model = models.User
        fields = ('username', 'password')

    # 在全局钩子中签发token
    def validate(self, attrs):
        # user = authenticate(**attrs)
        # 账号密码登录 => 多方式登录
        user = self._many_method_login(**attrs)

        # 签发token,并将user和token存放到序列化对象中
        payload = jwt_payload_handler(user)
        token = jwt_encode_handler(payload)

        self.user = user
        self.token = token

        return attrs

    # 多方式登录
    def _many_method_login(self, **attrs):
        username = attrs.get('username')
        password = attrs.get('password')
        if re.match(r'.*@.*', username):
            user = models.User.objects.filter(email=username).first()  # type: models.User

        elif re.match(r'^1[3-9][0-9]{9}$', username):
            user = models.User.objects.filter(mobile=username).first()
        else:
            user = models.User.objects.filter(username=username).first()

        if not user:
            raise ValidationError({'username': '账号有误'})

        if not user.check_password(password):
            raise ValidationError({'password': '密码有误'})

        return user

Overview about jwt

The code is three, a payload, a token, a configuration settings

Him to help you complete user authentication, so you only write access to certification and certification of the three frequency certification. You only need to do is to use jwt the token is generated, and then placed in user's name space, verification token, it is done by jwt part of your configured settings inside.

Frequency Module

Custom class complete frequency limit frequency view class
1) defined class inheritance SimpleRateThrottle, get_cache_key override method, scope class attribute set
2) is a scope authentication string, the string corresponding to the configuration scope frequency setting in the configuration file
3) get_cache_key the return value is a string, the string is a cache access frequency and cache key

In settings where drf configuration write this

'DEFAULT_THROTTLE_RATES': {
        'three': '3/min',
    },

To customize the view class defined frequency

from rest_framework.permissions import IsAuthenticated
from utils.throttles import ThreeTimeUserThrottle
class UserCenterAPIView(APIView):
    # 认证全局配置吗,权限局部配置,认证已经交给jwt了
    # authentication_classes = []
    permission_classes = [IsAuthenticated]
    # 频率模块局部配置
    throttle_classes = [ThreeTimeUserThrottle]

    def get(self, request, *args, **kwargs):
        user = request.user
        serializer = serializers.UserModelSerializer(user)
        return APIResponse(data=serializer.data)

throttles

# 自定义频率类
from rest_framework.throttling import SimpleRateThrottle
# 1)定义类继承SimpleRateThrottle,重写get_cache_key方法,设置scope类属性
# 2)scope就是一个认证字符串,在配置文件中配置scope字符串对应的频率设置
# 3)get_cache_key的返回值是字符串,该字符串是缓存访问次数的缓存key
class ThreeTimeUserThrottle(SimpleRateThrottle):
    #这里的scope要和settings里面的key对上。
    scope = 'three'
    # 当前用户缓存的key,这个方法的返回值是一个能够唯一标识用户的信息,如果name是唯一的,用name也行,总之它会认得这个字符串,知道下次进来的人是不是你。如果返回的字符串每次都是同样的,那么你所有用户登录就共用一个频率了。
    def get_cache_key(self, request, view):
        return 'throttle:user_%s' % (request.user.id)

Guess you like

Origin www.cnblogs.com/chanyuli/p/11966208.html
jwt