<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"><channel><title>نوشته های mahdi hoseyni</title><link>https://virgool.ir/feed/@mahdihos38</link><description></description><language>fa</language><pubDate>2026-11-12 15:21:54</pubDate><image><url>https://files.virgool.ir/upload/users/2304266/avatar/avatar.png</url><title>mahdi hoseyni</title><link>https://virgool.ir/@mahdihos38</link></image><item><title>پیاده سازی گوگل 2FA در جنگو</title><link>https://virgool.ir/@mahdihos38/پیاده-سازی-گوگل-2fa-در-جنگو-ywmnbhdvdafp</link><description>روش Google Authenticator یک احراز هویت مبتنی بر نرم‌افزار توسط Google عه که خدمات تأیید دو مرحله‌ای را با استفاده از الگوریتم گذرواژه یکبار مصرف مبتنی بر زمان و الگوریتم رمز عبور یک‌بار مبتنی بر HMAC برای احراز هویت کاربران برنامه‌های نرم‌افزاری پیاده‌سازی می‌کنه.برای پیاده سازی این روش تو جنگو اول یه مدل به این شکل میسازیمclass AuthInformation(models.Model):&#xA;    secret_key = models.CharField(max_length=512 , unique=True)&#xA;    user = models.OneToOneField(&#39;account.User&#39; , on_delete=models.CASCADE)من از کتابخونه pyotp استفاده کردم که با این دستور نصب میشه:pip install pyotp  داکیومنت این کتابخونه رو هم میتونید از اینجا بخونید.https://pyotp.readthedocs.io/en/stable/معمولا تو سایت ها دیدیم که این روش برای اهراز هویت  رو خوده کاربر فعالش میکنه پس نیازه یه فیلد بولین به مدل یوزر اضافه کنیم.من فیلد is_2FA_activate رو تو کلاس یوزر به این شکل اضافش کردم:class User(AbstractUser):&#xA;    is_2FA_active = models.BooleanField(default=False)&#xA;یه api هم نیازه که کاربر اونو کال کنه و این فیلد رو ترو کنه. وقتی کاربر این فیلد رو کال میکنه از مدل AuthInformation که ساخته بودیم برا این یوزر هم بسازیم.@decorators.api_view([&#39;GET&#39;, ])&#xA;@decorators.permission_classes([perms.IsAuthenticated, ])&#xA;def active_2FA(request):&#xA;    import pyotp&#xA;    from authentication.models import AuthInformation&#xA;    user = request.user&#xA;    user.is_2FA_active = True&#xA;    user.save()&#xA;    while True:&#xA;        auth, crt = AuthInformation.objects.get_or_create(&#xA;            user=user,&#xA;        )&#xA;        if crt:&#xA;            try:&#xA;                secret_key = pyotp.random_base32()&#xA;                auth.secret_key = secret_key&#xA;                auth.save()&#xA;                break&#xA;            except:&#xA;                pass&#xA;        else:&#xA;            break&#xA;&#xA;    return response.Response({&#39;result&#39; :&#34;با موفقیت فعال شد.&#34; , &#34;secret_key&#34; : auth.secret_key})سکرت کی مورد نیاز برای کاربر توسط تابع:  pyotp.random_base32()ساخته میشه.حالا باید سکرت کیی که توسط برنامه ساخته شده رو به یه نرم افزار تولید این کد بدیم تا اون رو استفاده کنیم.(این روش جزو Time-based OTP ها هستش و ما از توابع Time-Based های کتابخونه pyotp استفاده میکنیم.)من از اکستنشن Authenticator  برای این کار استفاده کردم.حالا کد وریفای رو در ادامه داریم:username = request.data.get(&#39;username&#39;)&#xA;password = request.data.get(&#39;password&#39;)&#xA;user = authenticate(username=username, password=password)&#xA;&#xA;if not user:&#xA;    return response.Response({&#39;detail&#39;: &#34;نام کاربری یا رمز عبور اشتباه است&#34;}, status=status.HTTP_400_BAD_REQUEST)&#xA;&#xA;if user.is_2FA_active:&#xA;    from authentication.models import AuthInformation&#xA;    import pyotp&#xA;&#xA;    auth_info_detail = AuthInformation.objects.get(user_id = user.id)&#xA;    secret_key = auth_info_detail.secret_key&#xA;    pin = request.data.get(&#39;pin&#39;)&#xA;    if pin is None:&#xA;        return response.Response({&#34;detail&#34;: &#34;کد وارد نشده است.&#34;}, status=status.HTTP_400_BAD_REQUEST)&#xA;    totp = pyotp.TOTP(secret_key)&#xA;    verification_status = totp.verify(pin)&#xA;    if verification_status:&#xA;        pass&#xA;    else:&#xA;        return response.Response({&#34;detail&#34; : &#34;کد وارد شده اشتباه است.&#34;}, status = status.HTTP_400_BAD_REQUEST)&#xA;&#xA;&#xA;&#xA;data = serializers.UserSerializers(user).data&#xA;token = get_tokens_for_user(user)&#xA;data[&#39;access&#39;] = token[&#39;access&#39;]&#xA;data[&#39;refresh&#39;] = token[&#39;refresh&#39;]&#xA;&#xA;return response.Response(data, status=status.HTTP_200_OK)من این تابع رو به صورت POST نوشتم که باید نام کاربری ، رمز عبور و کد جنربت شده رو(درصورت فعال بودن این روش برای کاربر) ارسال کنید که اگه درست بود توکن کاربر بهش برگردونده بشه.امیدوارم مفید باشه براتون.</description><category>mahdi hoseyni</category><author>mahdi hoseyni</author><pubDate>Sat, 25 Mar 2023 17:48:57 +0330</pubDate></item></channel></rss>