一、开发环境

django 1.10.2

python3.5.2

django-social-auth 0.3.6

二、申请QQ互联 APPID及SECRECT_KEY

大致步骤:

1.成为QQ互联开发者

2.创建应用

3.获取应用app_id 及secret_key

三、代码

1.安装认证框架

$ pip3 install social-auth-app-django

2.在INSTALLED_APPS中添加应用(settings.py)

INSTALLED_APPS = (
...
'social_django',
...
)

3.更新数据库

python3 managy.py migrate

4.在认证后端添加QQ认证以及QQ互联的key和id(settings.py)

AUTHENTICATION_BACKENDS = (
...
'social_core.backends.qq.QQOAuth2',
)
SOCIAL_AUTH_QQ_KEY = 'your qq app id,like some number,for examle 230402020' # QQ APP_ID
SOCIAL_AUTH_QQ_SECRET = 'you qq seckey ,combined by letter with number,for examle: f123bas324' # QQ SECRECT_KEY
SOCIAL_AUTH_QQ_USE_OPENID_AS_USERNAME = True

5.添加根urls.py的URL路由

urlpatterns = [
......
url('', include('social_django.urls', namespace='social'))
]

6.在需要登录的地方加上如下代码:

<a href="{% url "social:begin" "qq" %}">QQ登录 <!-- 这个登录标识注意要满足QQ互联的要求 --></a>

7.settings.py中的TEMPALTES如下:

TEMPLATES = [
{
...
'OPTIONS': {
...
'context_processors': [
...
'social_django.context_processors.backends',
'social_django.context_processors.login_redirect',
...
]
}
}
]

四、可能出现的问题

1.认证页面是空白页面

解决方案,检查APPID和SECRET_KEY是否填写正确

2.redirect_url不合法 10010

解决方案,注意域名的一致性,此问题是由于http请求中url和QQ互联中的 回调地址不同引起的,

https://graph.qq.com/oauth/show?which=Login&display=pc&redirect_uri=http://localhost.com:8080/complete/qq/&client_id=xxxx&response_type=code&state=xxxx

在实际使用过程中出现同样问题,主要是因为网站使用了多个域名,使用www.czxxs.cn和czxxs.cn都能访问网站,此时可以把回调地址设置为两个地址,如下:

再次尝试,错误消失

3.用openid代替昵称存储在数据库,在settings.py中加上以下语句(避免QQ昵称相同引起用户存储错误)

SOCIAL_AUTH_QQ_USE_OPENID_AS_USERNAME = True

参考连接:http://python-social-auth.readthedocs.io/en/latest/configuration/django.html

http://python-social-auth.readthedocs.io/en/latest/backends/qq.html

备注:

功能可以根据上面两个连接进行完善,有问题欢迎留言

五、扩展(Pipeline管道),实现认证流程的自定义

用途:在认证过程中,可以加入自己的函数,实现认证过程的定制化。

原理:自定义的函数会收到当前进程传递的参数,包括strategy,user,和request,建议在定义函数的时候额外添加**kwargs参数来避免 未知参数错误。

返回:管道(自定义的函数)可以返回dict或者None,如果返回其他内容,这些内容则会被看做 一个  response,然后会直接返回给客户端,Partial Pipeline会介绍原理)

如果返回的dict,那么dict的值会合并到 kwargs参数中,然后传递给下一个pipeline,如果返回None将被看做返回了'{}'空的字典

(认证管道)Authentication Pipeline

认证流程的最后一步,是处理一系列可操作的管道,可以在管道中添加自定义的功能,也可以删除默认的管道。认证系统默认的管道是创建用户实例,然后从认证服务商处获取一些基本的信息。默认的管道如下:

(
# 从服务商获取用户信息,然后以一种简单的格式返回,用来将来创建用户使用
# 有时候用户的信息已经在认证消息的 Response 响应中了,但是有时需要使用服务商提供的api
'social_core.pipeline.social_auth.social_details', # 从服务商处获取 social uid,这个uid是服务商给用户的唯一标识
'social_core.pipeline.social_auth.social_uid', # 验证当前认证流程是否合法,需要提供邮箱和域名白名单(好像没用到过,可以自己深入研究)
'social_core.pipeline.social_auth.auth_allowed', # 判断当前认证账户是否已经关联到了网站用户、
'social_core.pipeline.social_auth.social_user', # 为认证用户创建一个用户名,如果用户名冲突则在用户名后添加随机字符串
'social_core.pipeline.user.get_username', # 给用户发送验证邮件,验证其邮箱的真实性,默认禁用
# 'social_core.pipeline.mail.mail_validation', # 把 当前社交认证信息和其他 邮箱相似的用户关联起来,默认禁用
# 'social_core.pipeline.social_auth.associate_by_email', #如果没有发现用户账户则创建用户(以social user的信息创建)
'social_core.pipeline.user.create_user', #创建将社交帐户与用户关联的记录。
'social_core.pipeline.social_auth.associate_user', #使用settings.py指定的值(和access_token等默认值)填充社交记录中的extra_data字段。
'social_core.pipeline.social_auth.load_extra_data', #使用来自auth服务的任何更改的信息更新用户记录。
'social_core.pipeline.user.user_details',
)

可以在setting中通过设置SOCIAL_AUTH_PIPELINE来覆盖默认的管道。例如可以通过设置如下变量来达到,

不创建用户,只与已经存在的用户关联的目的。

SOCIAL_AUTH_PIPELINE = (
'social_core.pipeline.social_auth.social_details',
'social_core.pipeline.social_auth.social_uid',
'social_core.pipeline.social_auth.auth_allowed',
'social_core.pipeline.social_auth.social_user',
'social_core.pipeline.social_auth.associate_user',
'social_core.pipeline.social_auth.load_extra_data',
'social_core.pipeline.user.user_details',
)

这是在用户已经授权的情况下可以通过这种方式来关联用户,因此在dict中会有 user这一键值。如果认证完全来自外部,必须提供一个用来产生 user键值的管道,比如:

SOCIAL_AUTH_PIPELINE = (
'social_core.pipeline.social_auth.social_details',
'social_core.pipeline.social_auth.social_uid',
'social_core.pipeline.social_auth.auth_allowed',
'myapp.pipeline.load_user',
'social_core.pipeline.social_auth.social_user',
'social_core.pipeline.social_auth.associate_user',
'social_core.pipeline.social_auth.load_extra_data',
'social_core.pipeline.user.user_details',
)

也可以在setting中为每一个后端定制管道,例如 SOCIAL_AUTH_TWITTER_PIPELINE,指定的pipeline会覆盖默认的pipeline。

每个pipeline函数会收到以下参数:

1.strategy(包含访问当前存储,后端和请求的参数)

2.社交认证端给出的userid

3.社交认证端给出的用户信息

4.is_new标志,默认值为False

5.传递给 auth_complete方法的参数,默认的视图传递以下参数:

①当前登录的用户,如果未登录,是None

②当前的request

Disconnection Pipeline(断开管道)

和认证管道想反,当用户断开社交账户关联时的功能。

比如,当用户断开所有社交账户关联时,需要用户填写登录密码(这种情况是针对,在认证管道中直接创建用户的情况,认证管道中存在'social_core.pipeline.user.create_user' 这条语句时才需要考虑断开管道,因为这个管道会直接用用户的社交 user_id创建用户名,但是却可以不存在密码如下图)。

可以通过覆盖默认的断开管道,然后添加一个可以检查用户是否有密码的函数,如果不存在的话重定向到填写密码表单,然后继续执行断开流程。注意断开连接需要确保在POST方法下进行,一个简单的方法来确保这一点,是使您的表单POST到/
disconnect /并在管道功能中设置需要密码。

覆盖断开管道的设置如下:

SOCIAL_AUTH_DISCONNECT_PIPELINE = (
# 验证社交关联是否可以断开(确保用户登录不会被断开 破坏?(compromised))
'social_core.pipeline.disconnect.allowed_to_disconnect', # 收集需要断开的关联
'social_core.pipeline.disconnect.get_entries', # 抽取acces_token
'social_core.pipeline.disconnect.revoke_tokens', # 移除关联
'social_core.pipeline.disconnect.disconnect',
)

同样也可以设置针对性管道如:SOCIAL_AUTH_TIWTTER_DISCONNECT_PIPELINE.

Partial Pipeline(部分?管道)

可以暂停管道返回到用户需要执行的动作,然后再继续执行。

为了实现这一装饰器功能,需要用 @partial装饰器断开处理流程,partial装饰器文件位置位于social/pipeline/partial.py

当需要返回到处理流程时,只需要把用户重定向到/complete/<backend>/或者/diconnect/<backend>/视图中,这样管道就会继续执行同样的功能,但是也可以中断处理流程。

@partial把需要的数据存储到数据库中名为social_auth_partial的表中。此表包含着可以在将来从任何浏览器恢复的信息,同时会删除浏览器会话的旧依赖关系,从而防止浏览器之间的复制行为。

partial数据根据UUID token来区分,token可以存储在session或者追加在url中以partial_token参数命名(默认值),库会从request中获取这些值,然后加载需要的值来让用户继续执行流程。

pipeline功能函数会得到一个current_partial的实例,包含partial token和数据库中需要的数据

为了使后端可以重定向到任何社交视图,只需要:

backend = current_partial.backend

通过下列语句可以覆盖默认的参数名称:

SOCIAL_AUTH_PARTIAL_PIPELINE_TOKEN_NAME = '...

示例:

https://github.com/python-social-auth/social-examples

Extending the Pipeline(扩展管道)

扩展一个管道需要:

1.编写功能函数

2.把功能函数放到可引用的地方

3.用新管道覆盖默认的管道

写功能时比较简单,但是需要注意的是,管道功能的排列顺序会影响到认证流程,因此需要谨慎安排。pipeline的位置会决定每个管道会收到什么参数,比如,把你自定义的功能管道放到social_core.pipeline.user.create_user可以确保你的功能得到一个用户实例(创建的或者是已经存在的)而不是None。pipeline管道功能函数会收到需要参数,包含使用的后端,不同的模型实例,服务器request和社交提供商的response,简单介绍如下:

strategy:当前strategy实例

backend:当前backend实例

uid:社交服务商提供的uid,这个uid是当前用户在社交服务商处的唯一标识。

response:{}或者object()

服务器user-details response,取决于使用的协议(),通常是一个包含用户个人信息详情的dict,这已经包含了许多的用户详情,有时scope会增加信息的总量


details
= {}
后端产生的用户的基本信息,用来去创建或者更新user model(字典中包含username,email.first_name,last_name 和fullname等值)

user
= None
user实例,如果没有创建用户或者在数据库中没有找到则是None
social
= None
给出用户已关联的社交认证,如果用户没有创建或者数据库中不存在则返回None

通常自定义管道功能函数时,只需要从response中获得一些参数,但是你可以通过调用其他api去获取更多用户信息,然后存储到其他地方。

下面是一个创建用户Profile实例的一个例子,profile实例存储的是一些社交服务商返回的信息,(如Facebook,Facebook的response通常如下)

{
'username': 'foobar',
'access_token': 'CAAD...',
'first_name': 'Foo',
'last_name': 'Bar',
'verified': True,
'name': 'Foo Bar',
'locale': 'en_US',
'gender': 'male',
'expires': '5183999',
'email': 'foo@bar.com',
'updated_time': '2014-01-14T15:58:35+0000',
'link': 'https://www.facebook.com/foobar',
'timezone': -3,
'id': '100000126636010',
}

假如我们想存储用户的个人简介链接,性别和时区到数据库,则功能管道可以如下:

def save_profile(backend, user, response, *args, **kwargs):
if backend.name == 'facebook':
profile = user.get_profile()
if profile is None:
profile = Profile(user_id=user.id)
profile.gender = response.get('gender')
profile.link = response.get('link')
profile.timezone = response.get('timezone')
profile.save()

现在我们只需要让soical-auth使用我们的管道即可,因为这个管道需要user实例,我们需要把他放到social_core.pipeline.user.create_user之后,可以确保有一个用户。

SOCIAL_AUTH_PIPELINE = (
'social_core.pipeline.social_auth.social_details',
'social_core.pipeline.social_auth.social_uid',
'social_core.pipeline.social_auth.auth_allowed',
'social_core.pipeline.social_auth.social_user',
'social_core.pipeline.user.get_username',
'social_core.pipeline.user.create_user',
'path.to.save_profile', # <--- set the path to the function
'social_core.pipeline.social_auth.associate_user',
'social_core.pipeline.social_auth.load_extra_data',
'social_core.pipeline.user.user_details',
)

目前我们创建的管道功能函数返回时None,即被看做返回的是{},如果你想要profile能在下个管道中使用,那你只需要返回{'profile':profile}.

六、异常处理

在认证过程中会产生许多异常,需要处理,此时可以利用django Middleware来解决。

django social auth提供了一个基础中间件,通过Django消息框架向用户提供消息,然后通过重定向到一个中间件方法中定义的URL来处理SocialAuthBaseException。

中间件在social_django.middleware.SocialAuthExceptionMiddleware。
其中的任何方法都可以被覆盖,但为了简单起见,建议使用这两种方法:

get_message(request, exception)
get_redirect_uri(request, exception)

默认情况下,消息是异常消息,重定向的URL是由LOGIN_ERROR_URL设置指定的位置。

如果'strategy()'装饰器检测到有效的后端,则它将在request.strategy.backend中可用,并且process_exception()将使用它来构建后端相关的重定向URL,但如果未定义,则将其回退到默认值。

如果下列设置中,任意一项被定义为True,那么异常处理都是不能够使用:

<backend name>_SOCIAL_AUTH_RAISE_EXCEPTIONS = True
SOCIAL_AUTH_RAISE_EXCEPTIONS = True
RAISE_EXCEPTIONS = True
DEBUG = True

重定向的目的会得到两个参数:

message
= ''
来自触发异常处的消息,在某些情况下,它是在验证过程中由社交运营商返回的消息
Message from the exception raised, in some cases it’s the message returnedby the provider during the auth process.
backend
= ''
正在使用的后端(backend),前提是合法的后端

中间件将尝试使用Django内置消息应用程序来存储异常消息,并使用社会认证和后端名称进行标记。
如果应用程序未启用或发生MessageFailure错误,则应用程序将默认为上述URLformat。

django QQ认证登录的更多相关文章

  1. Django——用户认证和判断用户是否登录

    用户认证 必须通过认证之后才能login(request,user)这样才能保存会话到request中,注销后会话结束 注意 自定义的用户登陆时只不止需要验证用户名和密码的需要写认证,就例如在线教育平 ...

  2. [py][mx]django自定义认证类-实现邮箱作为用户名登录

    创建自定义验证用户名密码类CustomBackend users/views.py from django.contrib.auth import authenticate, login from d ...

  3. 基于Thinkphp3.2的qq第三方oauth认证登录扩展类

    基于Thinkphp3.2的qq第三方oauth认证登录扩展类,由于腾讯oauth sdk写的太多,不能与thinkphp和好的结合,最终想法讲腾讯oauth sdk写成tp的扩展类先看代码,将代码保 ...

  4. Django之auth登录认证

    前言:我们在开发一个网站的时候,无可避免的需要设计实现网站的用户系统.此时我们需要实现包括用户注册.用户登录.用户认证.注销.修改密码等功能,这还真是个麻烦的事情呢. Django作为一个完美主义者的 ...

  5. Django项目中使用qq第三方登录。

    使用qq登录的前提是已经在qq互联官网创建网站应用并获取到QQ互联中网站应用的APP ID和APP KEY 1,建路由 # qq登录 path('loginQq/',qq.loginQq,name=' ...

  6. 利用JS_SDK实现QQ第三方登录

    前言 现如今,第三方登录已成为大部分网站必备的一项基础技能,引入时髦的第三方登录不仅能帮你吸引更多的用户,也让你的网站可以充分利用其他大型网站的用户资源.本次教程将让你的网站最快捷便利地引入QQ登录. ...

  7. Django 用户认证及OneToOneField

    Django 用户认证如果自己不想写 就可以用django自带的认证 首选导入模块 models.py #!/usr/bin/env python #_*_ coding:utf8 _*_ from ...

  8. Django auth认证

    Django自带的用户认证 我们在开发一个网站的时候,无可避免的需要设计实现网站的用户系统.此时我们需要实现包括用户注册.用户登录.用户认证.注销.修改密码等功能,这还真是个麻烦的事情呢. Djang ...

  9. Django的认证系统

    Django自带的用户认证 我们在开发一个网站的时候,无可避免的需要设计实现网站的用户系统.此时我们需要实现包括用户注册.用户登录.用户认证.注销.修改密码等功能,这还真是个麻烦的事情呢. Djang ...

随机推荐

  1. BUPT复试专题—哈夫曼树(2010)

    https://www.nowcoder.com/practice/162753046d5f47c7aac01a5b2fcda155?tpId=67&tqId=29635&tPage= ...

  2. [Unit Testing] Fundamentals of Testing in Javascript

    In this lesson, we’ll get the most fundamental understanding of what an automated test is in JavaScr ...

  3. hdu 1679 The Unique MST (克鲁斯卡尔)

    The Unique MST Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 24152   Accepted: 8587 D ...

  4. 远程唤醒UP Board

    前言 原创文章,转载引用务必注明链接.水平有限,如有疏漏,欢迎指正. 本文使用Markdown写成,为获得更好的阅读体验和正常的图片.链接,请访问我的博客: http://www.cnblogs.co ...

  5. win10 UWP 申请微软开发人员

    申请微软开发人员能够到https://dev.windows.com/zh-cn/programs/join 假设是学生,先去http://www.dreamspark.com/ 假设是英文,点stu ...

  6. Vue 建立工程

    npm install -g vue npm install -g vue-cli vue init webpack my-project cd my-project npm isntall npm ...

  7. 关于CAShapeLayer

    关于CAShapeLayer 内容大纲: CAShapeLayer简介 贝塞尔曲线与CAShapeLayer的关系 strokeStart和strokeEnd 动画 用CAShapeLayer实现进度 ...

  8. 编译 Deedle

    编译 Deedle Deedle 中含有 RProvider. 要编译 Deedle.须要先下载 R.地址: http://cran.cnr.berkeley.edu/bin/windows/base ...

  9. BZOJ 1042: [HAOI2008]硬币购物 容斥+背包

    1042: [HAOI2008]硬币购物 Description 硬币购物一共有4种硬币.面值分别为c1,c2,c3,c4.某人去商店买东西,去了tot次.每次带di枚ci硬币,买si的价值的东西.请 ...

  10. kaminari分页插件样式

    修改国际化文件,zh-cn views: pagination: first: "首页" last: "尾页" previous: "上一页" ...