目标:使用RESTful服务安全可靠地更新用户密码。
我对使用最佳实践的工作流程应该是什么感到困惑:
1.)为知道现有密码的用户更新密码
2.)如果用户忘记了重置密码。
3.)URI(资源)是否RESTful?出于此Web应用程序的目的,我只需要GET和POST进行更改。
我相信我的代码可能是多余的。密码更新方法(如下所示)未正确更新密码。它正在改变它,但当我尝试使用new_password
中设置的新密码登录时,密码不匹配。我同样遵循Michael Merickel的STACKs answer进行更新。
user = DBSession.query(User).filter_by(email = email).first() 如果用户: 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
views.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 DB方案中的哈希密码,如下所示:
Storing and validating encrypted password for login in Pyramid
答案 0 :(得分:6)
<强> 1。更新密码。
通常,密码以散列形式存储在数据库中,因此如果有人窃取您的数据库,则无法轻松获取密码。从您的代码中不清楚实际发生散列的位置,因此您需要检查@Html.DevExpress().HtmlEditor(settings =>
{
settings.Name = "HtmlEditor1";
settings.CallbackRouteValues = new { Controller = "HtmlEditor", Action = "HtmlEditorPartial" };
settings.Width = System.Web.UI.WebControls.Unit.Percentage(100);
settings.ToolbarMode = HtmlEditorToolbarMode.Menu;
settings.SettingsDialogs.InsertImageDialog.SettingsImageUpload.UploadCallbackRouteValues = new { Controller = "HtmlEditor", Action = "HtmlEditorPartialImageUpload" };
settings.SettingsDialogs.InsertImageDialog.SettingsImageUpload.UploadFolder = HtmlEditorControllerHtmlEditor1Settings.ImageUploadDirectory;
settings.SettingsDialogs.InsertImageDialog.SettingsImageUpload.ValidationSettings.Assign(HtmlEditorControllerHtmlEditor1Settings.ImageUploadValidationSettings);
settings.SettingsDialogs.InsertImageDialog.SettingsImageSelector.Assign(HtmlEditorControllerHtmlEditor1Settings.ImageSelectorSettings);
}).GetHtml()
是否执行了所需的魔法,或者您是否需要手动执行此操作。它应该类似于最初使用密码创建用户的代码。
如果您忘记了前面一行中的user.password = new_password
子句,则会出现“哎呀!密码不匹配。”的实际问题:
else
<强> 2。为不知道当前密码的用户重置密码
一种简单的方法是向用户模型添加一个新字段,例如 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.'
。当一个健忘的人输入他们的电子邮件时,你会通过电子邮件找到一个用户,用随机的不可猜测的胡言乱语填充password_reset_secret
并向用户发送一封电子邮件,其中包含指向特殊页面的链接,比如说https://yoursite.com/password_reset/jhg876jhgd87676 < / p>
收到电子邮件后,用户点击该链接并访问“秘密”页面 - 此时您知道他们可以访问他们输入的电子邮件地址,因为该URL无法猜测且未链接到任何地方。在该页面上是一个带有新密码字段的表单。当他们输入新密码时,您可以通过URL中的password_reset_secret
从数据库中查询用户对象并更新其密码。完成。
要使密码重置URL在一定时间后过期,您可以向password_reset_secret
模型添加另一个字段字段 - 例如'password_reset_last_valid',在创建密码时将其设置为“now + 3 days”当用户尝试访问链接时重置哈希并检查字段。如果该字段的值是过去那么您只是假装找不到任何内容。
要阻止用户多次使用该链接,您只需在用户成功更改密码后清除User
和password_reset_secret
字段。
第3。 URI是否适用?
不,他们不是,但你现在可能不应该担心这个问题:)