2010-08-30 35 views
0

我寫了一個代碼來恢復我的網站passwrod。用戶輸入他的電子郵件地址,我們給他發送一個新的密碼。另外,我們還將他的密碼更改爲最新的密碼。C#回滾sendemail

問題: 如果發送郵件的代碼失敗,我不能在數據庫中更改他的密碼,並且如果密碼更改失敗,我不能發送郵件。

請看:

public bool RecoverPassword(string email) 
     { 
      try 
      { 
       SceLoginMail sceEmail = new SceLoginMail(email, "Recuperação de senha", 5); 
       ChangeUserPassword(sceEmail.NovaSenha, email); 
       sceEmail.SendEmail(); 
       sceUsers.CommitOrRollBack(true); 
       return true; 
      } 
      catch (Exception ex) 
      { 
       sceUsers.CommitOrRollBack(false); 
       return false; 
      } 
     } 

我嘗試在DB回滾如果SendEmail method.But出現異常,我不能「回滾」 sendmail的方法,如果一個例外CommitOrRollback method.If拋出如此,系統將發送郵件並且不會在數據庫上進行更改。

任何意識?

+3

將這些「新」密碼保存在臨時密碼錶中。在用戶使用臨時密碼登錄之前,請勿更換舊密碼。 – 2010-08-30 20:15:41

+0

我想這是最好的解決方案 – ozsenegal 2010-08-30 20:27:33

+2

[offtopic]這是你得到的一個醜陋的API。在得到'sceUsers.CommitOrRollBack(true);'的意思之前,我必須多次閱讀它。你最好將這個方法分成兩個單獨的方法,名爲'Commit()'和'Rollback()'。如果你不擁有'SceLoginMail'類,你至少可以使用兩種擴展方法。[/ offtopic] – Steven 2010-08-30 21:02:56

回答

1

而不是重新設置密碼以響應「我丟失了我的密碼」請求,請向用戶發送一封電子郵件,其中包含一個唯一的,有時間限制的重置URL。只有在允許的時間內訪問該URL時才重置密碼。

這有兩個好處:如果郵件成功發送和接收

  1. 密碼僅重置。
  2. 如果賬戶所屬人以外的人執行了「我遺失了密碼」請求(無論是意外還是故意),合法賬戶持有人沒有意外地使他/她的密碼失效。
3

直到數據庫事務(以及其他影響新密碼有效性的任務)完成之後才發送電子郵件。這樣,如果它引發異常,SendEmail()調用永遠不會被執行。

+0

然後,如果在SendMail()方法中發生異常,我確實改變了他的密碼,並且沒有發送郵件。使用不會能夠訪問系統,導致他的密碼已經改變,他不知道什麼。 – ozsenegal 2010-08-30 20:15:11

+1

@ozsenegal - 爲那些邊緣情況提供客戶支持的電子郵件地址。如果網絡中斷和其他技術問題是一個真正的問題,請使用消息隊列來帶外發送電子郵件。但最終,只有這麼一個技術解決方案可以做到這一點:用戶可能只是提供了一個無效的(或不正確的)地址。 – 2010-08-30 20:18:09

+0

@ozsenegal - 當然,但你可以陷阱和(大概,除非你的郵件服務器着火)從/重試電子郵件恢復。如果絕對不能接受** **密碼更改或發生SendEmail,除非** BOTH **成功,則需要實現更復雜的邏輯以確定何時真正提交數據庫更改,而不是在異常處理程序中進行簡單回滾。 – 2010-08-30 20:20:13

2

如果您分配新密碼並且由於某種原因未發送,則無關緊要。用戶已經不知道他/她的密碼。該電子郵件不會顯示,他們會再次請求。因此,提交數據庫,並按照該順序進行發送。

0

請參閱,要求更改密碼和請求獲取更改密碼的電子郵件的操作是單獨的現象。

當用戶請求更改密碼時,您只需調用該語句即可用新密碼更新數據庫。更新後,請嘗試發送郵件。

最好有一個郵件發件箱。因此,當電子郵件發送失敗時,它會存儲在數據庫表發件箱中,並且應該在閾值時間後定期嘗試。

這將確保您繼續嘗試將該郵件發送給用戶。