You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Django rest-auth与allauth时,未验证邮箱仍允许登录的问题

解决Django rest-auth + allauth 需邮箱验证后才能登录激活的问题

哈,这个场景我之前踩过坑,刚好能给你一步步捋清楚怎么配置:

1. 先把注册后的用户默认设为非活跃状态

rest-auth默认注册完就把is_active设为True了,咱们得自定义注册序列化器来改掉这个行为:

# 在你的app下新建/修改serializers.py
from rest_auth.registration.serializers import RegisterSerializer
from django.contrib.auth import get_user_model

User = get_user_model()

class CustomRegisterSerializer(RegisterSerializer):
    def save(self, request):
        # 先调用父类的save方法创建用户
        user = super().save(request)
        # 把用户设为非活跃
        user.is_active = False
        user.save()
        return user

然后在settings.py里指定用这个自定义序列化器:

REST_AUTH_REGISTER_SERIALIZERS = {
    'REGISTER_SERIALIZER': 'your_app_name.serializers.CustomRegisterSerializer',
}

2. 让邮箱验证后自动激活用户

现在注册后的用户是is_active=False,接下来要实现:用户点击验证链接后,自动把is_active改成True。这里有两种常用方法:

方法一:用信号监听邮箱验证事件

这是最简洁的方式,在你的app下新建signals.py:

from django.db.models.signals import post_save
from django.dispatch import receiver
from allauth.account.models import EmailAddress
from django.contrib.auth import get_user_model

User = get_user_model()

@receiver(post_save, sender=EmailAddress)
def activate_user_after_email_verify(sender, instance, **kwargs):
    # 当邮箱被标记为已验证,且用户还没激活时,激活用户
    if instance.verified and not instance.user.is_active:
        instance.user.is_active = True
        instance.user.save()

然后要在app的apps.py里注册这个信号,确保项目启动时加载:

from django.apps import AppConfig

class YourAppConfig(AppConfig):
    default_auto_field = 'django.db.models.BigAutoField'
    name = 'your_app_name'

    def ready(self):
        import your_app_name.signals

方法二:重写邮箱验证视图

如果信号的方式不满足你的定制需求,可以重写allauth的验证视图:

# views.py
from allauth.account.views import ConfirmEmailView
from django.contrib.auth import get_user_model

User = get_user_model()

class CustomConfirmEmailView(ConfirmEmailView):
    def post(self, *args, **kwargs):
        # 先执行父类的验证逻辑
        response = super().post(*args, **kwargs)
        # 获取当前验证邮箱对应的用户
        user = self.object.email_address.user
        # 激活用户
        if not user.is_active:
            user.is_active = True
            user.save()
        return response

然后在项目的urls.py里替换默认的验证路由:

from django.urls import path, include
from your_app_name.views import CustomConfirmEmailView

urlpatterns = [
    # ... 其他路由
    # 替换allauth的默认邮箱验证路由
    path('accounts/confirm-email/<str:key>/', CustomConfirmEmailView.as_view(), name='account_confirm_email'),
    path('rest-auth/', include('rest_auth.urls')),
    path('rest-auth/registration/', include('rest_auth.registration.urls')),
]

3. 可选:登录时强制检查邮箱是否验证

即使用户被激活了,也可以再加一层保障:登录时必须确保邮箱已验证。自定义登录序列化器:

# serializers.py
from rest_auth.serializers import LoginSerializer
from allauth.account.models import EmailAddress
from rest_framework import serializers

class CustomLoginSerializer(LoginSerializer):
    def validate(self, attrs):
        # 先调用父类的验证逻辑,拿到用户对象
        user = super().validate(attrs)
        # 检查该用户是否有已验证的邮箱
        has_verified_email = EmailAddress.objects.filter(user=user, verified=True).exists()
        if not has_verified_email:
            raise serializers.ValidationError("请先验证你的邮箱后再登录")
        return user

在settings.py里配置使用这个登录序列化器:

REST_AUTH_SERIALIZERS = {
    'LOGIN_SERIALIZER': 'your_app_name.serializers.CustomLoginSerializer',
}

4. 基础配置检查

最后别忘了确保settings.py里的allauth核心配置是正确的:

# 强制要求注册时提供邮箱
ACCOUNT_EMAIL_REQUIRED = True
# 强制邮箱验证,注册后自动发送验证邮件
ACCOUNT_EMAIL_VERIFICATION = "mandatory"
# 可选:设置用邮箱作为登录凭证(比用户名更合理)
ACCOUNT_AUTHENTICATION_METHOD = "email"
ACCOUNT_UNIQUE_EMAIL = True

这样一套配置下来,用户注册后is_active为False,必须点击邮件链接验证邮箱后,is_active才会被设为True,而且登录时也会检查邮箱是否验证,完全符合你的需求啦~

内容的提问来源于stack exchange,提问作者Bleh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 09:45:59