OAuth2:使用电子邮件而不是用户名进行身份验证
Posted
技术标签:
【中文标题】OAuth2:使用电子邮件而不是用户名进行身份验证【英文标题】:OAuth2: authenticate with email instead of username 【发布时间】:2016-02-26 21:19:11 【问题描述】:我将 OAuth2 与 django-oauth-toolkit django-rest-framework 一起使用。
我通常通过以下方式对我的用户进行身份验证,以获得令牌:
curl -X POST -d "grant_type=password&username=new_user&password=new_user" -u "GZwzDjPM89BceT8a6ypKGMbXnE4jWSzsyqbM3dlK:" http://localhost:8000/o/token/
有没有办法使用电子邮件而不是用户名来验证我的用户?
谢谢!
【问题讨论】:
【参考方案1】:是的!可以通过在用户模型中将电子邮件设置为username
来实现。
class User(AbstractBaseUser, PermissionsMixin):
email = models.EmailField(
verbose_name='email address',
max_length=255,
unique=True,
)
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=30)
USERNAME_FIELD = 'email'
然后电子邮件现在可以在请求中用作username
。
curl -X POST -d "grant_type=password&username=test@test.com&password=new_user" -u "GZwzDjPM89BceT8a6ypKGMbXnE4jWSzsyqbM3dlK:" http://localhost:8000/o/token/
【讨论】:
django 1.11 中的新功能。对我来说有点晚了,但很高兴知道,谢谢!【参考方案2】:如果您不想(或不能)创建自定义用户模型,这里有一个简单的解决方案:只需像这样覆盖 rest_framework_social_oauth2.views.TokenView
:
from django.contrib.auth import get_user_model
import rest_framework_social_oauth2.views
class TokenView(rest_framework_social_oauth2.views.TokenView):
def create_token_response(self, request):
email = request.POST.pop('email', None)
if email:
username = get_user_model().objects.filter(email=email[0]).values_list('username', flat=True).last()
request.POST['username'] = username
return super(TokenView, self).create_token_response(request)
然后,在您的 urls.conf
中将此自定义视图连接到 oauth/token
模式,例如:
urlpatterns = [
url(r'^oauth/token', my_auth.TokenView.as_view()), # The customized TokenView
url(r'^oauth/', include('rest_framework_social_oauth2.urls')), # Original URLs
]
【讨论】:
url 应该是oauth/token/
以覆盖 oauth2 的默认 url【参考方案3】:
我不知道为什么这个问题从未得到回答,但无论如何,我希望我的回答对遇到这个问题的人也有用:
丑陋但快速的方法:
在您的 POST 请求中将电子邮件作为用户名发送,然后找到其真实用户名并用此数据替换您的 POST 请求;所有这些都在你的中间件中:
class DisableCSRF(object):
"""Middleware for disabling CSRF in a specified app name.
"""
def process_request(self, request):
"""Preprocess the request.
"""
if (resolve(request.path_info).app_name == "api") or (
resolve(request.path_info).namespace == "oauth2_provider"):
if resolve(request.path_info).namespace == "oauth2_provider":
post_data = request.POST.copy()
true_username = User.objects.get(
email=request.POST.get("username")
).username
post_data["username"] = true_username
request.POST = post_data
setattr(request, '_dont_enforce_csrf_checks', True)
else:
pass # check CSRF token validation
优雅又好的实践方式:
创建您自己的类以请求身份验证令牌,以便您可以接收电子邮件作为您的用户名。您甚至可以添加更多自定义身份验证,例如 Facebook 或 Google 登录。这绝对是最好的方法,但它需要一些时间来开发,所以如果你有足够的时间来实现它,这取决于你。
希望现在回答这个问题还为时不晚。
【讨论】:
【参考方案4】:knaperek 的回答不适合我。 根据他的代码,我最终得到了以下对我的案例非常有效的解决方案:
import json
from django.http import HttpResponse
from django.contrib.auth import get_user_model
from oauth2_provider.views.base import TokenView
from oauth2_provider.models import get_access_token_model
from oauth2_provider.signals import app_authorized
from django.utils.decorators import method_decorator
from django.views.decorators.csrf import csrf_exempt
from django.views.decorators.debug import sensitive_post_parameters
from django.contrib.auth import get_user_model
@method_decorator(csrf_exempt, name="dispatch")
class TokenView(TokenView):
@method_decorator(sensitive_post_parameters("password"))
def post(self, request, *args, **kwargs):
request.POST = request.POST.copy()
email = request.POST.pop('email', None)
request.POST['username'] = get_user_model().objects.filter(email=email[0]).values_list('username', flat=True).last()
url, headers, body, status = self.create_token_response(request)
if status == 200:
access_token = json.loads(body).get("access_token")
if access_token is not None:
token = get_access_token_model().objects.get(token=access_token)
app_authorized.send(sender=self, request=request, token=token)
response = HttpResponse(content=body, status=status)
for k, v in headers.items():
response[k] = v
return response
【讨论】:
以上是关于OAuth2:使用电子邮件而不是用户名进行身份验证的主要内容,如果未能解决你的问题,请参考以下文章
使用 Spring Boot OAuth2 针对 Google 进行身份验证时如何将 google 用户电子邮件发送到白名单用户
使用自定义数据库而不是 ASPNETDB 的 ASP.NET MVC 身份验证?
如何使用 Twisted 通过 OAuth2.0 身份验证检查 Gmail