In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-02-27 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/03 Report--
This article introduces the "django drf framework how to achieve user verification and the composition of JWT" related knowledge, in the actual case of the operation process, many people will encounter such a dilemma, then let the editor lead you to learn how to deal with these situations! I hope you can read it carefully and be able to achieve something!
Login registration is the interface that almost all websites need to do, and when it comes to login, it naturally involves authentication and the preservation of user login status. Recently, in a project on online shopping malls done with DRF, an extended DRF JWT was introduced, which is specifically used for authentication and user status preservation. This extension is more secure than traditional CSRF. Let's first introduce the JWT authentication mechanism.
Json web token (JWT) is an open standard based on JSON (RFC 7519) for passing declarations between network application environments. The token is designed to be compact and secure and is particularly suitable for single sign-on (SSO) scenarios at distributed sites. The declaration of JWT is generally used to transfer authenticated user identity information between the identity provider and the service provider in order to obtain resources from the resource server, and can also add some additional declaration information necessary for other business logic. The token can also be directly used for authentication or can be encrypted.
Authentication Mechanism based on token
Token-based authentication mechanism is similar to http protocol is also stateless, it does not need to retain the user's authentication information or session information on the server. This means that applications based on token authentication mechanism do not need to consider which server the user has logged in, which facilitates the expansion of the application.
The process goes like this:
The user uses the username and password to request the server
The server verifies the information of the user
The server sends a token to the user through authentication
The client stores the token and attaches this token value to each request
The server validates the token value and returns data
This token must be passed to the server on each request, and it should be stored in the request header. In addition, the server should support the CORS (cross-source resource sharing) policy, which is generally fine with Access-Control-Allow-Origin: * on the server.
So let's get back to the theme of JWT.
The composition of JWT
The first part we call it the head (header), the second part we call it the payload (similar to the objects carried on the plane), and the third part is the signature.
The header of jwt carries two pieces of information: 1, declare the type, here is jwt,2 declares that the encryption algorithm usually uses HMAC SHA256 directly. The complete head looks like the following JSON:
{'typ':' JWT', 'alg':' HS256'}
The header is then encrypted with base64 (the encryption can be decrypted symmetrically), forming the first part.
Such as eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.
Load is the place where valid information is stored. The name seems to refer specifically to the goods carried on the aircraft, and this valid information contains three part 1 standard registered statements, 2 public statements, and 3 private statements. Statement registered in the standard (recommended but not mandatory): 1 iss: jwt issuer, 2 sub: the user for jwt, 3 aud: the party receiving the jwt, 4 exp: the expiration time of the jwt, this expiration time must be greater than the issuance time, 5 nbf: defines the time before which the jwt is not available, 6 iat: jwt issuance time, 7 jti: jwt unique identity It is mainly used as an one-time token to avoid replay attacks. Public statement: public statement can add any information, generally add user-related information or other necessary information needed by the business. However, it is not recommended to add sensitive information because this part can be decrypted on the client side. Private declaration: a private declaration is a declaration defined by both providers and consumers. It is generally not recommended to store sensitive information, because base64 is symmetrically decrypted, which means that this part of the information can be classified as plaintext. Define a payload:
{"sub": "1234567890", "name": "John Doe", "admin": true}
Then encrypt it with base64 to get the second part of the JWT.
Such as eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.
The third part of JWT is a visa information, which consists of three parts: 1 header (after base64), 2 payload (after base64), and 3 secret. This part requires the use of base64 encrypted header and base64 encrypted payload. Concatenate the string, then add salt secret combination encryption through the encryption declared in header, and then form the third part of the jwt.
Note: secret is stored on the server side, and the signing and generation of jwt is also on the server side. Secret is used for jwt signing and jwt verification, so it is your server's private key and should not be revealed in any scenario. Once the client knows about the secret, it means that the client can sign the jwt itself.
You first need to install the extension pip install djangorestframework-jwt, then configure it in django, and JWT_EXPIRATION_DELTA indicates the validity period of the token.
REST_FRAMEWORK = {'DEFAULT_AUTHENTICATION_CLASSES': (' rest_framework_jwt.authentication.JSONWebTokenAuthentication', 'rest_framework.authentication.SessionAuthentication',' rest_framework.authentication.BasicAuthentication',),} JWT_AUTH = {'JWT_EXPIRATION_DELTA': datetime.timedelta (days=1),}
The method of manually issuing JWT is provided in the documentation for the Django REST framework JWT extension
From rest_framework_jwt.settings import api_settingsjwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLERjwt_encode_handler = api_settings.JWT_ENCODE_HANDLERpayload = jwt_payload_handler (user) token = jwt_encode_handler (payload)
When registering, introduce the above code and issue JWT. For login, the JWT extension provides a built-in view that can be added to urls for routing.
From rest_framework_jwt.views import obtain_jwt_tokenurlpatterns = [url (r'^ authorizations/$', obtain_jwt_token),]
Although it is easy to write, a lot of things have been done internally. Today, let's take a closer look at what has been done inside the source code.
When the user logs in, he sends a request to the backend in the form of post, and visits the post method in obtain_jwt_token. You can see obtain_jwt_token = ObtainJSONWebToken.as_view () in the source code, which is very similar to the class view we wrote. This is a class view that has been written internally.
Class ObtainJSONWebToken (JSONWebTokenAPIView): "APIView that receives a POST with a user's username and password. Returns a JSONWebToken that can be used for authenticated requests." Serializer_class = JSONWebTokenSerializer
There are no methods defined in this class, so the corresponding post method should be written in the parent class. Here is the post method in the parent class.
Def post (self, request, * args, * * kwargs): serializer = self.get_serializer (data=request.data) if serializer.is_valid (): user = serializer.object.get ('user') or request.user token = serializer.object.get (' token') response_data = jwt_response_payload_handler (token, user) Request) response = Response (response_data) if api_settings.JWT_AUTH_COOKIE: expiration = (datetime.utcnow () + api_settings.JWT_EXPIRATION_DELTA) response.set_cookie (api_settings.JWT_AUTH_COOKIE, token, expires=expiration, httponly=True) return response return Response (serializer.errors, status=status.HTTP_400_BAD_REQUEST)
The above method returns a Response object, which is returned to the front end after a series of operations, and the access ends.
In the DRF framework, the corresponding validation operation is performed before the view is invoked. To understand the whole process, we need to explore step by step from the source code. When the current side initiates a request to the backend, it routes to the as_view () method of the view class of the object, which in turn calls the dispatch () method, whose dispatch method APIView is the parent of all view classes in DRF.
Def dispatch (self, request, * args, * * kwargs): "`.dispatch () `is pretty much the same as Django's regular dispatch, but with extra hooks for startup, finalize, and exception handling." Self.args = args self.kwargs = kwargs request = self.initialize_request (request, * args, * * kwargs) self.request = request self.headers = self.default_response_headers # deprecate? Try: self.initial (request, * args, * * kwargs) # Get the appropriate handler method if request.method.lower () in self.http_method_names: handler = getattr (self, request.method.lower (), self.http_method_not_allowed) else: handler = self.http_method_not_allowed response = handler (request, * args * * kwargs) except Exception as exc: response = self.handle_exception (exc) self.response = self.finalize_response (request, response, * args, * * kwargs) return self.response
As you can see, when the request comes in, the self.initalize_request () method is called to process the request.
Def initialize_request (self, request, * args, * * kwargs): "Returns the initial request object." Parser_context= self.get_parser_context (request) return Request (request, parsers=self.get_parsers (), authenticators=self.get_authenticators (), negotiator=self.get_content_negotiator (), parser_context=parser_context)
The only thing we need to focus on is authenticators=self.get_authenticators ().
Def get_authenticators (self): "Instantiates and returns the list of authenticators that this view can use." Return [auth () for auth in self.authentication_classes]
Then, if you look up, you can see the class attribute permission_classes = api_settings.DEFAULT_PERMISSION_CLASSES, which is why we want to add the DEFAULT_PERMISSION_CLASSES configuration to the DEFAULT_PERMISSION_CLASSES configuration. The above method will traverse the list we wrote in the configuration, get the validation class inside, instantiate it, and install the generated object in a new list and save it in the newly generated Request object. Then we go on to look at the dispatch method, and before actually calling the corresponding method in the view class, we call the self.initial () method to do some initialization.
Def initial (self, request, * args, * * kwargs): "Runs anything that needs to occur prior to calling the method handler." Self.format_kwarg = self.get_format_suffix (* * kwargs) # Perform content negotiation and store the accepted info on the request neg = self.perform_content_negotiation (request) request.accepted_renderer, request.accepted_media_type = neg # Determine the API version, if versioning is in use. Version, scheme = self.determine_version (request, * args, * * kwargs) request.version, request.versioning_scheme = version, scheme # Ensure that the incoming request is permitted self.perform_authentication (request) self.check_permissions (request) self.check_throttles (request)
What we need to focus on is the last three rows, where three methods are called for authentication, permission verification and diversion operations. here we only focus on the authentication method, self.perform_authentication (), which has only one line of code request.user, which looks like calling the user property of the request object, but in fact, we can find the following method in the Request object of the DRF framework.
@ property def user (self): "Returns the user associated with the current request, as authenticated by the authentication classes provided to the request." If not hasattr (self,'_ user'): with wrap_attributeerrors (): self._authenticate () return self._user
After the user method is decorated by the property decorator, you can call the method like an attribute. The method will return directly when there is a corresponding user in the Request object. If the user logs in, there is no corresponding user in the Request object, so the code will go inside the if judgment, and we only need to pay attention to the call to the method self._authenticate ().
Def _ authenticate (self): "Attempt to authenticate the request using each authentication instance in turn." For authenticator in self.authenticators: try: user_auth_tuple = authenticator.authenticate (self) except exceptions.APIException: self._not_authenticated () raise if user_auth_tuple is not None: self._authenticator = authenticator self.user, self.auth = user_auth_tuple return self._not_authenticated ()
As you can see, this method traverses the list of validation class objects passed in when we were dealing with the Request object, and calls the authenticate () method of the validation class. If the verification successfully generates the corresponding self.user and self.auth and directly return, the generated self.user is returned directly up. If there is an internal error in the verification, self._not_ authenticated () is called and an error is thrown. Looking up, in the dispatch method If there is an error in the initialization method, the capture is made, and the self.handle_exception () method is called to generate a Response object for return. The corresponding method in the view class is not executed, then the call is for self._not_authenticated ().
Def _ not_authenticated (self): "Set authenticator, user & authtoken representing an unauthenticated request. Defaults are None, AnonymousUser & None." Self._authenticator = None if api_settings.UNAUTHENTICATED_USER: self.user = api_settings.UNAUTHENTICATED_USER () else: self.user = None if api_settings.UNAUTHENTICATED_TOKEN: self.auth = api_settings.UNAUTHENTICATED_TOKEN () else: self.auth = None
UNAUTHENTICATED_USER is an anonymous user class in the default configuration of django, and UNAUTHENTICATED_ token defaults to None. If all authentication is passed or there is an error in a verification process, an anonymous user is generated and self.auth is set to None.
To sum up, before the request is executed, the DRF framework authenticates the user according to the authentication class we configured in the configuration file. If the authentication fails, an anonymous user is generated. If the authentication passes, the corresponding user is generated.
This is the end of the content of "how the django drf framework implements user verification and the composition of JWT". Thank you for reading. If you want to know more about the industry, you can follow the website, the editor will output more high-quality practical articles for you!
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.