登录实现后,有很多页面还没有进行设置登录要求,即使没有登录也可以到页面中来,当页面多了以后,每个页面都进行设置又非常繁琐,所以这里用到了 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_URLS和IGNORE_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
类。它用于 生成用户的身份验证码。下面是对代码的详细解析:
hashlib
模块,用于进行哈希操作。geneAuthCode
,该方法接受一个参数user_info
,用于传入用户信息。hashlib.md5()
对象,用于进行MD5哈希操作。str
,其中包含了用户的uid
、login_name
、login_pwd
和login_salt
。m.update()
方法,将字符串str
进行UTF-8编码后更新到MD5对象中。m.hexdigest()
方法,获取MD5对象的哈希值,并将其作为身份验证码返回。这段代码的作用是根据用户的信息生成一个唯一的身份验证码,用于 用户身份验证 或 其他安全相关的操作。
可以按照以下步骤使用UserService类中的geneAuthCode方法生成用户认证码:
from UserService import UserService
user_service = UserService()
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)来处理后端返回的数据,并将其显示在浏览器上。这样你就可以根据返回值来决定在浏览器中显示什么内容。