dj-rest-auth 将社交注册限制到特定的电子邮件地址域

问题描述

我正在开始使用 dj-rest-auth,并且我有一个应用程序,它只允许用户通过谷歌登录。但是,我希望用户只能使用特定的 Google Apps 电子邮件域访问我的服务。

我将 dj-rest-auth 与 django-allauth 结合使用。

这是我尝试过的:我创建了这样的 allauth 适配器:

class CustomAccountAdapter(DefaultAccountAdapter):
    def is_open_for_signup(self,request):
        return False  # No email/password signups allowed


class CustomSocialAccountAdapter(DefaultSocialAccountAdapter):
    def is_open_for_signup(self,request,socialaccount):
        u = socialaccount.user
        return u.email.split("@")[1] == "mydomain.com"

在我的设置中我有

ACCOUNT_ADAPTER = "users.adapters.CustomAccountAdapter"
SOCIALACCOUNT_ADAPTER = "users.adapters.CustomSocialAccountAdapter"

使用此解决方案,如果用户尝试使用有效的电子邮件登录,一切正常,而如果他们使用不允许的电子邮件域,我会在控制台中收到此错误

Traceback (most recent call last):
  File "/home/my_user/.local/share/virtualenvs/my_project-mzTAT1MS/lib/python3.8/site-packages/django/core/handlers/exception.py",line 47,in inner
    response = get_response(request)
  File "/home/my_user/.local/share/virtualenvs/my_project-mzTAT1MS/lib/python3.8/site-packages/django/core/handlers/base.py",line 181,in _get_response
    response = wrapped_callback(request,*callback_args,**callback_kwargs)
  File "/home/my_user/.local/share/virtualenvs/my_project-mzTAT1MS/lib/python3.8/site-packages/django/views/decorators/csrf.py",line 54,in wrapped_view
    return view_func(*args,**kwargs)
  File "/home/my_user/.local/share/virtualenvs/my_project-mzTAT1MS/lib/python3.8/site-packages/django/views/generic/base.py",line 70,in view
    return self.dispatch(request,*args,**kwargs)
  File "/home/my_user/.local/share/virtualenvs/my_project-mzTAT1MS/lib/python3.8/site-packages/django/utils/decorators.py",line 43,in _wrapper
    return bound_method(*args,**kwargs)
  File "/home/my_user/.local/share/virtualenvs/my_project-mzTAT1MS/lib/python3.8/site-packages/django/views/decorators/debug.py",line 89,in sensitive_post_parameters_wrapper
    return view(request,**kwargs)
  File "/home/my_user/.local/share/virtualenvs/my_project-mzTAT1MS/lib/python3.8/site-packages/dj_rest_auth/views.py",line 48,in dispatch
    return super(LoginView,self).dispatch(*args,**kwargs)
  File "/home/my_user/.local/share/virtualenvs/my_project-mzTAT1MS/lib/python3.8/site-packages/rest_framework/views.py",line 505,in dispatch
    response = self.handle_exception(exc)
  File "/home/my_user/.local/share/virtualenvs/my_project-mzTAT1MS/lib/python3.8/site-packages/rest_framework/views.py",line 465,in handle_exception
    self.raise_uncaught_exception(exc)
  File "/home/my_user/.local/share/virtualenvs/my_project-mzTAT1MS/lib/python3.8/site-packages/rest_framework/views.py",line 476,in raise_uncaught_exception
    raise exc
  File "/home/my_user/.local/share/virtualenvs/my_project-mzTAT1MS/lib/python3.8/site-packages/rest_framework/views.py",line 502,in dispatch
    response = handler(request,line 138,in post
    self.serializer.is_valid(raise_exception=True)
  File "/home/my_user/.local/share/virtualenvs/my_project-mzTAT1MS/lib/python3.8/site-packages/rest_framework/serializers.py",line 234,in is_valid
    self._validated_data = self.run_validation(self.initial_data)
  File "/home/my_user/.local/share/virtualenvs/my_project-mzTAT1MS/lib/python3.8/site-packages/rest_framework/serializers.py",line 436,in run_validation
    value = self.validate(value)
  File "/home/my_user/.local/share/virtualenvs/my_project-mzTAT1MS/lib/python3.8/site-packages/dj_rest_auth/registration/serializers.py",line 134,in validate
    complete_social_login(request,login)
  File "/home/my_user/.local/share/virtualenvs/my_project-mzTAT1MS/lib/python3.8/site-packages/allauth/socialaccount/helpers.py",line 151,in complete_social_login
    return _complete_social_login(request,sociallogin)
  File "/home/my_user/.local/share/virtualenvs/my_project-mzTAT1MS/lib/python3.8/site-packages/allauth/socialaccount/helpers.py",line 172,in _complete_social_login
    ret = _process_signup(request,line 38,in _process_signup
    return render(
  File "/home/my_user/.local/share/virtualenvs/my_project-mzTAT1MS/lib/python3.8/site-packages/django/shortcuts.py",line 19,in render
    content = loader.render_to_string(template_name,context,using=using)
  File "/home/my_user/.local/share/virtualenvs/my_project-mzTAT1MS/lib/python3.8/site-packages/django/template/loader.py",line 62,in render_to_string
    return template.render(context,request)
  File "/home/my_user/.local/share/virtualenvs/my_project-mzTAT1MS/lib/python3.8/site-packages/django/template/backends/django.py",line 61,in render
    return self.template.render(context)
  File "/home/my_user/.local/share/virtualenvs/my_project-mzTAT1MS/lib/python3.8/site-packages/django/template/base.py",line 170,in render
    return self._render(context)
  File "/home/my_user/.local/share/virtualenvs/my_project-mzTAT1MS/lib/python3.8/site-packages/django/test/utils.py",line 96,in instrumented_test_render
    return self.nodelist.render(context)
  File "/home/my_user/.local/share/virtualenvs/my_project-mzTAT1MS/lib/python3.8/site-packages/django/template/base.py",line 938,in render
    bit = node.render_annotated(context)
  File "/home/my_user/.local/share/virtualenvs/my_project-mzTAT1MS/lib/python3.8/site-packages/django/template/base.py",line 905,in render_annotated
    return self.render(context)
  File "/home/my_user/.local/share/virtualenvs/my_project-mzTAT1MS/lib/python3.8/site-packages/django/template/loader_tags.py",line 150,in render
    return compiled_parent._render(context)
  File "/home/my_user/.local/share/virtualenvs/my_project-mzTAT1MS/lib/python3.8/site-packages/django/test/utils.py",in render
    result = block.nodelist.render(context)
  File "/home/my_user/.local/share/virtualenvs/my_project-mzTAT1MS/lib/python3.8/site-packages/django/template/base.py",in render_annotated
    return self.render(context)
  File "/home/my_user/.local/share/virtualenvs/my_project-mzTAT1MS/lib/python3.8/site-packages/django/template/defaulttags.py",line 312,in render
    return nodelist.render(context)
  File "/home/my_user/.local/share/virtualenvs/my_project-mzTAT1MS/lib/python3.8/site-packages/django/template/base.py",line 446,in render
    url = reverse(view_name,args=args,kwargs=kwargs,current_app=current_app)
  File "/home/my_user/.local/share/virtualenvs/my_project-mzTAT1MS/lib/python3.8/site-packages/django/urls/base.py",line 87,in reverse
    return iri_to_uri(resolver._reverse_with_prefix(view,prefix,**kwargs))
  File "/home/my_user/.local/share/virtualenvs/my_project-mzTAT1MS/lib/python3.8/site-packages/django/urls/resolvers.py",line 685,in _reverse_with_prefix
    raise noreverseMatch(msg)
django.urls.exceptions.noreverseMatch: Reverse for 'account_login' not found. 'account_login' is not a valid view function or pattern name.
[17/Mar/2021 18:49:42] "POST /dj-rest-auth/google HTTP/1.1" 500 246781

我想要做的是让我的 django 应用程序向用户(或类似用户)发送 403 响应,其中包含一条消息,例如“您只能使用 [at] 任何电子邮件地址访问此服务”。 我试图弄清楚 dj-rest-auth 视图在哪一点调用用户适配器以及如何处理失败并实现我所追求的目标。

感谢任何指导。

解决方法

当你返回 is_open_for_signup==False 时,django-allauth 在内部返回一个模板:

if not get_adapter(request).is_open_for_signup(request,sociallogin):
        return render(
            request,"account/signup_closed." + account_settings.TEMPLATE_EXTENSION,)

该模板扩展了模板 account/base.html(在 django-allauth 项目中),并且在此模板中您定义了有问题的 URL <li><a href="{% url 'account_login' %}">Sign In</a></li>

您可以覆盖您的 signup_closed.html 模板并解决此错误,但如果您需要返回 Json(由于 API),您应该使用您自己的 django-allauth 实现。