2015-11-13 90 views
4

我想驗證金字塔login目的的加密密碼。因此,如果用戶和密碼匹配,則系統將授權用戶。目前,我發現編寫一個函數來比較密碼時,在數據庫中進行加密並且輸入到Pyramid的login表單中的密碼未加密時很困難。現在,我沒有在登錄視圖中進行驗證。存儲和驗證加密的密碼登錄金字塔

我對使用安全措施/代碼的整個過程感到陌生,並且希望做到這一點。我在看這Auth tutorial,但User類中的加密稍有不同,我使用Pyramid的Auth套件。任何指導如何成功和巧妙地做到這一點將不勝感激。

軟件:Python的2.7.9,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, 
     ) 
+1

請不要使用sha224存儲用戶密碼,請使用合適的庫,以便您安全地存儲密碼(suc h as [passlib](http://pythonhosted.org/passlib/))。 –

回答

5

請修改您的代碼,添加了優秀passlib庫,並使用bcrypt爲使用安全密碼存儲哈希算法。

在你的項目的setup.py添加以下的要求:

  • bcrypt
  • passlib

然後用下面的代碼片段模型:

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) 
+0

謝謝你的代碼!我不知道。我更新了我的代碼以反映這個更強大的系統。乾杯! – thesayhey

+1

最近引起了我的注意,使用上下文管理器可能會有所幫助,因爲它允許您在時間到時輕鬆地切換到新算法:https://pythonhosted.org/passlib/lib/passlib.context-tutorial。 html#module-passlib.context –

+1

這裏的代碼現在開始引發一些問題:'passlib.registry:DEBUG:registered'bcrypt'handler: passlib.handlers.bcrypt: DEBUG:'bcrypt'後端缺少'$ 2 $'支持' – thesayhey

1

警告不安全的代碼後記

下面的代碼不是安全和安全的方式來存儲/驗證用戶密碼。請使用提供安全密碼存儲的庫,例如passlib,它專門用於安全存儲密碼。


您在使用User.__init__self.password = hashlib.sha224(password).hexdigest()散列用戶的密碼。只要使用類似的方法來驗證它:

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 
+0

我試圖驗證沒有'哈希...'代碼的增加。這很簡單!非常感謝你澄清。我爲此瘋狂了。還有一個問題。我注意到,如果用戶登錄錯誤,它不會顯示失敗的登錄消息。這是由於返回後放置消息嗎?我應該移動它嗎?所以我可以重定向創建一個帳戶? – thesayhey

+1

@thesayhey是的,你的'message ='失敗登錄'似乎縮進了太多。刪除4個空格,你應該很好。 –

+0

請不要直接使用sha224作爲密碼。使用合適的庫,例如passlib! –