2

背景:

我拥有一个非常简单的基于投票的站点设置的核心功能,并且使用 sqlite 数据库在金字塔中运行良好。此应用程序的最后一个要求是每个用户每天只允许一票。已指定必须通过 cookie 完成此操作,并且不允许用户在周六或周日投票。

我目前UnencryptedCookieSessionFactoryConfig用于会话管理和处理闪存消息。

问题:

我已经确定我需要以下功能,但无法确定金字塔的哪些模块可以提供它(或者我是否应该在其他地方寻找):

  • 为在浏览器会话之间持续存在的每个用户创建一个 cookie(我知道作为防止多票的一种方法是不安全的。没关系。)

  • 允许每个用户每天进行一次投票。

  • 24 小时后给用户一个新的投票。

  • 如果星期几 = 星期六或星期日,则阻止所有投票(这对于在任何 cookie 检查逻辑之前使用 datetime() 检查应该是微不足道的。

附加信息:

我当前的数据库架构如下,必须保持这种方式:

create table if not exists games (
    id integer primary key autoincrement,
    title char(100) not null,
    owned bool not null,
    created char(40) not null
);

create table if not exists votes (
    gameId integer,
    created char(40) not null,
    FOREIGN KEY(gameId) REFERENCES games(id)
);

当前的投票功能如下:

@view_config(route_name='usevote')
def usevote_view(request):
    game_id = int(request.matchdict['id'])
    request.db.execute('insert into votes (gameId,created) values (?,?)',
                (game_id,now))
    request.db.commit()
    request.session.flash('Your vote has been counted. You can vote again in 24 hours.')
    return HTTPFound(location=request.route_url('list'))

谢谢!

4

2 回答 2

3

仅 cookie 上的会话数据

要在金字塔上集成 cookie 会话,请查看pyramid_beaker

为了仅使用 cookie 来保证完整性(并避免用户戳入 cookie 数据),您应该使用加密的 cookie(查看基于会话的 cookie加密选项)。

您的主要配置将如下所示:

[app:main]
...
session.type = cookie
session.key = SESSION
session.encrypt_key = R9RD9qx7uzcybJt1iBzeMoohyDUbZAnFCyfkWfxOoX8s5ay3pM
session.validate_key = pKs3JDwWiJmt0N0wQjJIqdG5c1XsHSlauM6T2DfB8FqOifsWZN
...

session.key只是 cookie 的名称。随心所欲地改变

session.encrypt_key以上session.validate_key只是大随机字符串的示例。您应该自己生成它们并将它们保密。

此外,要正确加密 cookie,您将需要 AES 密码实现。安装pycrypto应该这样做:

pip install pycryto

main创建 wsgi 应用程序的函数也应更改为以下内容:

from pyramid_beaker import session_factory_from_settings
...

def main(global_config, **settings):
    ...
    config = Configurator(settings=settings)
    ...
    config.set_session_factory(session_factory_from_settings(settings))

现在您可以将 cookie 数据直接存储到客户端浏览器中,避免数据被篡改。解决您的问题的简单解决方案是将此 cookie 设置为永不过期,将他最后一次投票的日期存储在其中,并根据今天是哪一天以及他最后一次投票是哪一天进行检查

主要问题

现在的主要问题是处理删除 cookie、使用其他浏览器或简单地使用浏览器的隐身窗口 (chrome) 或私人导航 (firefox) 的用户。此用户似乎是您系统的新用户,因此可以再次投票。

IMO 解决了您需要有一个服务器端控制或惩罚用户的方式,即删除 cookie 实际上会使他的生活更加困难,以至于不再需要删除 cookie 以获得投票。

安全性不是完美的不可破解的系统,而是构建绕过它的成本实际上高于这样做的好处的系统。

于 2013-06-07T17:33:30.030 回答
1

即使是最简单的攻击(例如使用不同的浏览器 :)),使用 cookie 进行这种控制也无法阻止。但是您似乎知道它并且实际上并不在乎,所以我猜应该没问题:

每次用户投票时,使用当前日期的值向 cookie 添加一个字段(您还应该将其年龄限制设置为至少一周)。

下次用户尝试投票时,您检查是星期六还是星期日(根据用户时间设置),该字段是否存在以及该值是否早于一天。

如果您将 cookie 有效期设置为下周六,您将有一个额外的验证机制,因为如果是周六,cookie 无论如何都不会有效 :)

于 2013-06-07T16:48:31.280 回答