在 Pyramid 中存储和验证用于登录的加密密码

Posted

技术标签:

【中文标题】在 Pyramid 中存储和验证用于登录的加密密码【英文标题】:Storing and validating encrypted password for login in Pyramid 【发布时间】:2016-02-15 14:22:38 【问题描述】:

我正在尝试在 Pyramid 中验证用于login 目的的加密密码。这样,如果用户和密码匹配,则系统将授权用户。目前,当密码在数据库中加密并且输入 Pyramid 的login 表单的密码未加密时,我发现很难编写一个函数来比较密码。目前,我没有在登录视图中进行验证。

我对使用安全措施/代码的整个过程不熟悉,并希望正确地做到这一点。我在看这个Auth tutorial,但是User 类中的加密略有不同,我使用的是 Pyramid 的 Auth 工具包。任何有关如何成功和巧妙地做到这一点的指导都将受到高度赞赏。

软件:Python 2.7.9、Pyramid 1.5.7、SQLAlchemy 1.0.9


数据库类:

class User(Base):
    __tablename__ = 'users'

    id = Column(Integer, primary_key=True)
    username = Column(String(15), nullable=False, unique=True)
    email = Column(String(300))
    password = Column(String(300), nullable=False)

    def __init__(self, username, password, email):
        self.username = username
        self.password = hashlib.sha224(password).hexdigest()
        self.email = email

    def __repr__(self):
        return "<User(username ='%s', password='%s', email='%s')>" % (self.username, self.password, self.email)

观看次数

@view_config(route_name='login', renderer='templates/login.jinja2')
@forbidden_view_config(renderer='templates/login.jinja2')
def login(request):
    login_url = request.route_url('login')
    referrer = request.url
    if referrer == login_url:
        referrer = '/' # never use the login form itself as came_from
    came_from = request.params.get('came_from', referrer)
    message = ''
    login = ''
    password = ''
    if 'form.submitted' in request.params:
        login = request.params['login']
        password = request.params['password']

        user = api.retrieve_user(login) # need some way to validate password
        if user is not None: # need to check user/password here, redirect if wrong
            headers = remember(request, login)
            return HTTPFound(location = came_from,
                             headers = headers)
            message = 'Failed login'

    return dict(
        message = message,
        url = request.application_url + '/login',
        came_from = came_from,
        login = login,
        password = password,
        )

【问题讨论】:

请不要使用 sha224 存储用户密码,请使用允许您安全存储密码的适当库(例如 passlib)。 【参考方案1】:

请修改您的代码,添加优秀的 passlib 库,并使用 bcrypt 作为哈希算法的安全密码存储。

在您的项目 setup.py 中添加以下要求:

bcrypt 密码库

然后为您的模型使用以下代码 sn-p:

from passlib.hash import bcrypt

class User(Base):
    __tablename__ = 'users'

    id = Column(Integer, primary_key=True)
    username = Column(String(15), nullable=False, unique=True)
    email = Column(String(300))
    password = Column(String(300), nullable=False)

    def __init__(self, username, password, email):
        self.username = username
        self.password = bcrypt.encrypt(password)
        self.email = email

    def validate_password(self, password):
        return bcrypt.verify(password, self.password)

    def __repr__(self):
        return "<User(username ='%s', password='%s', email='%s')>" % (self.username, self.password, self.email)

【讨论】:

感谢您的代码!我不知道。我更新了我的代码以反映这个更强大的系统。干杯! 我最近注意到使用上下文管理器可能会有所帮助,因为它可以让您在时机成熟时轻松切换到新算法:pythonhosted.org/passlib/lib/… 这里的代码现在开始抛出一些问题:passlib.registry: DEBUG: registered 'bcrypt' handler: &lt;class 'passlib.handlers.bcrypt.bcrypt'&gt; passlib.handlers.bcrypt: DEBUG: 'bcrypt' backend lacks '$2$' support 看来我推荐的 bcrypt 库不支持 pass lib 使用的 salt 机制。查看此处支持的这些后端,并验证它是否适用于该哈希算法的 pass lib,或者更改 salt 算法:pythonhosted.org/passlib/lib/passlib.hash.bcrypt.html#index-0 现在,passlib 在使用bcrypt.encrypt() 时会发出弃用警告。我们应该改用bcrypt.hash()【参考方案2】:

警告不安全的代码如下

下面的代码不是存储/验证用户密码的安全方法。请使用提供安全密码存储的库,例如专为安全存储密码而设计的passlib。


您使用self.password = hashlib.sha224(password).hexdigest()User.__init__ 中的用户密码进行哈希处理。只需使用类似的方法来验证它:

class User(Base):
    # Your existing code unchanged

    def validate_password(self, password):
        return self.password == hashlib.sha224(password).hexdigest()

并在你的视图中使用它:

user = api.retrieve_user(login)
if user is not None and user.validate_password(password):
    # You logic on success

【讨论】:

我试图在不添加“哈希...”代码的情况下进行验证。这太简单了!非常感谢您的澄清。我为此快疯了。还有一个问题。我注意到如果用户登录错误,它不会显示登录失败消息。是因为退货后的留言吗?我应该把它搬上去吗?所以我可以重定向创建一个帐户? @thesayhey 是的,你的message = 'Failed login' 似乎缩进太多了。删除4个空格,你应该很好。 密码请不要直接使用sha224。使用适当的库,例如 passlib!

以上是关于在 Pyramid 中存储和验证用于登录的加密密码的主要内容,如果未能解决你的问题,请参考以下文章

登录验证之密码处理

在钥匙串中存储用于加密密码的密钥的最佳位置在哪里

使用 React 和 Pyramid(微服务架构)进行身份验证,如何存储“会话数据”?

php登录加密加盐

分享知识-快乐自己:注册用户密码加密登录验证及权限验证

函数,事务,索引,存储过程