Flask 拦截器

登录实现后,有很多页面还没有进行设置登录要求,即使没有登录也可以到页面中来,当页面多了以后,每个页面都进行设置又非常繁琐,所以这里用到了 Flask 拦截器

相关资料源码来自编程浪子的Flask点餐小程序系统

web/interceptors/AuthInterceptor.py

import re

from application import app
from flask import request, redirect, g

from common.libs.LogService import LogService
from common.libs.user.UserService import UserService
from common.models.User import User
from common.libs.UrlManager import UrlManager


@app.before_request
def before_request():
    ignore_urls = app.config['IGNORE_URLS']
    ignore_check_login_urls = app.config['IGNORE_CHECK_LOGIN_URLS']
    path = request.path
    user_info = check_login()

    # 如果是静态文件就不要查询用户信息了
    pattern = re.compile('%s' % "|".join(ignore_check_login_urls))
    if pattern.match(path):
        return

    if '/api' in path:
        return

    user_info = check_login()
    g.current_user = None
    if user_info:
        g.current_user = user_info

    # 加入日志
    LogService.addAccessLog()
    pattern = re.compile('%s' % "|".join(ignore_urls))
    if pattern.match(path):
        return


    if not user_info:
        return redirect( UrlManager.buildUrl("/user/login"))

    return

'''
判断用户是否已经登录
'''

def check_login():
    cookies = request.cookies
    auth_cookie = cookies[app.configp['AUTH_COOKIE_NAME']] if app.config['AUTH_COOKIE_NAME'] in cookies else None

    if auth_cookie is None:
        return False
# 0 是授权码,  1是uid

    auth_info = auth_cookie.split('#')
    if len(auth_info) !=2:
        return False

    try:
        user_info = User.query.filter_by(uid=auth_info[1]).first()
    except Exception:
        return False

    if user_info is None:
        return False

    if auth_info[0] != UserService.geneAuthCode(user_info):
        return False

    if user_info.status != 1:
        return False

    return user_info

Config/base_setting.py设置无需拦截器拦截的url,防止login都被拦截了,出现死循环。

## 过滤url
IGNORE_URLS = [
    "^/user/login"
]

IGNORE_CHECK_LOGIN_URLS =[
    "^/static"
    "^/favicon.ico"
]

        这段代码是一个Python的Flask应用程序中的配置项。其中定义了两个列表变量IGNORE_URLSIGNORE_CHECK_LOGIN_URLS,用于配置需要忽略的URL路径。

IGNORE_URLS列表中的正则表达式定义了一些URL路径,这些路径在进行登录检查时会被忽略。例如,“^/user/login"表示以”/user/login"开头的路径将被忽略。

IGNORE_CHECK_LOGIN_URLS列表中的正则表达式定义了一些URL路径,这些路径在进行登录检查时也会被忽略。例如,“^/static"表示以”/static"开头的路径将被忽略。

        这些配置项的作用是在进行登录检查时,排除一些特定的URL路径,使其不受登录检查的限制。

问题1: ^的作用是什么?

正则表达式中,^符号的作用是匹配字符串的开头位置。在给定的代码中,^被用于定义忽略的URL模式。具体来说,IGNORE_URLS列表中的正则表达式会匹配以"/user/login"开头的URL,而IGNORE_CHECK_LOGIN_URLS列表中的正则表达式会匹配以"/static""/favicon.ico"开头的URL。这样,当用户访问这些URL时,系统会忽略对用户登录状态的检查

问题2:pattern = re.compile('%s' % "|".join(ignore_check_login_urls))

这段代码的作用是将ignore_check_login_urls列表中的元素用竖线|连接起来,并将结果作为参数传递给re.compile()函数,生成一个 正则表达式模式对象 。这个模式对象可以用于匹配path字符串 是否 符合 其中 任意一个元素的模式。

例如,如果ignore_check_login_urls列表中有两个元素['/login', '/register'],那么生成的正则表达式模式对象就是re.compile('/login|/register')。这个模式对象可以用于判断path字符串是否匹配/login/register

问题3: 下段代码是什么意思?

auth_cookie = cookies[app.config['AUTH_COOKIE_NAME']] if app.config['AUTH_COOKIE_NAME'] in cookies else None

这段代码是用来获取名为auth_cookie的cookie的值。它首先检查cookies字典中是否存在键为app.config['AUTH_COOKIE_NAME']的项,如果存在,则将其值赋给auth_cookie变量;如果不存在,则将auth_cookie赋值为None

这段代码的作用是判断是否存在名为app.config['AUTH_COOKIE_NAME']的cookie,并将其值赋给auth_cookie变量。如果存在该cookie,则auth_cookie变量将保存该cookie的值;如果不存在该cookie,则auth_cookie变量将为None


def check_login():
    cookies = request.cookies
    auth_cookie = cookies[app.configp['AUTH_COOKIE_NAME']] if app.config['AUTH_COOKIE_NAME'] in cookies else None

    if auth_cookie is None:
        return False
# 0 是授权码,  1是uid

    auth_info = auth_cookie.split('#')

问题4: 该段代码中auth_info是啥?

auth_info是一个列表,其中包含两个元素。第一个元素是授权码(auth_code),第二个元素是用户ID(uid)。

在这段代码中,首先检查名为AUTH_COOKIE_NAME的cookie是否存在于cookies字典中。如果存在,将其赋值给auth_cookie变量;否则,将auth_cookie设置为None

接下来,检查auth_cookie是否为None。如果是,表示未找到授权cookie,返回False

最后,使用split('#')方法将auth_cookie按照#分隔符拆分成两个元素,并将结果赋值给auth_info变量。

说实话到这我已经迷糊了,cookie是已经之前在web/controllers/user/User.py中定义好的

response.set_cookie( app.config['AUTH_COOKIE_NAME'], '%s#%s' % (
        UserService.geneAuthCode(user_info), user_info.uid), 60 * 60 * 24 * 120)   # 保存120填

这段代码将会设置一个名为app.config['AUTH_COOKIE_NAME']的cookie,其值为'%s#%s' % (UserService.geneAuthCode(user_info), user_info.uid),并且过期时间为120天

common/libs/user/UserService.py

class UserService():

    @staticmethod
    def geneAuthCode(user_info = None):   #user_info 是哪来的? 用函数时带的 geneAuthoCode(user_info)
        m = hashlib.md5()
        str = "%s-%s-%s-%s" % (user_info.uid, user_info.login_name, user_info.login_pwd, user_info.login_salt)
        m.update(str.encode("utf-8"))
        return m.hexdigest()

这段代码是一个静态方法,属于UserService类。它用于 生成用户的身份验证码。下面是对代码的详细解析:

  1. 首先,导入了hashlib模块,用于进行哈希操作。
  2. 然后,定义了一个静态方法geneAuthCode,该方法接受一个参数user_info,用于传入用户信息。
  3. 在方法内部,创建了一个hashlib.md5()对象,用于进行MD5哈希操作。
  4. 接下来,根据用户信息的不同属性,构建了一个字符串str,其中包含了用户的uidlogin_namelogin_pwdlogin_salt
  5. 使用m.update()方法,将字符串str进行UTF-8编码后更新到MD5对象中。
  6. 最后,使用m.hexdigest()方法,获取MD5对象的哈希值,并将其作为身份验证码返回。

这段代码的作用是根据用户的信息生成一个唯一的身份验证码,用于 用户身份验证 或 其他安全相关的操作。

可以按照以下步骤使用UserService类中的geneAuthCode方法生成用户认证码

  1. 导入UserService类:
    from UserService import UserService
  2. 创建UserService对象:
    user_service = UserService()
  3. 调用geneAuthCode方法生成用户认证码:
    user_info = # 获取用户信息
    auth_code = user_service.geneAuthCode(user_info)

    这样,你就可以使用  UserService类  中的  geneAuthCode方法  生成 用户认证码了。


问题5: 回归总结一下,cookie就是两个值,一个是用户认证码,一个是uid。 这两个值是什么样的呢?

response.set_cookie函数用于设置Cookie。app.config['AUTH_COOKIE_NAME']是Cookie的名称,'%s#%s' % (UserService.geneAuthCode(user_info), user_info.uid)是Cookie的值, 60 * 60 * 24 * 120是Cookie的过期时间(单位为秒)。

这个例子中,Cookie的值由两部分组成,用#符号分隔。第一部分是用户验证码,由UserService.geneAuthCode(user_info)生成。第二部分是用户的uid

以下是一个示例,展示如何生成 用户验证码uid

user_info = {
    'uid': 123,
    'username': 'example_user'
}

auth_code = UserService.geneAuthCode(user_info)
uid = user_info['uid']

print("用户验证码:", auth_code)
print("用户uid:", uid)

输出结果:

用户验证码: abcdefg
用户uid: 123

也就是说cookie是这样一个值  abcdefg#123


问题6: auth_info = auth_cookie.split('#') 中 auth_info是啥值 请给个案例

auth_info  是通过将auth_cookie字符串使用 "#" 进行分割后得到的一个  列表 。具体的值取决于auth_cookie的内容。下面是一个示例:

auth_cookie = 'abcd1234#12345'
auth_info = auth_cookie.split('#')
print(auth_info)

输出结果为:

['abcd1234', '12345']

auth_info是一个由授权码用户ID组成的列表。授权码在列表的索引0处,用户ID在列表的索引1处。


问题7: Exception是什么,有什么作用?

Exception是Python中的一个内置类,用于处理异常情况。在try-except语句中,当try块中的代码发生异常时,程序会跳转到对应的except块中执行异常处理代码。Exception类是所有异常类的基类,可以捕获任何类型的异常。通过捕获Exception类,可以处理所有可能发生的异常情况,确保程序的稳定性和可靠性。

Exception类的作用是提供了一种统一的异常处理机制,使得程序可以在出现异常时进行适当的处理,避免程序崩溃或产生不可预料的错误。通过捕获和处理异常,可以对异常情况进行适当的处理,例如输出错误信息、记录日志、回滚事务等。

在给定的代码中,try-except语句中的except块捕获了Exception异常,并返回False。这样做的目的是在发生异常时,返回一个特定的值,以便在调用该代码的地方进行进一步的处理或判断。

问题8: return False是怎么的一个值,在浏览器中会怎样显示?

return False是一个返回值,表示函数执行到这一步时返回了False。在浏览器中,如果这段代码是在后端服务器上执行的,那么浏览器不会直接显示返回值。相反,它会根据后端服务器的逻辑来处理返回值。可能会返回一个错误页面或者其他相应的信息。

如果你想在浏览器中显示返回值,你可以使用前端技术(如JavaScript)来处理后端返回的数据,并将其显示在浏览器上。这样你就可以根据返回值来决定在浏览器中显示什么内容。

你可能感兴趣的:(flask,python,后端)