如何在 CherryPy 中使用 cookie 和 HTTP 基本身份验证?

2024-03-25

我有一个需要身份验证的 CherryPy Web 应用程序。我正在使用 HTTP 基本身份验证,其配置如下所示:

app_config = {
    '/' : {
        'tools.sessions.on': True,
        'tools.sessions.name': 'zknsrv',
        'tools.auth_basic.on': True,
        'tools.auth_basic.realm': 'zknsrv',
        'tools.auth_basic.checkpassword': checkpassword,
        }
    }

HTTP 身份验证此时效果很好。例如,这将为我提供我在其中定义的成功登录消息AuthTest:

curl http://realuser:realpass@localhost/AuthTest/

由于会话已开启,我可以保存 cookie 并检查 CherryPy 设置的 cookie:

curl --cookie-jar cookie.jar http://realuser:realpass@localhost/AuthTest/

The cookie.jar文件最终将如下所示:

# Netscape HTTP Cookie File
# http://curl.haxx.se/rfc/cookie_spec.html
# This file was generated by libcurl! Edit at your own risk.

localhost       FALSE   /       FALSE   1348640978      zknsrv  821aaad0ba34fd51f77b2452c7ae3c182237deb3

但是,我会得到一个 HTTP401 Not Authorized如果我提供此会话 ID 而不提供用户名和密码,则会失败,如下所示:

curl --cookie 'zknsrv=821aaad0ba34fd51f77b2452c7ae3c182237deb3' http://localhost/AuthTest

我缺少什么?

非常感谢您的帮助。


所以,简短的答案是你可以这样做,但你必须编写自己的 CherryPy 工具 (a before_handler), 你呢must not在 CherryPy 配置中启用基本身份验证(也就是说,您不应该执行类似的操作tools.auth.on or tools.auth.basic...等) - 您必须自己处理 HTTP 基本身份验证。原因是内置的基本身份验证内容显然非常原始。如果您像我上面那样通过启用基本身份验证来保护某些内容,它将执行身份验证检查在检查会话之前,并且您的 cookie 将不会执行任何操作。

我的解决方案,散文

幸运的是,即使 CherryPy 没有办法内置这两种方法,您仍然可以使用其内置会话代码。您仍然需要编写自己的代码来处理基本身份验证部分,但总的来说,这还不错,并且使用会话代码是一个巨大的胜利,因为编写自定义会话管理器是将安全错误引入到您的 web 应用程序中的好方法。

我最终能够从 CherryPy wiki 上的一个名为 的页面获取很多内容简单的身份验证和访问限制助手 http://tools.cherrypy.org/wiki/AuthenticationAndAccessRestrictions。该代码使用 CP 会话,但它不是使用基本身份验证,而是使用带有登录表单的特殊页面,该页面可以提交?username=USERNAME&password=PASSWORD。我所做的基本上无非就是改变提供的check_auth从使用特殊登录页面到使用 HTTP 身份验证标头的功能。

一般来说,您需要一个可以添加为 CherryPy 工具的函数 - 特别是before_handler。 (在原始代码中,这个函数被称为check_auth(),但我将其重命名为protect().) 该函数首先尝试查看 cookie 是否包含(有效)会话 ID,如果失败,它会尝试查看标头中是否存在 HTTP 身份验证信息。

然后,您需要一种方法来要求对给定页面进行身份验证;我这样做与require(),加上一些状况,这只是返回的可调用对象True。就我而言,这些条件是zkn_admin(), and user_is()功能;如果您有更复杂的需求,您可能还想看看member_of(), any_of(), and all_of()从原始代码。

如果您这样做,您已经有了一种登录方法 - 您只需将有效的会话 cookie 或 HTTPBA 凭据提交到您使用@require()装饰师。您现在需要的只是一种注销方式。

(原始代码有一个AuthController类包含login() and logout(),你可以使用整个AuthController只需将对象放入 HTTP 文档树中即可auth = AuthController()在您的 CherryPy 根类中,并通过 URL 例如访问它http://example.com/auth/login http://example.com/auth/login and http://example.com/auth/logout http://example.com/auth/logout。我的代码不使用 authcontroller 对象,仅使用一些函数。)

关于我的代码的一些注释

  • 警告:因为我为 HTTP 身份验证标头编写了自己的解析器,所以它只解析我告诉它的内容,这意味着只是 HTTP 基本身份验证 - 而不是摘要身份验证或其他任何内容。对于我的应用程序来说,这很好;对你来说,可能不是。
  • 它假设我的代码中其他地方定义了一些函数:user_verify() and user_is_admin()
  • 我也用一个debugprint()仅在以下情况下打印输出的函数DEBUG变量已设置,为了清楚起见,我保留了这些调用。
  • 你可以调用它cherrypy.tools.WHATEVER(见最后一行);我叫它zkauth基于我的应用程序的名称。注意不要调用它auth,或任何其他内置工具的名称。
  • 然后你必须启用cherrypy.tools.WHATEVER在您的 CherryPy 配置中。
  • 正如您从所有 TODO: 消息中看到的,此代码仍处于不断变化的状态,并且没有针对边缘情况进行 100% 测试 - 对此感到抱歉!不过,我希望它仍然会给你足够的想法继续下去。

我的解决方案,用代码

import base64
import re
import cherrypy 

SESSION_KEY = '_zkn_username'

def protect(*args, **kwargs):
    debugprint("Inside protect()...")

    authenticated = False
    conditions = cherrypy.request.config.get('auth.require', None)
    debugprint("conditions: {}".format(conditions))
    if conditions is not None:
        # A condition is just a callable that returns true or false
        try:
            # TODO: I'm not sure if this is actually checking for a valid session?
            # or if just any data here would work? 
            this_session = cherrypy.session[SESSION_KEY]

            # check if there is an active session
            # sessions are turned on so we just have to know if there is
            # something inside of cherrypy.session[SESSION_KEY]:
            cherrypy.session.regenerate()
            # I can't actually tell if I need to do this myself or what
            email = cherrypy.request.login = cherrypy.session[SESSION_KEY]
            authenticated = True
            debugprint("Authenticated with session: {}, for user: {}".format(
                    this_session, email))

        except KeyError:
            # If the session isn't set, it either wasn't present or wasn't valid. 
            # Now check if the request includes HTTPBA?
            # FFR The auth header looks like: "AUTHORIZATION: Basic <base64shit>"
            # TODO: cherrypy has got to handle this for me, right? 

            authheader = cherrypy.request.headers.get('AUTHORIZATION')
            debugprint("Authheader: {}".format(authheader))
            if authheader:
                #b64data = re.sub("Basic ", "", cherrypy.request.headers.get('AUTHORIZATION'))
                # TODO: what happens if you get an auth header that doesn't use basic auth?
                b64data = re.sub("Basic ", "", authheader)

                decodeddata = base64.b64decode(b64data.encode("ASCII"))
                # TODO: test how this handles ':' characters in username/passphrase.
                email,passphrase = decodeddata.decode().split(":", 1)

                if user_verify(email, passphrase):

                    cherrypy.session.regenerate()

                    # This line of code is discussed in doc/sessions-and-auth.markdown
                    cherrypy.session[SESSION_KEY] = cherrypy.request.login = email
                    authenticated = True
                else:
                    debugprint ("Attempted to log in with HTTBA username {} but failed.".format(
                            email))
            else:
                debugprint ("Auth header was not present.")

        except:
            debugprint ("Client has no valid session and did not provide HTTPBA credentials.")
            debugprint ("TODO: ensure that if I have a failure inside the 'except KeyError'"
                        + " section above, it doesn't get to this section... I'd want to"
                        + " show a different error message if that happened.")

        if authenticated:
            for condition in conditions:
                if not condition():
                    debugprint ("Authentication succeeded but authorization failed.")
                    raise cherrypy.HTTPError("403 Forbidden")
        else:
            raise cherrypy.HTTPError("401 Unauthorized")

cherrypy.tools.zkauth = cherrypy.Tool('before_handler', protect)

def require(*conditions):
    """A decorator that appends conditions to the auth.require config
    variable."""
    def decorate(f):
        if not hasattr(f, '_cp_config'):
            f._cp_config = dict()
        if 'auth.require' not in f._cp_config:
            f._cp_config['auth.require'] = []
        f._cp_config['auth.require'].extend(conditions)
        return f
    return decorate

#### CONDITIONS
#
# Conditions are callables that return True
# if the user fulfills the conditions they define, False otherwise
#
# They can access the current user as cherrypy.request.login

# TODO: test this function with cookies, I want to make sure that cherrypy.request.login is 
#       set properly so that this function can use it. 
def zkn_admin():
    return lambda: user_is_admin(cherrypy.request.login)

def user_is(reqd_email):
    return lambda: reqd_email == cherrypy.request.login

#### END CONDITIONS

def logout():
    email = cherrypy.session.get(SESSION_KEY, None)
    cherrypy.session[SESSION_KEY] = cherrypy.request.login = None
    return "Logout successful"

现在您所要做的就是启用内置会话和您自己的会话cherrypy.tools.WHATEVER在您的 CherryPy 配置中。再次强调,注意不要启用cherrypy.tools.auth。我的配置最终看起来像这样:

config_root = {
    '/' : {
        'tools.zkauth.on': True, 
        'tools.sessions.on': True,
        'tools.sessions.name': 'zknsrv',
        }
    }
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何在 CherryPy 中使用 cookie 和 HTTP 基本身份验证? 的相关文章

  • 美丽的汤从谷歌搜索中提取href

    谷歌搜索给出了以下 HTML 的第一个结果 h3 class r a href https rads stackoverflow com amzn click com 0470284889 class l vst em Quantitati
  • 帮助需要在可选条件下编写正则表达式[关闭]

    我有一个日志文件包含如下内容 log Using data from yyyy mm dd 2011 8 3 0 files queued for scanning Warning E test H ndler pdf File not F
  • Python 小数.InvalidOperation 错误

    当我运行这样的东西时 我总是收到此错误 from decimal import getcontext prec 30 b 2 3 Decimal b Error Traceback most recent call last File Te
  • 使用信号时出现 django TransactionManagementError

    我有一个与 django 的用户和 UserInfo 一对一的字段 我想订阅用户模型上的 post save 回调函数 以便我也可以保存 UserInfo receiver post save sender User def saveUse
  • 通过鼻子测试检查某个函数是否发出警告

    我正在使用编写单元测试nose http somethingaboutorange com mrl projects nose 0 11 2 我想检查函数是否引发警告 该函数使用warnings warn 这是很容易就能做到的事情吗 def
  • 十六进制数的按位异或

    我们如何在 Python 中对十六进制数进行异或 例如 我想要异或 ABCD and 12EF 答案应该是 B922 我使用了下面的代码 但它给出了错误的结果 xor two strings of different lengths def
  • 使用字母而不是数字进行顺序计数[重复]

    这个问题在这里已经有答案了 我需要一种方法 将字符串 递增 到 z 然后将 aa 递增到 az 然后将 ba 递增到 bz 依此类推 就像 Excel 工作表中的列一样 我将向该方法提供前一个字符串 它应该增加到下一个字母 PSEUDO C
  • 在 PHP 中计算 Cookie 大小

    我想使用 php 在服务器端读取 cookie 并计算其长度 但找不到任何直接方法来执行此操作 那么如何实现这个任务呢 那这个呢 setcookie user Dino babu kannampuzha time 3600 if isset
  • 理解@property装饰器和继承[重复]

    这个问题在这里已经有答案了 这里是 Python 3 以防万一它很重要 我试图正确理解如何实现继承 property使用 我已经搜索了 StackOverflow 并阅读了大约 20 个类似的问题 但无济于事 因为他们试图解决的问题略有不同
  • Pyinstaller --onefile 警告文件已存在但不应存在

    跑步时Pyinstaller onefile 并开始得到结果 exe 会出现多个弹出窗口 并显示以下警告 WARNING file already exists but should not C Users myuser AppData L
  • 属性错误:类型对象“图像”没有属性“打开”

    Exception in Tkinter callback Traceback most recent call last File C Python34 lib tkinter init py line 1482 in call retu
  • InvalidArgumentException:消息:无效参数:“using”必须是字符串

    我对 python 很陌生 试图创建可重用的代码 当我尝试通过传递 Login 类下使用的所有参数来调用 test main py 中的 Login 类和函数 login user 时 我收到错误 InvalidArgumentExcept
  • 如何使用 msgpack 进行读写?

    如何序列化 反序列化字典data with msgpack http msgpack org The Python 文档 http msgpack python readthedocs io en latest badge latest似乎
  • 管理文件字段当前 url 不正确

    在 Django 管理中 只要有 FileField 编辑页面上就会有一个 当前 框 其中包含指向当前文件的超链接 但是 此链接会附加到当前页面 url 因此会导致 404 因为不存在这样的页面 例如 http 127 0 0 1 8000
  • 基于资源的访问控制与基于角色的访问控制

    我正在学习 Apache Shiro 发现了这篇文章 新的 RBAC 基于资源的访问控制 http www stormpath com blog new rbac resource based access control 作者说 您可以将
  • 如何在 Python 中执行相当于预处理器指令的操作?

    有没有办法在 Python 中执行以下预处理器指令 if DEBUG lt do some code gt else lt do some other code gt endif There s debug 这是编译器预处理的特殊值 if
  • 网页抓取 - 如何识别网页上的主要内容

    给定一个新闻文章网页 来自任何主要新闻来源 例如时报或彭博社 我想识别该页面上的主要文章内容 并丢弃其他杂项元素 例如广告 菜单 侧边栏 用户评论 在大多数主要新闻网站上都可以使用的通用方法是什么 有哪些好的数据挖掘工具或库 最好是基于Py
  • 在 Java 服务器中验证 Windows 用户

    我正在开发一个用 Java 编写的服务器和一个在同一网络上的 Windows 计算机上运行的客户端 用 Net 编写的桌面应用程序 我希望进行一些基本身份验证 以便服务器可以确定运行客户端的用户的用户名 而不需要用户在客户端中重新输入其 W
  • 在 Tensorflow 2.0 中的简单 LSTM 层之上添加 Attention

    我有一个由一个 LSTM 和两个 Dense 层组成的简单网络 如下所示 model tf keras Sequential model add layers LSTM 20 input shape train X shape 1 trai
  • Selenium Python 使用代理运行浏览器[重复]

    这个问题在这里已经有答案了 我正在尝试编写一个非常简单的脚本 该脚本从 txt 文件获取代理 不需要身份验证 并用它打开浏览器 然后沿着代理列表循环此操作一定次数 我确实知道如何打开 txt 文件并使用它 我的主要问题是让代理正常工作 我见

随机推荐

  • 标签文本换行但不缩进第二行

    我有一个宽度有限的表单 但是标签文本可能比表单宽度长 因此文本被换行为多行 我的问题是 由于输入元素 第一行缩进 但第二行没有缩进 这使得表单不太好 你有什么想法让第二行 第三行 将缩进为第一行 只使用CSS吗 Actual 我的期望是 这
  • 调试 Chrome 上加载的源映射

    我在缩小过程中生成 javascript 文件的源映射 使用地图文件旁边的缩小 JS 文件中的相对 URL 来引用地图文件 这是末尾的评论示例app e47a6637 js sourceMappingURL app e47a6637 js
  • `http://localhost` 上的安全 Cookie

    我正在尝试设置安全 cookiehttp localhost 3000 设置 Cookie loggedUser brillout 最大年龄 315360000 路径 仅 Http 安全的 但 Chrome 抱怨道 此 Set Cookie
  • MS Access 的新管理员,如何修改现有宏

    我是 MS Access 数据库的新管理员 我对 MS Access 很陌生 所以如果我问的问题在这里没有意义 请原谅我 当前员工的桌面上有一个小的 5MB 左右 mdb 文件 单击该文件将打开 Access 并在 Access 左侧列出查
  • 使用 ACR122U NFC 读卡器对 Mifare 1K NFC 标签进行身份验证失败

    我在使用ACR122U工具验证Mifare 1K NFC标签时总是得到失败结果 但我可以使用Android手机读取 写入该标签 ACR122U Load Authentication Keys lt FF 82 00 00 06 FF FF
  • Android Gallery 中 CoverFlow 中的错误图像重叠

    我正在摆弄 CoverFlow从这里 http www inter fuser com 2010 02 android coverflow widget v2 html以满足我的喜好并且无法解决一个问题 这是屏幕截图 截屏 https i
  • orderBy 在 Laravel 5 中不起作用

    我正在使用以下查询 orderBy在下面的查询中不起作用 此查询在本地主机中有效 但在在线服务器中无效 return DB table reports gt leftJoin sources reports report source id
  • 通过 OleDb ACE 访问 Excel 2007 二进制文件 (.xlsb)

    我发现 Excel 2007 二进制格式 扩展名为 xlsb 非常完美 适合我的需求 因为它加载速度快且非常紧凑 我交付一个 Excel 中的一堆报告包含大量数据 这些报告是 实际上正在加载一个 IS 包 所以我假设转换为这种格式 请阅读有
  • 如何打印json数据。

    我有一个像这样的 json 输出数组 data name Ben Thorpe id XXXXXXXXXXX name Francis David id XXXXXXXXXXX 我想循环遍历它并使用 javascript 打印出所有名称 我
  • 弹出视图的位置问题

    当我在 iPad 中的纵向视图和横向视图 反之亦然 之间切换时 我的弹出视图的位置出现乱码 这是我计算弹出视图框架的方法 aRect self myElement frame aRect origin x aRect size width
  • API“BaseVariant.getApplicationIdTextResource”已过时,已替换为“VariantProperties.applicationId”

    构建 gradle 时我收到以下消息 API BaseVariant getApplicationIdTextResource is obsolete and has been replaced with VariantProperties
  • 在 matplotlib 中向颜色条添加白色背景

    我想通过添加白色背景使我的颜色条更加明显 我需要图像内的颜色条 这有时很难阅读 这是没有白色背景的代码 import matplotlib pyplot as plt import numpy as np a np random rand
  • CSS3动画“进度”回调

    我只是想知道是否有一种方法可以监视元素动画的进度 我所知道的是animationstart and animationend 有没有某种animationprogress 不 没有animationprogess事件 根据W3规格 http
  • 如何使用 sqlalchemy IntegrityError 查找有问题的属性

    我有一个非常简单的 SqlAlchemy 模型 class User Base The SQLAlchemy declarative model class for a User object tablename users id Colu
  • Javascript - 跟踪任何 xmlhttprequest

    我可以检查页面上的任何 XmlHttpRequest 可执行文件 而无需分别添加 addEventListener 吗 我尝试添加 document addEventListener loadend 但什么也没发生 看起来请求没有全局事件
  • 在Python中提取每个子列表的第一项

    我想知道提取列表列表中每个子列表的第一项并将其附加到新列表的最佳方法是什么 所以如果我有 lst a b c 1 2 3 x y z 还有 我想拔出来a 1 and x并从中创建一个单独的列表 I tried lst2 append x 0
  • 在python中读取二进制文件

    我必须用 python 读取二进制文件 首先由 Fortran 90 程序这样编写 open unit 10 file filename form unformatted write 10 table n1 table n2 write 1
  • 如何将wordpress循环与网格系统引导程序一起使用?

    我想显示一个带两列的条形行 其中包含wordpress循环内容 标题 以绿色块表示 每行都有白色和灰色背景的列 这些列在每行中反转 就像国际象棋检查器一样 see the image for more detail 编辑答案 我相信这就是您
  • 如何让 Windows 错误报告 (WER) 保存内存转储以防止挂起?

    WER 正在应用程序挂起后创建内存转储 当 Windows 显示对话框时应用名称没有回应 如果用户点击关闭程序 我可以看到正在创建的 hdmp 文件C ProgramData Microsoft Windows WER Temp 将它们发送
  • 如何在 CherryPy 中使用 cookie 和 HTTP 基本身份验证?

    我有一个需要身份验证的 CherryPy Web 应用程序 我正在使用 HTTP 基本身份验证 其配置如下所示 app config tools sessions on True tools sessions name zknsrv too