Why is user authentication required when the front and back ends are separated for development? The reason is that the HTTP protocol does not store state (stateless), which means that when we authenticate a user through the account password, it will forget the data just before the next request. So our program doesn't know who is who, so we have to verify it again. So in order to ensure system security, we need to verify whether the user is logged in.
1. Traditional way
How to verify the user's login information and permissions when the front and back ends are separated for data interaction through Restful API. In the original project, the most traditional and simple way is used. The front-end login, the back-end generates a token based on user information, saves the token and the corresponding user id in the database or session, and then passes the token to the user , Save it in the browser cookie, and then the browser requests to bring this cookie, and the backend queries the user based on the cookie value to verify whether it has expired.
But there are many problems with this. If our page has XSS vulnerabilities, because cookies can be read by JavaScript, XSS vulnerabilities will cause the user token to be leaked, and as a backend to identify the user's identity, the leak of the cookie means that user information is no longer Safety. Although we can avoid XSS injection by escaping the output content and using CDN, etc., no one can guarantee that this problem will not occur in large projects.
When setting cookies, you can actually set httpOnly and secure items. After setting httpOnly, the cookie cannot be read by JS, and the browser will automatically add it to the request header. If secure is set, the cookie will only be transmitted via HTTPS. The secure option can filter out some XSS injections that use the HTTP protocol, but it cannot completely prevent it.
The httpOnly option makes JS unable to read the cookie, so there is basically no need to worry about XSS injection. But setting httpOnly brings another problem, that is, it can be easily forged by XSRF, that is, cross-site request. When you open this page in your browser, another page can easily request the content of this page across sites. Because the cookie is sent out by default.
In addition, if the verification information is stored in the database, the backend needs to find out the user id based on the token every time, which increases the query and storage overhead of the database. If the authentication information is stored in the session, the storage pressure on the server side is increased. Then can we not query the server? If we generate tokens following certain rules, for example, we use a symmetric encryption algorithm to encrypt the user id to form a token, then the server can actually know what the user id is by decrypting the token. However, I just give an example. If you do this, as long as your symmetric encryption algorithm is leaked, and others can use this encryption method to forge tokens, then all user information is no longer safe. Well, use an asymmetric encryption algorithm to do it. In fact, there is a specification that does this, which is the JWT we will introduce next.
2. Json Web Token (JWT)
WT is an open standard (RFC 7519), which defines a concise, self-contained method for securely transmitting information in the form of JSON objects between communicating parties. JWT can be signed using HMAC algorithm or RSA public key key pair. It has two characteristics:
It can be sent through URL, POST parameters or in HTTP header, because the amount of data is small and the transmission speed is fast
The load contains the information required by all users, avoiding multiple queries to the database
JWT composition
Header
The header contains two parts, the token type and the encryption algorithm used
{" alg":"HS256","typ":"JWT"}
It uses Base64 encoding to form the first part of the JWT structure. If you use Node.js, you can use the Node.js package base64url to get this string.
———— Base64 is an encoding, that is, it can be translated back to its original appearance. It is not an encryption process.
Payload
The load is where the effective information is stored. This effective information consists of three parts:
—-Registration statement in the standard
---Public statement
---Private statement
**Public statement: **
The public statement can add any information, generally adding user related information or other necessary information required by the business. However, it is not recommended to add sensitive information, because this part can be decrypted on the client.
**Private statement: **
A private statement is a statement jointly defined by providers and consumers. It is generally not recommended to store sensitive information, because base64 is symmetrically decrypted, which means that this part of information can be classified as plaintext information
{" iss":"lion1ou JWT","iat":1441593502,"exp":1441594722,"aud":"www.example.com","sub":"[email protected]"}//Including user information that needs to be transmitted;{"iss":"Online JWT Builder","iat":1416797419,"exp":1448333419,"aud":"www.gusibi.com","sub":"uid","nickname":"goodspeed","username":"goodspeed","scopes":["admin","user"]}
Others include:
The first two parts are all encoded using Base64, that is, the front end can unlock and know the information inside. Signature needs to use the encoded header and payload and a key we provide, and then use the signature algorithm (HS256) specified in the header to sign. The function of the signature is to ensure that the JWT has not been tampered with.
//The signature string obtained by encrypting according to the alg algorithm and the private key;//This section is the most important sensitive information and can only be decrypted on the server side; HMACSHA256(base64UrlEncode(header)+"."+base64UrlEncode(payload),
SECREATE_KEY
)
The three parts are connected together to be our JWT. It may look like this. The length seems to be related to your encryption algorithm and private key.
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjU3ZmVmMTY0ZTU0YWY2NGZmYzUzZGJkNSIsInhzcmYiOiI0ZWE1YzUwOGE2NTY2ZTc2MjQwNTQzZjhmZWIwNmZkNDU3Nzc3YmUzOTU0OWM0MDE2NDM2YWZkYTY1ZDIzMzBlIiwiaWF0IjoxNDc2NDI3OTMzfQ.PA3QjeyZSUh7H0GfE0vJaKW4LjKJuC3dVLQiY4hii8s
In fact, at this point, some people may think that the HTTP request will always carry the token, so that the token will pass around and take up unnecessary bandwidth. If you think so, then you can learn about HTTP2, HTTP2 compresses the header, I believe it also solves this problem.
Purpose of signature
The last step of signing is actually signing the header and payload content to prevent the content from being tampered with. If someone modifies the content of the header and payload after decoding it, and then encodes it, and finally adds the previous signature combination to form a new JWT, then the server will determine that the signature formed by the new header and payload is attached to the JWT. The signature is different. If the new header and payload are to be signed, the signature obtained is also different without knowing the key used for server encryption.
Information disclosure
Everyone will definitely ask a question here: Base64 is a kind of encoding and is reversible, then my information will be exposed?
Yes. Therefore, in JWT, no sensitive data should be added to the load. In the above example, we are transmitting the User ID of the user. This value is not actually sensitive, and it is safe to be known under normal circumstances. But content like passwords cannot be placed in JWT. If you put the user's password in the JWT, a malicious third party can quickly know your password through Base64 decoding.
Therefore, JWT is suitable for delivering some non-sensitive information to Web applications. JWT is also often used to design user authentication and authorization systems, and even implement single sign-on for Web applications.
After the token is generated, the token can be used to communicate with the server.
Three, JWT use
The following figure shows the interaction process between the client and the server using JWT:
Here, after we get the JWT in the third step, we need to store the JWT in the client, and then send the JWT to every request that requires authentication. (You can put it in the Authorization of the header when requesting)
First, the front-end sends its username and password to the back-end interface through a web form. This process is generally an HTTP POST request. The recommended way is to use SSL encrypted transmission (https protocol) to prevent sensitive information from being sniffed.
After the backend successfully checks the user name and password, it uses the user's id and other information as the JWT Payload (payload), which is respectively Base64 encoded and spliced with the header to form a JWT. The resulting JWT is a string similar to lll.zzz.xxx.
The back end returns the JWT string as the result of successful login to the front end. The front end can save the returned results in localStorage or sessionStorage, and the front end can delete the saved JWT when logging out.
The front end puts the JWT into the Authorization bit in the HTTP Header every time it requests. (Solve XSS and XSRF issues)
The backend checks whether it exists, and if it exists, it verifies the validity of the JWT. For example, check whether the signature is correct; check whether the Token has expired; check whether the recipient of the Token is yourself (optional).
After the verification is passed, the backend uses the user information contained in the JWT to perform other logical operations and returns the corresponding results.
Four, JWT usage scenarios
The main advantage of WT is to handle user sessions in applications in a stateless and extensible way. The server can easily obtain the user's session information through the embedded declaration information, without the need to access the user or session database. This is very useful in a distributed service-oriented framework.
However, if the system needs to use a blacklist to implement a long-term effective token refresh mechanism, the advantage of this statelessness is not obvious.
advantage
Rapid development
No cookie needed
Wide application of JSON on mobile
Does not rely on social login
Relatively simple conceptual understanding
Disadvantage
Token has a length limit
Token cannot be revoked
Require token to have expiration time limit (exp)
Five, the difference between ID storage and Session mode
The biggest drawback of storing user IDs in the Session mode is that the Session is stored on the server side, so it takes up a lot of server memory, and for larger applications, a lot of state may be saved. Generally speaking, large-scale applications also need to use some KV databases and a series of caching mechanisms to implement Session storage.
The JWT method disperses the user state to the client, which can significantly reduce the memory pressure on the server. In addition to the user id, other user-related information can also be stored, such as whether the user is an administrator, the group where the user is located, and so on. Although the JWT method puts some computational pressure on the server (such as encryption, encoding, and decoding), these pressures may be nothing compared to disk storage. Whether to use it or not, you need to use data to speak in different scenarios.
sign in
The session method is used to store the user id. At the beginning, the user's session will only be stored on one server. For sites with multiple subdomains, each subdomain corresponds to at least one different server, for example: www.taobao.com, nv.taobao.com, nz.taobao.com, login.taobao.com. So if you want to realize that after logging in at login.taobao.com, you can still get Session under other subdomains, which requires us to synchronize Session on multiple servers. Using JWT does not have this problem, because the user's status has been transmitted to the client.
Six, summary
The main functions of JWT are:
(1) User information can be attached, and the back-end can obtain relevant information directly through JWT.
(2) Use local storage and submit for verification through the Authorization bit in HTTP Header.
Seven, additional, python uses JWT
To use jwt in the djagno rest framework in python, you can use the following module: githubs document has instructions for use
https://github.com/GetBlimp/django-rest-framework-jwt
pip install djangorestframework-jwt
Instead of using django, we can use pyjwt:
https://github.com/jpadilla/pyjwt/
It is more convenient to use, the following is an example I used in the application:
import jwt
import time
# Use sanic as a restful api framework
def create_token(request):
grant_type = request.json.get('grant_type')
username = request.json['username']
password = request.json['password']if grant_type =='password':
account =verify_password(username, password)
elif grant_type =='wxapp':
account =verify_wxapp(username, password)if not account:return{}
payload ={"iss":"gusibi.com","iat":int(time.time()),"exp":int(time.time())+86400*7,"aud":"www.gusibi.com","sub": account['_id'],"username": account['username'],"scopes":['open']}
token = jwt.encode(payload,'secret', algorithm='HS256')return True,{'access_token': token,'account_id': account['_id']}
def verify_bearer_token(token):
# If the aud parameter is used when generating the token, this parameter also needs to be added when verifying
payload = jwt.decode(token,'secret', audience='www.gusibi.com', algorithms=['HS256'])if payload:return True, token
return False, token
So far, this article on the implementation of JWT user authentication in python is introduced. For more related python JWT user authentication content, please search for ZaLou.Cn's previous articles or continue to browse the following related articles. Hope you will support ZaLou more in the future. Cn!
Recommended Posts