Small knowledge, big challenge! This paper is participating in theEssentials for programmers”Creative activities

Python modifiers for JWT validation feel very elegant, this blog will show you how to use Python modifiers to add permission group validation JWT for flask.

First, we need a token generation function to write the user ID into the token. In the subsequent parsing, the identity can be determined by the stored user ID:

def generate_token(user, expiration=864000) :
    The default expiration date is 10 days
    s = Serializer(SECRET_KEY, expires_in=expiration)   # expiration is 3600: 1 hour
    token = s.dumps({'id': user.id}).decode('utf-8')
    return token
Copy the code

Simple login authentication

def login_required(func) :
    @functools.wraps(func)
    def wrapper(*args, **kwags) :
        token = request.headers["Authorization"].split()[-1]
        s = Serializer(SECRET_KEY)
        try:
            user_id = s.loads(token)["id"]
            if not users.find_by_id(user_id):
                User does not exist, return 404
                return make_resp({"error_msg": "User does not exist"}, code=404)
        except SignatureExpired:
            # token is correct but expired
            return make_resp({"error_msg": "The token expired"}, code=50001)
        except BadSignature:
            # token error
            return make_resp({"error_msg": "Token error"}, code=50000)
        return func(user, *args, **kwags)
    return wrapper
Copy the code

writelogin_requiredIf the token is incorrect or expired, the corresponding error code is returned. Otherwise, the User object is returned to facilitate subsequent operations. The method of use is as followsviewWe need to add a variable to store the parameter:

Second, further expand the function of the permission group

def login_required(*auths_need) :
    def decorator(func) :
        @functools.wraps(func)
        def wrapper(*args, **kwags) :
            try:
                Get token on request head
                token = request.headers["Authorization"]
            except Exception as e:
                Token not received, throws an error to the front end
                return serialization.make_resp("", code=400)
            token = token.split()[-1]
            s = Serializer(SECRET_KEY)
            try:
                user_id = s.loads(token)["id"]
                user = users.find_by_id(user_id)
                if not user:
                    """ User does not exist """
                    return serialization.make_resp({"error_msg": "User does not exist"}, code=404)
                if auths_need:
                    Access token permission list if in argument list, no permission otherwise.
                    if not [auth.name for auth in user.auths if auth.name in auths_need]:
                        # If the intersection is empty, the permission is insufficient
                        return serialization.make_resp({"error_msg": "Insufficient authority"}, code=401)
            except SignatureExpired:
                Token correct but expired
                return serialization.make_resp({"error_msg": "The token expired"}, code=50001)
            except BadSignature:
                "' token error" '
                return serialization.make_resp({"error_msg": "Token error"}, code=50000)
            return func(user, *args, **kwags)
        return wrapper
    return decorator
Copy the code

The operation is similar to the above, but you can see that there is an extra step of authentication. Read the intersection between the user’s permission group and the entered permission list. If the intersection is not empty, the user can pass the authentication.

Its use method is as follows:

@admin.route("/students/upload", methods=['POST'])
@login_required("SuperAdmin"."Admin")
def students_upload() :
Copy the code

In this way, users with permissions including SuperAdmin or Admin can pass permission authentication to achieve access.