2015-12-08 2 views
1

Цель: безопасное и безопасное обновление пароля пользователя с использованием служб RESTful.RESTful update password

Я немного запутался о том, что рабочий процесс, используя лучшие практики, должны быть для:
    1.) обновление пароля для пользователя, который знает, что есть существующий пароль
    2.) сброс пароля если пользователь забыл.
    3.) Являются ли URI (ресурсы) RESTful? Для целей этого веб-приложения мне просто нужны GET и POST для изменений.

Я считаю, что мой код может быть избыточным. Метод обновления пароля (показано ниже) не обновляет пароль правильно. Он меняет его, но когда я пытаюсь войти с новым паролем, установленным в new_password, пароль не совпадает. Я так же следил за этим STACKs answer Майклом Мерикелем для обновления.

пользователя = DBSession.query (Пользователь) .filter_by (электронная почта = электронная почта) .first() если пользователь: user.password = new_password

Благодарим Вас за какие-либо идеи/ввода. Я новичок и хочу правильно закодировать.

Все это через HTML, а не JSON.
Software: Python 2.7.9, 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

вы должны использовать некоторые аутентификации (OAuth может аутентифицировать и его еще успокоительного) ... Вы также не должны на самом деле измените пароль, но отправьте по электронной почте связанную учетную запись электронной почты ссылку на тип типа «изменить пароль». –

+0

@JoranBeasley Я использую код аутентификации Pyramid для входа в систему. Что касается пароля сброса, я понятия не имею, как это сделать. Можете ли вы указать мне на то, что не является Django, поскольку я использую SQLAlchemy и Pyramid. Может быть, пример псевдокода? Это было бы очень полезно в качестве плана. Или ссылки? благодаря!!! – thesayhey

ответ

6

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

При получении электронной почты, пользователь нажимает на ссылку и посещает «секретную» страницу - это тот факт, что вы знаете, что у них есть доступ к адресу электронной почты, на который они набрали, поскольку URL-адрес в противном случае не является допустимым и не связан ни с чем. На этой странице есть форма с полем для нового пароля. Когда они вводят новый пароль, вы запрашиваете объект User из БД с помощью password_reset_secret с URL-адресом и обновляете его пароль. Готово.

Чтобы сбросить URL-адрес для доступа к URL-адресу через определенное время, вы можете добавить другое поле поля в свою модель User - скажем, 'password_reset_last_valid', установите значение «сейчас + 3 дня» при создании хэша сброса пароля и проверяя поле, когда пользователь пытается посетить ссылку. Если значение поля в прошлом, вы просто притворяетесь, что ничего не найдено.

Чтобы предотвратить использование пользователем нескольких раз, вы просто очищаете поля password_reset_secret и password_reset_last_valid после того, как пользователь с успехом изменил свой пароль.

3. Сохраняются ли URI?

Нет, это не так, но вы, вероятно, не стоит беспокоиться об этом на данном этапе :)

+0

Когда пользователь создан, пароль автоматически хэшируется при создании. У меня есть функция validate_password() 'внутри db, которая затем проверяется. См. Ссылку, добавленную выше. Это работает? Или я должен добавить ручной код в код 'new_password'? Ваше объяснение 2. сброс пароля является удивительным! Я все еще не уверен в том, что 'password_reset_secret' будет выглядеть в модели User, поскольку он требует отправки пользователю (тексту) электронной почты. Я предполагаю, что код вида просто попросит адрес электронной почты пользователя и если будет действительным отправить сообщение об ошибке elif. PS, Ваше объяснение настолько ясное и просветительное. – thesayhey

+0

@thesayhey: «Когда пользователь создан, пароль автоматически хэшируется при создании» - поэтому вам нужно убедиться, что пароль также хэшируется при установке нового пароля. 'Validate_password()', я полагаю, работает путем хеширования копии нового пароля и сравнения его со старым сохраненным хэшированным паролем, но он не изменяет значение, которое вы назначаете user.password, если только не используется какая-либо магия место. Просто проверьте в базе данных содержимое поля пользователя 'password' после обновления пароля – Sergey

+0

не только подтвердите пароль, как показано в моей ссылке, и автоматическое хеширование при создании. Должна ли существовать новая функция внутри таблицы, которая хешируется точно так же, как метод создания? Что касается второй части, я создал метод «retrieve_user_byemail (email)» в db, который запрашивает пользователя по электронной почте и возвращает объект пользователя со всей информацией пользователя. Я предполагаю, что это будет то, что будет отправить ссылку по электронной почте в views.py? Если это так, я не уверен в том, что вы указали автоматическую отправку и часть сплетения. – thesayhey