python - RESTful更新密码

标签 python rest sqlalchemy pyramid

目标:使用 RESTful 服务安全可靠地更新用户密码。

我对使用最佳实践的工作流程的用途感到有点困惑:
1.) 为知道现有密码的用户更新密码
2.) 如果用户忘记了密码,则重置密码。
3.) URI(资源)是 RESTful 的吗?出于此 Web 应用的目的,我只需要 GET 和 POST 进行更改。

我相信我的代码可能是多余的。密码更新方法(如下所示)未正确更新密码。它正在更改它,但是当我尝试使用 new_password 中设置的新密码登录时,密码不匹配。我同样遵循了这个 STACKs answer由 Michael Merickel 更新。

user = DBSession.query(User).filter_by(email=email).first() if user: user.password = new_password

感谢您的任何见解/意见。我是新手,想正确编码。

所有这些都是通过 HTML 而不是 JSON。
软件:Python 2.7.9、Pyramid 1.5.7、SQLAlchemy 1.0.9


资源: __init__.py

config.add_route('users', '/users')
config.add_route('user', '/users/{id:\d+}/{login}') #/{login} added login

config.add_route('reset_password', '/users/{username}/reset_password')#reset
config.add_route('new_password', '/users/{username}/new_password')#new
config.add_route('save_password', '/save_password')#new

View .py

#http://0.0.0.0:6432/users/dorisday/reset_password <--like this
@view_config(route_name='reset_password', renderer='templates/password_recovery.jinja2')
def forgot_password(request):
    if request.method == 'GET':
        username = request.params['username']
        if username is not None:
            user = api.retrieve_user(username)

        return {}

#http://0.0.0.0:6432/users/macycat/new_password <--like this
@view_config(route_name='new_password', request_method='GET', renderer='templates/new_password.jinja2')
def new_password(request):
    logged_in_userid  = authenticated_userid(request)
    if logged_in_userid is None:
        raise HTTPForbidden()
    user = api.retrieve_user(logged_in_userid)
    return {'user': user.username}

@view_config(route_name='save_password', request_method='POST', renderer='templates/new_password.jinja2')
def save_password(request):
    with transaction.manager:
        logged_in_userid  = authenticated_userid(request)
        if logged_in_userid is None:
            raise HTTPForbidden()
        user = api.retrieve_user(logged_in_userid)
        if 'form.submitted' in request.params:
            password = request.params['old_password']
            new_password = request.params['new_password']
            confirm_password = request.params['confirm_password']
            if new_password == confirm_password:
                continue
                if user is not None and user.validate_password(password): #encrypted way of checking password from DB
                    user.password = new_password 

                message = 'Whoops! Passwords do not match.'

        transaction.commit()
        raise HTTPSeeOther(location=request.route_url('login'))
        return {'message': message, 'new_password': new_password}

SQLALCHEMY 数据库方案中的哈希密码,如下所示:

Storing and validating encrypted password for login in Pyramid

最佳答案

<强>1。更新密码。

通常,密码以散列形式存储在数据库中,因此如果有人窃取了您的数据库,他们将无法轻易获得密码。从您的代码中不清楚哈希实际发生的位置,因此您需要检查 user.password = new_password 是否具有所需的魔力,或者您是否需要手动执行此操作。它应该类似于最初用于创建带密码的用户的代码。

如果您忘记了前一行中的 else 子句,您收到“糟糕!密码不匹配”消息的实际问题:

            if user is not None and user.validate_password(password): #encrypted way of checking password from DB
                user.password = new_password 
            **else:**
                message = 'Whoops! Passwords do not match.'

<强>2。为不知道当前密码的用户重置密码

一个简单的方法是向您的用户模型添加一个新字段,例如 password_reset_secret。当一个健忘的人输入他们的电子邮件时,您通过电子邮件找到一个用户,用随机的不可猜测的乱码填充 password_reset_secret 并向用户发送一封包含特殊页面链接的电子邮件,比如 https://yoursite.com/password_reset/jhg876jhgd87676

收到电子邮件后,用户单击链接并访问“ secret ”页面 - 此时您知道他们可以访问他们输入的电子邮件地址,因为该 URL 是不可猜测的,也没有链接到任何地方。该页面上有一个带有新密码字段的表单。当他们输入新密码时,您可以通过 URL 中的 password_reset_secret 从数据库中查询用户对象并更新其密码。完成。

要使密码重置 URL 在一定时间后过期,您可以向 User 模型添加另一个字段 - 例如,'password_reset_last_valid',将其设置为“now + 3 days”创建密码重置散列并在用户尝试访问链接时检查该字段。如果该字段的值是过去的,那么您就假装什么也没找到。

要防止用户多次使用该链接,您只需在用户成功更改密码后清除 password_reset_secretpassword_reset_last_valid 字段。

<强>3。 URI 是 Restful 吗?

不,他们不是,但你可能不应该在这个阶段担心这个 :)

关于python - RESTful更新密码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34165573/

相关文章:

java - 如何保护java应用程序中的凭据

javascript - 无法在 Express 响应中发送对象

python - 如何使用 Flask 和 SQLAlchemy 输出扁平化数据库表以实现出色表现

python - 如何从python中的字符串中找到最大值和最小值?

python - Pandas 删除列表中除最后一项之外的所有项目

python - Cx_Freezing PySide,praw,请求应用程序在卡住时停止工作

python - Sqlalchemy - 关闭游标回溯时出错,出现内部错误 : Unread result found

python - 如何在 Python 中的单个日志记录中记录两个变量值?

python - 如何处理 requests_futures 的速率限制?

python - Alembic:如何在不求助于 `alembic.op.execute` 的情况下在迁移脚本中添加新的枚举类型