2016-09-16 6 views
1

私は、新しいパスワードフォームにリダイレクトするリンクをユーザーに電子メールで送信してパスワードリセットを実装しようとしています。Django Password Resest via Email

例:this questionthis siteです。

しかし、私の問題は少し異なります。私はユーザーを含むローカルデータベースを持っていないので、自分の属性に対して操作を実行することはできません。私はAPI(ユーザーID、ユーザーメール、ユーザーパスワード)を介してユーザーデータを受け取ります。このリンクは、ユーザーがが誰であるかを教えてとに私を許可する彼/彼女のパスワードをリセットするように?への最善の方法は、ユーザーに電子メールを介して送信するための一意のリンクを生成しているので、

、また、どのように私はそれをurls.pyにリダイレクトすることができますか? このリンクを一度だけ使用していただけたらと思います。

私のviews.pyは、このようなものです:

def password_reset_form(request): 

if request.method == 'GET': 
    form = PasswordResetForm() 
else: 
    form = PasswordResetForm(request.POST) 

    if form.is_valid(): 
     email = form.cleaned_data['email'] 

     content_dict = { 
      'email': email, 
      'domain': temp_data.DOMAIN, 
      'site_name': temp_data.SITE_NAME, 
      'protocol': temp_data.PROTOCOL, 
      } 

     subject = content_dict.get('site_name')+ ' - Password Reset' 
     content = render_to_string('portal/password_reset_email.html', content_dict) 
     send_mail(subject, content, temp_data.FIBRE_CONTACT_EMAIL, [email]) 

     return render(request, 'portal/password_reset_done.html', {'form': form,}) 

return render(request, 'portal/password_reset_form.html', {'form': form,}) 

そしてテンプレートは、私が送信していた電子メールは、次のとおりです。

{% autoescape off %} 

You're receiving this e-mail because we got a request to reset the password for your user account at {{ site_name }}. 

Please go to the following page and choose a new password: 

{% block reset_link %} 
{{ protocol }}://{{ domain }}/[***some unique link***] 
{% endblock %} 

If you didn't request a password reset, let us know. 

Thank you. 

The {{ site_name }} team. 

{% endautoescape %} 

おかげで、みんな。

+0

@KlausD。、いいえパスワードの塩です。 – revy

答えて

1

問題は一意のリンクを生成することではなく、ユーザーIDまたは電子メールに関するどこかの情報を格納し、トークンを生成する必要があります。そうしないと、どのユーザーがどのトークンを使用すべきか分かりません。ユーザーがパスワードをリセットすると、彼のレコード(彼のトークン)を削除することができます。

あなたは基本的にはこのように見える可能性がある、でもsqliteの中で、最も簡単なモデルを作成することができます。

class UserTokens(model.Models): 
    email = models.EmailField(max_length=50) 
    token = models.CharField(max_length=50) 

その後、あなたがメールを送信する際にはこのような何かます

def password_reset_form(request): 

    #your logic here 
    # form post 

    usr, created = UserToken.objects.get_or_create(email=form.email) 
    if usr.token: 
     #send this token to him 
    else: 
     usr.token = ''.join(
    random.choice(string.ascii_uppercase + string.digits) for _ in range(50)) 
     usr.save() 
     #also send this token to him 

を次に、あなたが作成しますそのトークンを検索する新しいビューまたはapiビューが見つかった場合、パスワードをリセットさせます。そうでない場合は、404エラーを発生させるか、パスワードをリセットするリンクがないことを知らせます。

これは私の電話から書かれていますので、誤植を心配してください。

PS。

url(r'unsubscribe/(?P<quit_hash>[\w\d]+)/$', 'quit_newsletter_or_somethin', name='quit_newsletter_or_somethin') 
+1

この回答に記載されているアプローチには、次のような問題があります。 ** 1 **使用直後に明示的なトークンの削除が行われなければなりません。 ** 2 **パスワードと同じように、トークンはよくハッシュ化されていて、塩漬けされています(https://news.ycombinator.com/item?id=1263128)。 ** 3 ** Pythonは 'ランダム '状態であるため、セキュリティ上の目的では使用しないでください。警告にご注意ください! [Djangoはフォールバックとしてのみバニラの 'random'を使用し、最初に種を蒔きます。](https://github.com/django/django/blob/master/django/utils/crypto.py#L54) – Tony

+1

はい@AntonStrogonoff私は、私が言ったように、この答えは電話で書かれました。しかしこれは単なる一般的な考え方であり、これを使用してさらに発展させることができます。 – sebb

1

私はジャンゴから、一般的なロジックを借りて、あなたの特定の条件に適合するようにお勧めしたい:

あなたがPasswordResetTokenGenerator._make_token_with_timestamp()から見ることができるように、そのALGOは、ユーザーの最後のログに依存していますあなたが消費するAPIがそれに対応する必要があるためです。

上記の暗号化で使用されているのと同じユーティリティ関数をインポートすることができます。十分にテストされたソリューションに頼る方がよいでしょう。深い内部は、新しいDjangoのバージョンに更新するときにはリリースノートなしで変更される傾向がありますので注意してください。

ローカルデータベースのユーザー名とともに、慎重にランダムに生成されたリセットコードを単純に保存し、ユーザーがリセットフォームにアクセスしたときに削除することもできますが、それはあまり控えめで、

0

車輪の再発明をしないでください:あなたはまた、ちょうどこのようなものを作るのURL

について尋ねました。この種のものには django-allauthを使用してください。図書館はよく管理され、積極的に発展しています。

関連する問題