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

Storing and validating encrypted password for login in Pyramid

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

我是整个安全工作流程的新手 measures/code,我想做好这件事。我正在查看此 Auth tutorial,但是 User class 中的加密略有不同,我使用的是 Pyramid 的 Auth 工具包。任何有关如何成功和巧妙地做到这一点的指导将不胜感激。

软件:Python2.7.9,Pyramid 1.5.7,SQLAlchemy 1.0.9


数据库class:

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,
        )

警告不安全代码如下

下面的代码不是 store/verify 用户密码的安全方法。请使用提供安全密码存储的库,例如专门用于安全存储密码的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

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

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

  • bcrypt
  • 密码库

然后为您的模型使用以下代码片段:

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)