Introduce JWT to modify the registration interface

review

Remember when we wrote a Register interface? But it’s just an empty shell that returns a “registered successfully” response body.

This can not help but remind me of the past in a Courier website, click ** “reminder” ** button, the other side directly pop-up reminder of success alert. But I opened his HTML code, found that as long as click this button will pop up a prompt, no interaction of any back end, HERE I will not name this Yunda express ha. Can only really show ~

Knowledge to prepare

  • The cookie and session

    Traditional Web software needs to store user login information. Cookies and sessions are the more common, and certainly older, patterns. The cookie mainly depends on the client, which can be simply said to be the browser. You can say that the user’s login information is stored in the browser’s localstorage. A session, as the name suggests, stores the user on the server. For a better explanation, please baidu.

  • token

    Token means token in a broad sense. This is short for JSON Web Token (JWT). Simply put, it’s a way of storing user information (encoded in Base64) and then parsing it as needed. This allows you, the user, to store all of your information as a string and not see the content. Those who are interested can go and have a look at ~~

In Python JWT

JWT comes with Python, so let’s familiarize ourselves with the methods.

I’ll start with my implementation for pity/middleware/ jwt.py

import hashlib from datetime import timedelta, datetime import jwt from jwt.exceptions import ExpiredSignatureError EXPIRED_HOUR = 3 class UserToken(object): key = 'pityToken' salt = 'pity' @staticmethod def get_token(data): new_data = dict({"exp": datetime.utcnow() + timedelta(hours=EXPIRED_HOUR)}, **data) return jwt.encode(new_data, key=UserToken.key).decode() @staticmethod def parse_token(token): try: return jwt.decode(token, key=UserToken.key) except ExpiredSignatureError: Raise Exception(" Token has expired, please log in again ") @staticMethod def add_salt(password): m = hashlib.md5() m.update(password + UserToken.salt) return m.hexdigest()Copy the code

The UserToken class has three methods. The first method condenses user information into a string with an expiration time of three hours.

The second is to parse the token to the previous user information.

The second method, add_salt, is used to store the user’s password in md5 code. If an evil force gets hold of the database password, it will not expose the user’s password. Add_salt means to add salt. So it’s relatively safe.

Writing the core method

If you think about it, the first step for our users to sign up is to determine if the account is already registered. Ok, so let’s write the first method: register_user.

Let’s create a new dao/auth/ userdao.py

from sqlalchemy import or_ from app.middleware.Jwt import UserToken from app.models import db from app.models.user import User from app.utils.logger import Log class UserDao(object): log = Log("UserDao") @staticmethod def register_user(username, name, password, email): """ :param username: Username :param Name: Name :param password: Password :param Email: Email :return: "" try: users = User.query.filter(or_(User.username == username, User.email == email)).all() if users is not None: PWD = usertoken.add_salt (password) user = user (username, name, PWD, Email) db.session.add(user) db.session.com MIT () except Exception as e: userdao.log.error (f" user registration failed: {str(e)}") return str(e) return NoneCopy the code

Note that the line user.query.filter means to find all users whose username or email already exists and throw an exception if they do, or insert the line directly through the ORM if they do not.

In the world of ORM, would it be clearer to understand that the user object we instantiate is a row of data in a table?

Retrofit registration interface

You can see that this method is very empty, so what do we need to do.

First we need to accept the username/password/email and other registration information coming in, do some critical validation of the parameters, and then call the core method. If nothing goes wrong, our login method is written

Calibration parameters

Flask gets the incoming JSON data directly from request.get_json() and returns a dict object.

PS: This is ugly, for the time being ** “endure” **, we will change later.

Introducing core methods

If err is not null, return code=110, which means an alarm has been reported.

Code =101 is a parameter error, 110 is an exception error, and 0 is a normal return.

Note, this is not an official rule, it is my whim haha, will follow this agreement in the future.

Complete code:

So let’s just test this

Start the service

As you can see, there’s a circular reference problem, because we’ve introduced the controller in app/init.py, we’ve introduced the model in controller, and we’ve introduced the pity object in app/init.py in Model, so there’s a circular reference.

The solution is simple: let’s put the dirty work of registering blueprints into run.py, which is the outermost layer where nobody introduced run.py.

Modified app/init.py:

from flask import Flask

from config import Config

pity = Flask(__name__)


pity.config.from_object(Config)


Copy the code

run.py:

from datetime import datetime from app import pity from app.utils.logger import Log from app.controllers.auth.user Import auth # register blueprint pity. Register_blueprint (auth) @pity. Route ('/') def hello_world(): Log = log ("hello world") log.info(" hello world") now = datetime.now().strftime("%Y-%M-%d %H:%M:%S") print(now) return now If __name__ = = "__main__" : pity. Run (" 0.0.0.0 ", implementing = True, the port = "7777")Copy the code

Open Up Postman to test:

Something wrong happened again, so angry! The 405HTTP method is not allowed, so find the interface we wrote:

It turns out that there is a problem here. Let’s change the request mode to POST.

Restart the service try again

We have not registered this user, but this is prompted. First, let’s check the database:

We find that the database is ok, so we use the big trick, break therapy:

Click here and a small red circle will appear. Ask again:

We need to change our validation to return an empty array instead of None:

Restart and try again:

I can see this, this must be the MD5 block problem, find out the reason carefully.

(Too special so confident, leading to the previous picture too lazy to change, can only write while modifying, later will not be such live write, write a good direct on the code can be.)

Unicode must hash into bytes. This is a big deal:

Restart and try again:

That’s not easy. Let’s check the database:

Got it. It’s not in clear text either

Check for duplicate registrations (request again)

Time is late, this is all for today’s content, closing time, crazy write bug!!

Back-end code address: github.com/wuranxu/pit…

Front-end code address: github.com/wuranxu/pit…

“If you think it’s useful, you can help to order a Star oh QAQ.”

This article uses the Article Synchronization Assistant to synchronize