Middleware Application

Middleware Application

Implement login authentication

We continue to improve the voting application. In the last chapter, we successfully passed the session after the user logs retain user information, then we can use to make some adjustments, requirements must first log in when voting for teachers, logged in users can vote, otherwise the user will guide to the login page, for which we can modify the view function.

def praise_or_criticize(request: HttpRequest):
    """投票"""
    if 'username' in request.session:
        try:
            tno = int(request.GET.get('tno', '0'))
            teacher = Teacher.objects.get(no=tno)
            if request.path.startswith('/praise'):
                teacher.good_count += 1
            else:
                teacher.bad_count += 1
            teacher.save()
            data = {'code': 200, 'message': '操作成功'}
        except (ValueError, Teacher.DoesNotExist):
            data = {'code': 404, 'message': '操作失败'}
    else:
        data = {'code': 401, 'message': '请先登录'}
    return JsonResponse(data)

In front page is received {'code': 401, 'message': '请先登录'}, the user may be directed to the login page, as shown in the modified page JavaScript code division teacher.html follows.

<script>
    $(() => {
        $('.comment > a').on('click', (evt) => {
            evt.preventDefault()
            let a = $(evt.target)
            $.getJSON(a.attr('href'), (json) => {
                if (json.code == 200) {
                    let span = a.next()
                    span.text(parseInt(span.text()) + 1)
                } else if (json.code == 401) {
                    location.href = '/login/?backurl=' + location.href
                } else {
                    alert(json.message)
                }
            })
        })
    })
</script>

Note: In order to be able to return after a successful login page just to vote, we set up a jump in the login backurlparameters, the current browser page URL as the return address.

We have implemented a user must be logged in to limit the voting, but a new problem came. If our application has many features require users to log in to perform, such as export front Excel reports and viewing charts are to be logon restrictions, we are not required to add code in each view function to check the session whether to include the information logged-in users do? The answer is no, if you do, we view the function will inevitably filled with a lot of duplicate code. Programming guru Martin Fowler once said: Code There are many bad taste, repetition is the worst kind . In Django project, we can verify that a user is logged so repetitive code into middleware.

Django Middleware Overview

Middleware is inserted between the Web application request and response process component that plays the role of interceptor filter throughout the Web applications through the middleware can intercept requests and responses, and request and response filter (Briefly It is to perform additional processing). Typically, a middleware component only focus on the completion of a specific thing, such as: Django framework through SessionMiddlewareimplemented support for session middleware, but also by AuthenticationMiddlewaremiddleware based session authentication request. By multiple middleware together, we can do more complex tasks, Django framework did.

Django project configuration file contains the configuration of the middleware, as shown in the following code.

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

Our little as we explain the role of these Middleware:

  1. CommonMiddleware - basic settings middleware can process some of the following configuration parameters.
    • DISALLOWED_USER_AGENTS - not allowed user agent (browser)
    • APPEND_SLASH - whether additional/
    • USE_ETAG - browser cache related
  2. SecurityMiddleware - safety-related middleware, and can handle security-related configuration items.
    • SECURE_HSTS_SECONDS - force the use of HTTPS time
    • SECURE_HSTS_INCLUDE_SUBDOMAINS - whether HTTPS covered subdomain
    • SECURE_CONTENT_TYPE_NOSNIFF - whether to allow the browser to infer content type
    • SECURE_BROWSER_XSS_FILTER - whether to enable cross-site scripting filter
    • SECURE_SSL_REDIRECT - whether to redirect to HTTPS connection
    • SECURE_REDIRECT_EXEMPT - exempt redirected to HTTPS
  3. SessionMiddleware - session middleware.
  4. CsrfViewMiddleware - by generating a token, a request to prevent cross-making parts of the dummy middleware.
  5. XFrameOptionsMiddleware - Middleware request header by setting parameters to prevent clickjacking attacks.

In the process of the request, the middleware above from top to bottom will be performed in the order written, then parsing the URL, the request will finally come to view function; the process response, the middleware in the order in the above written performed from bottom to top, and sequentially executing the middleware request opposite.

Custom Middleware

Django middleware in two ways: based implementation of the class and the function-based implementation, which is closer to the wording decorator. Decorator is actually an application proxy mode, crosscutting concerns function (normal business logic is not necessarily related functions, such as: authentication, logging, transcoding functions like) placed in proxy to the proxy object complete the proxy object's behavior and add extra functionality. Middleware to intercept user requests and responses and additional filtration process, at this point it is entirely consistent with the decorator, so based on the wording of the middleware functions to realize just writing a decorator's almost exactly the same. Here we use a custom middleware to implement user login authentication function.

"""
middlewares.py
"""
from django.http import JsonResponse
from django.shortcuts import redirect

# 需要登录才能访问的资源路径
LOGIN_REQUIRED_URLS = {
    '/praise/', '/criticize/', '/excel/', '/teachers_data/',
}


def check_login_middleware(get_resp):

    def wrapper(request, *args, **kwargs):
        # 请求的资源路径在上面的集合中
        if request.path in LOGIN_REQUIRED_URLS:
            # 会话中包含userid则视为已经登录
            if 'userid' not in request.session:
                # 判断是不是Ajax请求
                if request.is_ajax():
                    # Ajax请求返回JSON数据提示用户登录
                    return JsonResponse({'code': 10003, 'hint': '请先登录'})
                else:
                    backurl = request.get_full_path()
                    # 非Ajax请求直接重定向到登录页
                    return redirect(f'/login/?backurl={backurl}')
        return get_resp(request, *args, **kwargs)

    return wrapper

Modify the configuration file, activate the middleware to take effect.

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
    'debug_toolbar.middleware.DebugToolbarMiddleware',
    'vote.middlewares.check_login_middleware',
]

Note that the upper intermediate element in order of the list, when receiving a request from a user, the middleware sequentially performed in the order from top to bottom, after completion of these intermediate line, will request a final view function. Of course, in the process, the user's request can be intercepted, just above our custom middleware as if the user is not logged in the case of access to the protected resources, the middleware will be redirected to the login request directly page, middleware and rear view function will not be executed. In the process in response to user requests, the above middleware are executed in the order from bottom to top, so that we can respond to further processing.

Middleware order execution is very important, for there are dependencies middleware must be relied upon to ensure that middleware depend on it to be placed in front of middleware, middleware like we have just a custom to put SessionMiddlewareback, because we have to rely on this middleware request binding sessiontarget to determine whether the user is logged in.

summary

The complete code for the entire project, please refer https://github.com/jackfrued/django1902

Guess you like

Origin www.cnblogs.com/python001-vip/p/12606872.html