使用 Django 和 python-social-auth 进行 Facebook 重定向

Facebook redirection with Django and python-social-auth

要通过 python-social-auth 在本地测试使用 Facebook 登录我的 django 应用程序的能力,我遵循了以下步骤:

但是,当访问 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:8000http://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。