我正在使用Django Rest Framework构建API。后来,该API应该由iOS和Android设备使用。我想允许我的用户使用Facebook和Google等oauth2提供程序进行注册。在这种情况下,他们根本不必在我的平台上创建帐户。但是,当我没有django-oauth-toolkit的Facebook / Google帐户时,用户也应该能够注册,所以我有自己的oauth2-provider。
对于外部提供程序,我使用的是python-social-auth,它可以正常工作并自动创建用户对象。
我希望客户端使用承载令牌进行身份验证,这对于与我的提供程序注册的用户来说效果很好(django-oauth-toolkit为Django REST框架提供了身份验证方案和权限类)。
但是,python-social-auth仅实现基于会话的身份验证,因此没有直接的方法可以代表由外部oauth2提供程序注册的用户发出经过身份验证的API请求。
如果我使用django-oauth-toolkit生成的access_token
,则执行如下请求:
curl -v -H "Authorization: Bearer <token_generated_by_django-oauth-toolkit>" http://localhost:8000/api/
但是,以下操作无效,因为没有针对Django REST Framework的相应身份验证方案,并且python-social-auth提供的AUTHENTICATION_BACKENDS仅适用于基于会话的身份验证:
curl -v -H "Authorization: Bearer <token_stored_by_python-social-auth>" http://localhost:8000/api/
在通过python-social-auth进行身份验证后,使用Django REST Framework提供的可浏览API可以正常工作,只有没有会话cookie的API调用才起作用。
我想知道解决此问题的最佳方法是什么。从我的角度来看,我基本上有两个选择:
答:当用户注册外部oauth2提供程序(由python-social-auth处理)时,请进入该过程以创建oauth2_provider.models.AccessToken并继续使用’oauth2_provider.ext.rest_framework.OAuth2Authentication’,现在还可以对在外部提供程序中注册的用户进行身份验证。建议使用此方法:https: //groups.google.com/d/msg/django-rest-framework/ACKx1kY7kZM/YPWFA2DP9LwJ
B:使用python-social-auth进行API请求身份验证。我可以通过编写自定义后端并使用register_by_access_token使自己的用户进入python-social-auth。但是,由于API调用无法利用Django会话,这意味着我将不得不为Django Rest Framework编写一个身份验证方案,该方案利用python-social-auth存储的数据。有关如何执行此操作的一些说明,请参见此处:
http : //psa.matiasaguirre.net/docs/use_cases.html#signup-by-oauth-access-token
http://blog.wizer.fr/2013/11 / angularjs-facebook-with-a-django-rest-api /
http://cbdev.blogspot.it/2014/02/facebook-login-with-angularjs-django.html
但是,据我了解,python-social-auth仅在登录时验证令牌,此后依赖Django会话。这意味着我将不得不找到一种方法来防止python-social-auth对每个无状态API请求执行整个oauth2-flow,而是对照存储在数据库中的数据进行检查,因为该数据库实际上并未针对查询进行优化存储为JSON(尽管我可以使用UserSocialAuth.objects.get(extra_data__contains =))。
我还必须注意验证访问令牌的范围,并使用它们来检查权限,这是django-oauth-toolkit已经完成的工作(TokenHasScope,required_scopes等等)。
目前,我倾向于使用选项A,因为django-oauth-toolkit提供了与Django Rest Framework的良好集成,并且可以立即获得所需的一切。唯一的缺点是我必须将python-social-auth检索到的access_tokens“注入” django-oauth-toolkit的AccessToken模型中,这在某种程度上让人感到不对,但这可能是迄今为止最简单的方法。
是否有人对此有异议或以不同的方式解决了相同的问题?我是否遗漏了一些明显的东西并使我的生活变得更加艰难?如果有人已经将django-oauth-toolkit与python-social-auth和外部oauth2提供程序集成在一起,我将非常感谢你提供的一些指示或意见。
实施OAuth的许多困难归结为了解授权流程应如何工作。这主要是因为这是登录的“起点”,并且在使用第三方后端(使用类似Python Social Auth之类的方法)时,你实际上要执行两次:一次用于API,一次用于第三方API。
使用你的API和第三方后端授权请求
你需要通过的身份验证过程是:
Mobile App -> Your API : Authorization redirect
Your API -> Django Login : Displays login page
Django Login -> Facebook : User signs in
Facebook -> Django Login : User authorizes your API
Django Login -> Your API : User signs in
Your API -> Mobile App : User authorizes mobile App
我在这里使用“ Facebook”作为第三方后端,但是任何后端的过程都是相同的。
从移动应用程序的角度来看,你仅重定向到/authorizeDjango OAuth Toolkit提供的网址。从那里开始,移动应用程序将一直等到到达回调URL,就像在标准OAuth授权流程中一样。几乎所有其他内容(Django登录名,社交登录名等)都在后台由Django OAuth Toolkit或Python Social Auth处理。
这也将与你使用的几乎所有OAuth库兼容,并且无论使用什么第三方后端,授权流程都将相同。它甚至可以处理需要支持Django的身份验证后端(电子邮件/用户名和密码)以及第三方登录的(常见)情况。
Mobile App -> Your API : Authorization redirect
Your API -> Django Login : Displays login page
Django Login -> Your API : User signs in
Your API -> Mobile App : User authorizes mobile app
在此还要注意的重要一点是,移动应用程序(可以是任何OAuth客户端)永远不会收到Facebook /第三方OAuth令牌。这非常重要,因为它可以确保你的API充当OAuth客户端和用户的社交帐户之间的中介。
Mobile App -> Your API : Authorization redirect
Your API -> Mobile App : Receives OAuth token
Mobile App -> Your API : Requests the display name
Your API -> Facebook : Requests the full name
Facebook -> Your API : Sends back the full name
Your API -> Mobile App : Send back a display name
否则,OAuth客户端将能够绕过你的API并代表你向第三方API 发出请求。
Mobile App -> Your API : Authorization redirect
Your API -> Mobile App : Receives Facebook token
Mobile App -> Facebook : Requests all of the followers
Facebook -> Mobile App : Sends any requested data
你会注意到,此时你将失去对第三方令牌的所有控制权。这特别危险,因为大多数令牌都可以访问广泛的数据,这为滥用提供了方便,并最终以你的名字为名。极有可能的是,那些登录你的API /网站的人并不打算与OAuth客户端共享他们的社交信息,而是希望你(尽可能多地)将信息保密,而是向所有人公开这些信息。
验证对你的API的请求
当移动应用程序随后使用你的OAuth令牌向你的API发出请求时,所有身份验证都会在后台通过Django OAuth Toolkit(或你的OAuth提供程序)进行。你所看到的只是User与你的请求相关联。
Mobile App -> Your API : Sends request with OAuth token
Your API -> Django OAuth Toolkit : Verifies the token
Django OAuth Toolkit -> Your API : Returns the user who is authenticated
Your API -> Mobile App : Sends requested data back
这很重要,因为在授权阶段之后,无论用户来自Facebook还是Django的身份验证系统,都不会造成任何影响。你的API只需要一个User即可使用,你的OAuth提供者就应该能够处理令牌的身份验证和验证。
与使用会话支持的身份验证时,Django REST框架对用户进行身份验证的方式没有太大不同。
Web Browser -> Your API : Sends session cookie
Your API -> Django : Verifies session token
Django -> Your API : Returns session data
Your API -> Django : Verifies the user session
Django -> Your API : Returns the logged in user
Your API -> Web Browser : Returns the requested dat
同样,所有这些都由Django OAuth Toolkit处理,并且不需要额外的工作来实现。
使用本机SDK
在大多数情况下,你将通过自己的网站对用户进行身份验证,并使用Python Social Auth处理所有内容。但是一个值得注意的例外是使用本地SDK时,因为身份验证和授权是通过本地系统处理的,这意味着你将完全绕过API。这对于需要与第三方登录的应用程序或根本不使用你的API的应用程序非常有用,但是当两者结合在一起时,这就是一场噩梦。
这是因为你的服务器无法验证登录名,并被迫假定该登录名是真实和真实的,这意味着它绕过了Python Social Auth为你提供的所有安全性。
Mobile App -> Facebook SDK : Opens the authorization prompt
Facebook SDK -> Mobile App : Gets the Facebook token
Mobile App -> Your API : Sends the Facebook token for authorization
Your API -> Django Login : Tries to validate the token
Django Login -> Your API : Returns a matching user
Your API -> Mobile App : Sends back an OAuth token for the user
你会注意到,这会在身份验证阶段跳过你的API,然后强制你的API对传入的令牌进行假设。但是,在某些情况下,这种风险可能值得承担,因此你应该在进行评估之前把它扔出去。你需要在用户的快速登录和本机登录之间进行权衡,并可能处理不良或恶意令牌。
问题内容: 我正在尝试开发一个JMS 独立应用程序 来读写MQSeries上的Queue。我的老板要求我使用 纯Java JMS (而不是ibm.mq lib)来执行此操作。 这是建立jms连接所需的信息: 您知道该怎么做?还是您有任何链接教我做到这一点。 问题答案: 这里的问题是“我的老板要求我使用纯Java JMS(不是ibm.mq lib)来做到这一点”的要求。JMS是一个规范,每个实现都必
问题内容: 我正在尝试使用node.js制作Samsung Smart TV应用程序。 在我的项目中,我想使我的应用程序与服务器PC通信。 根据许多网站,我可以使用“ jsonp”来做到这一点。 这是我发现的客户端代码。 而且,这是我发现的服务器端代码。 这些代码在我的PC(服务器PC)上正常工作,但是当我在其他计算机上打开客户端页面时,它不起作用。 控制台只给我这个日志: 我想使用jsonp处理
我想用Netty ChannelHandler用Gzip压缩和解压,我试了一段时间,但总是有点困难。我的代码如下: 有什么问题吗?
问题内容: 如何创建使芹菜任务看起来像的包装器?还是有更好的方法与Celery集成? Celery的创建者@asksol这样说: 将Celery用作异步I / O框架之上的分布式层是很常见的(提示:将CPU绑定的任务路由到prefork worker意味着它们不会阻塞事件循环)。 但是我找不到任何专门针对框架的代码示例。 问题答案: 如官方网站上所述,这可以通过Celery 5.0版实现: htt
问题内容: 我有一个带有MySQL的远程数据库,并且将我的应用程序用户的照片存储在数据库中,作为LONGTEXT类型的数据库的一行。 我使用Base64将照片转换为字符串。 我使用JSON和PHP连接到远程数据库,因此,我必须使用Base64,因为据我所知,JSON和PHP需要在参数上发送字符串,而使用Base64可以将照片转换为字符串。 可以,但是非常慢。当我加载100 KB的照片时,会花费很多
问题内容: 我目前正在使用Electron和MongoDB构建一个桌面应用程序。此应用程序的目的是在应用程序的本地范围内(而不是在服务器上)收集和存储各种客户的信息。我已经使用node.js对MongoDB进行了一些研究;但是我还没有找到在Electron中使用它的方法。 问题答案: 这是用于MongoDB管理的电子应用程序,您可以检查代码作为如何使用mongodb和electronic的示例。
问题内容: 它们都使用相同的语法来插入变量。例如,如果我想要以下内容 在我的下划线中,我的主要EJS中断,因为它试图替换用户名,并且主页中不存在此类变量。 问题答案: 我认为方括号默认情况下可以在EJS中使用: 而且,如果您需要更高级的知识,EJS github页面将介绍如何创建自定义标签: 我认为第二个“更高级”部分可能特定于服务器端应用程序 https://github.com/visionm
如本文所述,Guava ServiceManager可通过以下方式获得: 为了实现这一点,我在Guice模块中添加了以下内容: 在我的主课上, 如何获取已启动服务的实例? 附言:将服务设置为@Singleton感觉就像一个黑客。