网站首页Python相关

Django增加QQ第三方登录

发布时间:2016-08-19编辑:阿超阅读(1576

    要使用QQ或者weibo的三方登录功能,必须先到相应网站的申请开发者权限。

    QQ在这里申请:http://connect.qq.com/

    选择网站接入-创建应用-网站-然后填写网站的信息

    注意回调地址(登录成功后的返回页)要写正确,不然无法进行正常登录。

    申请成功之后会得到APPID和APPKEY,后续需要用到。在网站未通过审核时只有开发者的QQ和协作组测试号可以登录。


    登录QQ可以使用openqqpy

    openqqpy.py下载之后放在django app的目录下供调用。

    配置

    因为QQ登录提供了一些额外的信息,django的user里面不包含这些信息。所以需要创建一个onetoone的model来存储QQ用户的信息。

    #demo/models.py
    from django.db import models
    from django.contrib.auth.models import User
    class QQ_user(models.Model):
        user = models.OneToOneField(User)
        profile_image_url = models.CharField(max_length=128, verbose_name=u"头像地址")
        screen_name = models.CharField(max_length=128, verbose_name=u'用户昵称')
        gender = models.CharField(max_length=20, verbose_name=u'性别')
        uid = models.CharField(max_length=50, verbose_name=u"用户id")
        access_token = models.CharField(max_length=50, verbose_name=u"token")
        expires_in = models.CharField(max_length=20, verbose_name=u'过期时间')
        def __unicode__(self):
            return self.uid

    由于使用的django的login来登录,所以需要提供一个帐号密码,帐号可以用QQ昵称,密码我这边实现是每次登陆的时候随机生成一个密码,然后save之后再将密码填入authenticate函数中.确保数据库中不保存明文密码。

    #demo/views.py
    from django.shortcuts import render, HttpResponseRedirect
    from django.contrib.auth import authenticate, login
    from uuid import uuid1
    from django.contrib.auth.models import User
    from demo.models import Weibo_user, QQ_user
    from demo.openqqpy import OpenQQClient
    import time
    QQ_APP_ID = ""
    QQ_APP_KEY = ""
    
    def add_email(request):
        if request.method == 'POST':
            user = request.user
            user.email = request.POST.get('email')
            user.save()
            back_to_url = request.session.get('login_from', '/')
            return HttpResponseRedirect(back_to_url)
        return render(request, 'weibo/add_email.html', {})
        
    def qq_create_user(username, openid):
        password = uuid1()
        user = User(username=username)
        user.set_password(password)
        user.save()
        return user, password
        
    def qq_login(request):
        """
        跳转QQ登录需要前往的地址
        :param request:
        :return:
        """
        login_backurl = request.build_absolute_uri('/server/qq/logincheck')
        auth_url = qq_oauth(login_backurl).get_auth_url()
        return HttpResponseRedirect(auth_url)
        
    def qq_oauth(call_back):
        """
        返回QQ登录连接
        :param call_back:
        :return:
        """
        client = OpenQQClient(client_id=QQ_APP_ID, client_secret=QQ_APP_KEY, redirect_uri=call_back)
        return client
        
    #上面2个函数一个用来获取QQclient类,另一个用来返回QQ登录的地址。
    #QQ成功登录之后会带着code返回到login_backurl页面
    #下面的函数就是该页面进行的工作:主要就是由code去获取用户的信息。
    
    
    def qq_login_check(request):
        login_backurl = request.build_absolute_uri('/server/qq/logincheck')
        client = qq_oauth(login_backurl)
        request_code = request.GET.get('code')
        r = client.request_access_token(request_code)
        access_token = r['access_token']
        #获取token
        expires_in = r['expires_in']
        openid = client.request_openid()
        #获取openid
        msg = client.request_api('user/get_user_info')
        username = msg["nickname"]
        user = User.objects.filter(username=username)
        #如果用户不存在,则创建一个新的user
        if not user:
            user, password = qq_create_user(username, openid)
            qq_user = QQ_user(user=user, profile_image_url=msg["figureurl_qq_1"], screen_name=username, gender=msg["gender"],
                              uid=openid, access_token=access_token, expires_in=expires_in)
            qq_user.save()
        else:
                #如果用户存在,更新密码,更新信息
          user = user[0]
          password = uuid.uuid1()
          user.set_password(password)
          user.save()
          qq_user = user.qq_user
          #检查expires_in是否过期,如果过期则更新
          if qq_user.expires_in < time.time():
              qq_user.profile_image_url = msg.figureurl_qq_1
            qq_user.expires_in = expires_in
            qq_user.access_token = access_token
            qq_user.save()
        request.session['oauth_access_token'] = access_token
        back_to_url = request.session.get('login_from', '/')
        login_user = authenticate(username=username, password=password)
        login(request, login_user)
        #登录
        #判断登录用户是否已经有email信息,如果没有跳转到添加email信息页
        if not user.email:
            return HttpResponseRedirect('/server/login/supply/')
        return HttpResponseRedirect(back_to_url)

    添加相关url路由

    from django.conf.urls import url
    from demo import views
    urlpatterns = [
        url(r'^login/supply/$', views.add_email, name='supply'),
        url(r'^qq/login/$', views.qq_login, name='qq_login'),
        url(r'^qq/logincheck/$', views.qq_login_check, name='qq_check'),
    ]
    现在QQ登录已经添加完毕,可以用测试帐号试一下.