使用 Django 和 python-social-auth 进行 Facebook 重定向
Facebook redirection with Django and python-social-auth
要通过 python-social-auth
在本地测试使用 Facebook 登录我的 django
应用程序的能力,我遵循了以下步骤:
- 在
/etc/hosts
中定义从127.0.0.1
到www.florian.com
的映射
- 在 Facebook 登录 --> 设置
的字段 OAuth valid URI redirect
中添加 http://www.florian.com:8000/login/facebook
和 http://www.florian.com:8000/complete/facebook
- 运行
python manage.py runserver www.florian.com:8000
但是,当访问 http://www.florian.com:8000/login/facebook
时,出现以下错误:
Can't Load URL: The domain of this URL isn't included in the app's domains. To be able to load this URL, add all domains and subdomains of your app to the App Domains field in your app settings.
然而,当我使用 Facebook 登录 --> 设置中可用的字段检查此 URL 的有效性时,它是可以的。
这是我的 Django 文件:
urls.py:
from django.conf.urls import url, include
from django.contrib import admin
from rest_framework import routers
from backend import views
from webapp import views as webapp_views
from django.contrib.auth import views as auth_views
router = routers.SimpleRouter()
router.register(r'users', views.UserViewSet, 'User')
router.register(r'games', views.GameViewSet, 'Game')
urlpatterns = [
url(r'^$', webapp_views.home, name='home'),
url('', include('social_django.urls', namespace='social')),
# FACEBOOK login/registration from Web
url(r'^login/$', auth_views.login, name='login'),
url(r'^logout/$', auth_views.logout, name='logout'),
url('', include('social_django.urls', namespace='social')),
url(r'^test/', webapp_views.test),
url(r'^admin/', admin.site.urls),
url(r'^connect/', views.CustomObtainAuthToken.as_view()),
url(r'^membership_create/', views.MembershipCreate.as_view()),
# Facebook login/registration from REST API
url(r'^auth/connect_with_fb/', views.ConvertTokenViewWithData.as_view()),
# standard Django login/registration from REST API
url(r'^auth/connect_with_credentials/', views.TokenViewWithData.as_view()),
url(r'^debug/', views.UserLoginAndIdView.as_view()),
url(r'^auth/', include('rest_framework_social_oauth2.urls'),
)
]
urlpatterns += router.urls
login.html
{% block content %}
<h2>Login</h2>
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Login</button>
</form>
<br>
<p><strong>-- OR --</strong></p>
<a href="{% url 'social:begin' 'facebook' %}">Login with Facebook</a>
{% endblock %}
settings.py
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'rest_framework.authtoken',
'rest_framework',
'oauth2_provider',
'social_django',
'rest_framework_social_oauth2',
'backend',
'webapp',
]
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'social_django.middleware.SocialAuthExceptionMiddleware', # <--
]
ROOT_URLCONF = 'WMC.urls'
SOCIAL_AUTH_URL_NAMESPACE = 'social'
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [ os.path.join(BASE_DIR, 'templates'),
os.path.join(BASE_DIR, 'webapp/templates')],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
'social_django.context_processors.backends',
'social_django.context_processors.login_redirect',
],
},
},
]
WSGI_APPLICATION = 'WMC.wsgi.application'
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'oauth2_provider.contrib.rest_framework.OAuth2Authentication',
'rest_framework_social_oauth2.authentication.SocialAuthentication',
),
}
AUTHENTICATION_BACKENDS = (
# Facebook OAuth2
'social_core.backends.facebook.FacebookAppOAuth2',
'social_core.backends.facebook.FacebookOAuth2',
# django-rest-framework-social-oauth2
'rest_framework_social_oauth2.backends.DjangoOAuth2',
# Django
'django.contrib.auth.backends.ModelBackend',
)
# Django client_secret for OAuth Toolkit for django-rest-social-auth
CLIENT_SECRET = '***********************************************************************************'
# Facebook configuration
SOCIAL_AUTH_FACEBOOK_KEY = '***********'
SOCIAL_AUTH_FACEBOOK_SECRET = '*****************************'
# Database
# https://docs.djangoproject.com/en/1.10/ref/settings/#databases
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
}
}
# Password validation
# https://docs.djangoproject.com/en/1.10/ref/settings/#auth-password-validators
AUTH_PASSWORD_VALIDATORS = [
{
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
},
]
# Define SOCIAL_AUTH_FACEBOOK_SCOPE to get extra permissions from facebook. Email is not sent by default, to get it, you must request the email permission:
SOCIAL_AUTH_FACEBOOK_SCOPE = ['email']
SOCIAL_AUTH_FACEBOOK_PROFILE_EXTRA_PARAMS = {
'fields': 'id, name, email'
}
# Internationalization
# https://docs.djangoproject.com/en/1.10/topics/i18n/
LANGUAGE_CODE = 'en-us'
TIME_ZONE = 'UTC'
USE_I18N = True
USE_L10N = True
USE_TZ = True
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/1.10/howto/static-files/
STATIC_URL = '/static/'
尝试添加
ALLOWED_HOSTS = [`.florian.com`]
到settings.py
假设您正在使用安装了 Nginx 的 Linux 开发环境。
我不建议您使用 'real' url 在本地进行测试。你应该试试 florian.local
.
在你的 /etc/hosts
中添加这样一行:
127.0.0.1 florian.local
将 florian.local
添加到 settings.py
文件中的 ALLOWED_HOSTS
。
在您的 /etc/nginx/sites-available
中创建一个文件 florian
(touch florian),其中包含如下内容:</p>
<pre><code>upstream florian {
server 127.0.0.1:8000;
}
server {
listen 80;
server_name florian.local;
keepalive_timeout 360;
client_max_body_size 100M;
location / {
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Protocol $scheme;
proxy_pass http://florian;
proxy_connect_timeout 600;
proxy_send_timeout 600;
proxy_read_timeout 600;
send_timeout 600;
}
}
CD 到 sites-enabled
并为之前创建的文件创建软 link:
ln -s ../sites-available/florian .
最后别忘了重启nginx,如:
sudo service nginx restart
运行 您的本地开发服务器:
./manage.py runserver 8000
,
然后您可以通过 http://127.0.0.1:8000
或 http://florian.local
.
访问它
我已使用此方法成功通过 Facebook、Twitter 和 Google 帐户向我的本地应用程序进行身份验证。
自 social_core
库的 1.6.0
版本(python-social-auth
的一部分)起,FacebookOAuth2
后端的字段 REDIRECT_STATE
已设置为 False
.
由于我使用的是 1.5.0
版本(其中 REDIRECT_STATE=True
),并且每次调用 Facebook 登录时 redirect_state
都会发生变化,因此我的应用无法处理这样的动态行为。
因此,将 social_core
升级到版本 1.7.0
即可解决问题。
我不确定是否已经回答了这个问题,但您的网站应该使用 https 而不是 http。
示例:
而不是http://www.florian.com:8000/complete/facebook
使用了这个:https://www.florian.com:8000/complete/facebook
Facebook 不接受 http 站点。
希望对您有所帮助。
对于儿童:
在 Facebook 开发者网站的 "Client OAuth Settings" 选项卡中将 https://yourdomain.example/oauth/complete/facebook/ 添加到 "Valid OAuth Redirect URIs"。
/oauth/ - 它是你的 django 社交的名称 url。
要通过 python-social-auth
在本地测试使用 Facebook 登录我的 django
应用程序的能力,我遵循了以下步骤:
- 在
/etc/hosts
中定义从 - 在 Facebook 登录 --> 设置 的字段
- 运行
python manage.py runserver www.florian.com:8000
127.0.0.1
到www.florian.com
的映射
OAuth valid URI redirect
中添加 http://www.florian.com:8000/login/facebook
和 http://www.florian.com:8000/complete/facebook
但是,当访问 http://www.florian.com:8000/login/facebook
时,出现以下错误:
Can't Load URL: The domain of this URL isn't included in the app's domains. To be able to load this URL, add all domains and subdomains of your app to the App Domains field in your app settings.
然而,当我使用 Facebook 登录 --> 设置中可用的字段检查此 URL 的有效性时,它是可以的。
这是我的 Django 文件:
urls.py:
from django.conf.urls import url, include
from django.contrib import admin
from rest_framework import routers
from backend import views
from webapp import views as webapp_views
from django.contrib.auth import views as auth_views
router = routers.SimpleRouter()
router.register(r'users', views.UserViewSet, 'User')
router.register(r'games', views.GameViewSet, 'Game')
urlpatterns = [
url(r'^$', webapp_views.home, name='home'),
url('', include('social_django.urls', namespace='social')),
# FACEBOOK login/registration from Web
url(r'^login/$', auth_views.login, name='login'),
url(r'^logout/$', auth_views.logout, name='logout'),
url('', include('social_django.urls', namespace='social')),
url(r'^test/', webapp_views.test),
url(r'^admin/', admin.site.urls),
url(r'^connect/', views.CustomObtainAuthToken.as_view()),
url(r'^membership_create/', views.MembershipCreate.as_view()),
# Facebook login/registration from REST API
url(r'^auth/connect_with_fb/', views.ConvertTokenViewWithData.as_view()),
# standard Django login/registration from REST API
url(r'^auth/connect_with_credentials/', views.TokenViewWithData.as_view()),
url(r'^debug/', views.UserLoginAndIdView.as_view()),
url(r'^auth/', include('rest_framework_social_oauth2.urls'),
)
]
urlpatterns += router.urls
login.html
{% block content %}
<h2>Login</h2>
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Login</button>
</form>
<br>
<p><strong>-- OR --</strong></p>
<a href="{% url 'social:begin' 'facebook' %}">Login with Facebook</a>
{% endblock %}
settings.py
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'rest_framework.authtoken',
'rest_framework',
'oauth2_provider',
'social_django',
'rest_framework_social_oauth2',
'backend',
'webapp',
]
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'social_django.middleware.SocialAuthExceptionMiddleware', # <--
]
ROOT_URLCONF = 'WMC.urls'
SOCIAL_AUTH_URL_NAMESPACE = 'social'
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [ os.path.join(BASE_DIR, 'templates'),
os.path.join(BASE_DIR, 'webapp/templates')],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
'social_django.context_processors.backends',
'social_django.context_processors.login_redirect',
],
},
},
]
WSGI_APPLICATION = 'WMC.wsgi.application'
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'oauth2_provider.contrib.rest_framework.OAuth2Authentication',
'rest_framework_social_oauth2.authentication.SocialAuthentication',
),
}
AUTHENTICATION_BACKENDS = (
# Facebook OAuth2
'social_core.backends.facebook.FacebookAppOAuth2',
'social_core.backends.facebook.FacebookOAuth2',
# django-rest-framework-social-oauth2
'rest_framework_social_oauth2.backends.DjangoOAuth2',
# Django
'django.contrib.auth.backends.ModelBackend',
)
# Django client_secret for OAuth Toolkit for django-rest-social-auth
CLIENT_SECRET = '***********************************************************************************'
# Facebook configuration
SOCIAL_AUTH_FACEBOOK_KEY = '***********'
SOCIAL_AUTH_FACEBOOK_SECRET = '*****************************'
# Database
# https://docs.djangoproject.com/en/1.10/ref/settings/#databases
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
}
}
# Password validation
# https://docs.djangoproject.com/en/1.10/ref/settings/#auth-password-validators
AUTH_PASSWORD_VALIDATORS = [
{
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
},
]
# Define SOCIAL_AUTH_FACEBOOK_SCOPE to get extra permissions from facebook. Email is not sent by default, to get it, you must request the email permission:
SOCIAL_AUTH_FACEBOOK_SCOPE = ['email']
SOCIAL_AUTH_FACEBOOK_PROFILE_EXTRA_PARAMS = {
'fields': 'id, name, email'
}
# Internationalization
# https://docs.djangoproject.com/en/1.10/topics/i18n/
LANGUAGE_CODE = 'en-us'
TIME_ZONE = 'UTC'
USE_I18N = True
USE_L10N = True
USE_TZ = True
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/1.10/howto/static-files/
STATIC_URL = '/static/'
尝试添加
ALLOWED_HOSTS = [`.florian.com`]
到settings.py
假设您正在使用安装了 Nginx 的 Linux 开发环境。
我不建议您使用 'real' url 在本地进行测试。你应该试试 florian.local
.
在你的 /etc/hosts
中添加这样一行:
127.0.0.1 florian.local
将 florian.local
添加到 settings.py
文件中的 ALLOWED_HOSTS
。
在您的 /etc/nginx/sites-available
中创建一个文件 florian
(touch florian),其中包含如下内容:</p>
<pre><code>upstream florian {
server 127.0.0.1:8000;
}
server {
listen 80;
server_name florian.local;
keepalive_timeout 360;
client_max_body_size 100M;
location / {
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Protocol $scheme;
proxy_pass http://florian;
proxy_connect_timeout 600;
proxy_send_timeout 600;
proxy_read_timeout 600;
send_timeout 600;
}
}
CD 到 sites-enabled
并为之前创建的文件创建软 link:
ln -s ../sites-available/florian .
最后别忘了重启nginx,如:
sudo service nginx restart
运行 您的本地开发服务器:
./manage.py runserver 8000
,
然后您可以通过 http://127.0.0.1:8000
或 http://florian.local
.
我已使用此方法成功通过 Facebook、Twitter 和 Google 帐户向我的本地应用程序进行身份验证。
自 social_core
库的 1.6.0
版本(python-social-auth
的一部分)起,FacebookOAuth2
后端的字段 REDIRECT_STATE
已设置为 False
.
由于我使用的是 1.5.0
版本(其中 REDIRECT_STATE=True
),并且每次调用 Facebook 登录时 redirect_state
都会发生变化,因此我的应用无法处理这样的动态行为。
因此,将 social_core
升级到版本 1.7.0
即可解决问题。
我不确定是否已经回答了这个问题,但您的网站应该使用 https 而不是 http。
示例:
而不是http://www.florian.com:8000/complete/facebook 使用了这个:https://www.florian.com:8000/complete/facebook
Facebook 不接受 http 站点。
希望对您有所帮助。
对于儿童:
在 Facebook 开发者网站的 "Client OAuth Settings" 选项卡中将 https://yourdomain.example/oauth/complete/facebook/ 添加到 "Valid OAuth Redirect URIs"。
/oauth/ - 它是你的 django 社交的名称 url。