摘要:在授權頁面里面,登錄并確認授權。從騰訊提供的按鈕下載放到你的登錄頁面即可。騰訊不給得到真實號可能是出于保護隱私的考慮。再回頭編輯,添加回調地址的處理方法逆向解析第三方登錄,回調函數登錄之后,會跳轉到這里。
準備工作_OAuth2.0
接入QQ登錄前,網站需首先進行申請,獲得對應的appid與appkey,以保證后續流程中可正確對網站與用戶進行驗證與授權。
在開發的過程中,發現獲取不到QQ號,只能獲取一個OpenID的東西。最后采取存儲這個OpenID并綁定對應賬號的方式。
所以需要創建對應的模型,即創建一個應用管理第三方登錄。
QQ登錄功能開發流程如下圖:
打開QQ互聯,進入管理中心。注冊一下應用開發者,并添加網站應用,獲得對應的appid與appkey。
申請appid和appkey的用途
appid:應用的唯一標識。在OAuth2.0認證過程中,appid的值即為oauth_consumer_key的值。
appkey:appid對應的密鑰,訪問用戶資源時用來驗證應用的合法性。在OAuth2.0認證過程中,appkey的值即為oauth_consumer_secret的值。
理解回調地址需要了解一下OAuth協議。
在你的網站頁面里面,打開授權頁面(這個授權頁面不是回調地址)。在授權頁面里面,登錄QQ并確認授權。
授權之后,會得到一個授權碼。回調地址就是用于接收這個授權碼。
授權碼以GET的方式返回,例如?http://www.junxi.site/web/oau...
通過這種方式,可以獲取授權碼,所以需要提供一個地址。這個地址先寫一個暫時沒有的地址,后面開發的時候,再給這個地址寫對應的響應方法。
這個QQ按鈕是提供QQ登錄的入口。從騰訊提供的QQ按鈕下載放到你的登錄頁面即可。
不用看幫助文檔里面的什么前端代碼。這些用不上,只需要加一個固定的訪問鏈接,再重定向即可。
前端頁面此處的代碼如下:
qq_login鏈接在下面第3步創建web應用里面設置。
第3步、創建web應用怎么創建應用就不細說了,這是基本功。這里我已經創建了一個名稱為web的django app應用。
創建完成之后,打開models.py文件,編寫模型:
#!/usr/bin/env python # _*_ coding:utf-8 _*_ __author__ = "junxi" import sys reload(sys) sys.setdefaultencoding("utf8") class OAuthQQ(models.Model): """QQ and User Bind""" user = models.ForeignKey(UserProfile) # 關聯用戶信息表 qq_openid = models.CharField(max_length=64) # QQ的關聯OpenID # def __str__(self): # return self.user
該模型用于存儲QQ登錄返回的OpenID值。這個OpenID值是用QQ號一一對應。騰訊不給得到真實QQ號可能是出于保護隱私的考慮。
在總的urls路由中,加入這個應用路由。(總路由在和工程名一樣的文件夾中的urls.py文件。這種方式對urls管理比較清晰)
from django.conf.urls import url, include from django.contrib import admin import web.urls import web.views urlpatterns = [ url(r"^admin/", admin.site.urls), url(r"^web/", include(web.urls)), ]
路由控制根據自己的工程自己寫即可。
打開web應用目錄下urls.py文件,先寫一下需要哪些鏈接地址:
from django.conf.urls import url from .views import * urlpatterns = [ url(r"^oauth/qq/login/$", login, name="qq_login"), url(r"^oauth/qq/check/$", login, name="qq_check"), url(r"^oauth/bind/account/$", login, name="bind_account"), ]
qq_login和qq_check,分別是打開授權頁面和回調地址。
bind_account是綁定用戶的頁面。
大致思路是授權之后,得到OpenID。判斷這個OpenID是否存在數據庫中。若存在,則直接登錄對應的用戶即可;若不存在,則打開這個綁定郵箱頁面,綁定對應的用戶。
為了管理好OAuth,在web應用的文件夾下創建oauth_client.py文件。把相關的OAuth操作方法集成在一起。編輯oauth_client.py文件:
#!/usr/bin/env python # _*_ coding:utf-8 _*_ __author__ = "junxi" import json import urllib, urllib2, urlparse class OAuthQQ: def __init__(self, client_id, client_key, redirect_uri): self.client_id = client_id self.client_key = client_key self.redirect_uri = redirect_uri def get_auth_url(self): """獲取授權頁面的網址""" params = {"client_id": self.client_id, "response_type": "code", "redirect_uri": self.redirect_uri, "scope": "get_user_info", "state": 1} url = "https://graph.qq.com/oauth2.0/authorize?%s" % urllib.urlencode(params) return url
創建一個類,需要申請QQ登錄的APP_ID、APP_KEY和回調地址。這些都是固定的,我把這幾個常量放入到settings.py中。settings.py添加如下常量,具體的值請在你的申請頁面查找(這里還需要提一下,本地調試的方法。因為授權之后是調整到部署之后的網站上,而部署的網站還沒開發響應的代碼,無法響應對應的地址。這里我是本地測試環境,強制綁定Hosts域名文件解析):
# OAuth設置 QQ_APP_ID = "XXXXXX" QQ_KEY = "XXXXXX" QQ_RECALL_URL = "http://www.junxi.site/web/oauth/qq/check"
回到OAuthQQ類,現里面有個get_auth_url方法。該方法是獲取打開授權頁面的鏈接地址。(可參考官方幫助,寫得不夠清晰)
接著,在編輯web應用的views.py文件,加入qq_login對應的響應方法:
from django.shortcuts import HttpResponseRedirect from django.conf import settings from oauth_client import OAuthQQ def qq_login(request): oauth_qq = OAuthQQ(settings.QQ_APP_ID, settings.QQ_KEY, settings.QQ_RECALL_URL) #獲取 得到Authorization Code的地址 url = oauth_qq.get_auth_url() #重定向到授權頁面 return HttpResponseRedirect(url)
到這里為止,就完成了點擊QQ登錄按鈕,跳轉到授權頁面。
登錄授權之后,授權頁面會自動跳轉到我們設置的回調地址。例如 http://www.junxi.site/web/oau...
我們可以獲取這個地址上面的GET參數。先假設我們可以順利獲取到,繼續完善OAuthQQ類。拿到這個授權碼之后,需要用該碼獲取騰訊的access_token通行令牌。
打開oauth_client.py文件,在OAuthQQ類添加如下方法:
def get_access_token(self, code): """根據code獲取access_token""" params = {"grant_type": "authorization_code", "client_id": self.client_id, "client_secret": self.client_key, "code": code, "redirect_uri": self.redirect_uri} # 回調地址 url = "https://graph.qq.com/oauth2.0/token?%s" % urllib.urlencode(params) # 訪問該網址,獲取access_token response = urllib2.urlopen(url).read() result = urlparse.parse_qs(response, True) access_token = str(result["access_token"][0]) self.access_token = access_token return access_token
該方法使用了urllib2,在服務器后臺訪問對應的鏈接,獲取access_token,并返回該值。因為我后續不需要用access_token做其他動作,直接一次性獲取QQ昵稱和OpenID。所以不用記錄這個通行令牌的有效期。
得到這個access_token之后,就可以做其他事了。首先需要獲取授權用戶的OpenID,因為騰訊不允許獲取QQ號。只好退而求次,獲取并保存OpenID。可參考官方文檔。
繼續給這個OAuthQQ添加獲取OpenID的方法和使用OpenID獲取QQ基本信息的方法:
def get_open_id(self): """獲取QQ的OpenID""" params = {"access_token": self.access_token} url = "https://graph.qq.com/oauth2.0/me?%s" % urllib.urlencode(params) response = urllib2.urlopen(url).read() v_str = str(response)[9:-3] # 去掉callback的字符 v_json = json.loads(v_str) openid = v_json["openid"] self.openid = openid return openid def get_qq_info(self): """獲取QQ用戶的資料信息""" params = {"access_token": self.access_token, "oauth_consumer_key": self.client_id, "openid": self.openid} url = "https://graph.qq.com/user/get_user_info?%s" % urllib.urlencode(params) response = urllib2.urlopen(url).read() return json.loads(response)
騰訊返回OpenID和QQ基本信息的內容格式都不一樣。
再回頭編輯views.py,添加回調地址的處理方法:
from django.shortcuts import render, HttpResponseRedirect, HttpResponse, reverse # reverse url逆向解析 from django.http import JsonResponse from . import models from .form import * import json import time from django.conf import settings from oauth_client import OAuthQQ def qq_check(request): # 第三方QQ登錄,回調函數 """登錄之后,會跳轉到這里。需要判斷code和state""" request_code = request.GET.get("code") oauth_qq = OAuthQQ(settings.QQ_APP_ID, settings.QQ_KEY, settings.QQ_RECALL_URL) # 獲取access_token access_token = oauth_qq.get_access_token(request_code) time.sleep(0.05) # 稍微休息一下,避免發送urlopen的10060錯誤 open_id = oauth_qq.get_open_id() print open_id # 檢查open_id是否存在 qq_open_id = models.OAuthQQ.objects.filter(qq_openid=str(open_id)) print qq_open_id if qq_open_id: # 存在則獲取對應的用戶,并登錄 user = qq_open_id[0].user.username print user request.session["username"] = user return HttpResponseRedirect("/web/") else: # 不存在,則跳轉到綁定用戶頁面 infos = oauth_qq.get_qq_info() # 獲取用戶信息 url = "%s?open_id=%s&nickname=%s" % (reverse("bind_account"), open_id, infos["nickname"]) return HttpResponseRedirect(url)
按照思路,授權之后,調整到處理授權結果的頁面。獲取授權碼之后,用get_access_token方法得到access_token。
再用access_token獲取OpenID。坑出現了,若不加time.sleep(0.05)休息一下的話,會得到urlopen 10060錯誤。
獲取到open_id之后,再判斷一下數據庫中是否存在。若存在,則已經關聯對應的用戶了,直接登錄該用戶。
若open_id不存在,則跳轉到綁定用戶的頁面。該頁面需要知道open_id和QQ昵稱(為什么需要QQ昵稱,下一步會提到)。通過GET方式,把這兩個參數寫在鏈接上即可傳遞過去。
本地調試,先本地打開授權頁面授權,得到一個回調地址。回調地址上有授權碼,如下圖:
第5步、綁定用戶上面提到若open_id在數據庫中不存在,則打開綁定用戶頁面。該頁面我設計成html表單,在templates下新建qq-bind-account.html文件。如下代碼:
{% extends "base.html" %} {% block title %}QQ和賬戶綁定 {% endblock %} {% block head-js %} {% endblock %} {% block nav %} {% endblock %} {% block content %}
? 2017 JunXi. All Rights Reserved
接著,在views.py繼續編輯,添加表單處理的對應方法:
def bind_account(request): # 綁定賬戶 open_id = request.GET.get("open_id") nickname = request.GET.get("nickname") if request.method == "POST" and request.POST: data = request.POST # 接收到前臺form表單傳過來的注冊賬戶信息 user = models.UserProfile() username = data["username"] password = data["password"].split(",")[0] user.username = username password = hash_sha256(password, username) user.password = password user.nickname = data["nickname"] user.departments_id = 1 user.save() oauthqq = models.OAuthQQ() oauthqq.qq_openid = open_id oauthqq.user_id = models.UserProfile.objects.get(username=username).id oauthqq.save() response = HttpResponseRedirect("/web/") request.session["username"] = username # 設置session return response # 返回首頁 return render(request, "qq-bind-account.html", locals())
訪問測試:
打開首頁
點擊QQ登錄
獲取授權并登錄
寫完代碼之后,本地測試可以通過。最后再部署到服務器并在QQ互聯提交審核。一般審核要1~2天左右。若審核不通過,又不明白審核說明,就直接找客服問問。
-----<我是分割線,下面是項目在pycharm中的展示>-----
-----<我是分割線,下面是urls.py、view.py、oauth_client.py完整的代碼>-----
urls.py
urlpatterns = [ url(r"^oauth/qq/login", qq_login, name="qq_login"), url(r"^oauth/qq/check", qq_check, name="qq_check"), url(r"^oauth/bind/account", bind_account, name="bind_account"), ]
views.py
#!/usr/bin/env python # _*_ coding:utf-8 _*_ __author__ = "junxi" from django.shortcuts import render, HttpResponseRedirect, HttpResponse, reverse # reverse url逆向解析 from django.http import JsonResponse from . import models from .form import * from script.salt_api import salt from script.web_ssh import webssh from django.contrib.auth.hashers import make_password, check_password # from django.forms.models import model_to_dict from django.core import serializers import datetime import json import hashlib import re import time import os from django.conf import settings from oauth_client import OAuthQQ def hash_sha256(password, username): # sha256加密 sha256 = hashlib.sha256() sha256.update((password + username).encode("utf-8")) sha256_password = sha256.hexdigest() return sha256_password def qq_login(request): # 第三方QQ登錄 oauth_qq = OAuthQQ(settings.QQ_APP_ID, settings.QQ_KEY, settings.QQ_RECALL_URL) # 獲取 得到Authorization Code的地址 url = oauth_qq.get_auth_url() # 重定向到授權頁面 return HttpResponseRedirect(url) def qq_check(request): # 第三方QQ登錄,回調函數 """登錄之后,會跳轉到這里。需要判斷code和state""" request_code = request.GET.get("code") oauth_qq = OAuthQQ(settings.QQ_APP_ID, settings.QQ_KEY, settings.QQ_RECALL_URL) # 獲取access_token access_token = oauth_qq.get_access_token(request_code) time.sleep(0.05) # 稍微休息一下,避免發送urlopen的10060錯誤 open_id = oauth_qq.get_open_id() print open_id # 檢查open_id是否存在 qq_open_id = models.OAuthQQ.objects.filter(qq_openid=str(open_id)) print qq_open_id if qq_open_id: # 存在則獲取對應的用戶,并登錄 user = qq_open_id[0].user.username print user request.session["username"] = user return HttpResponseRedirect("/web/") else: # 不存在,則跳轉到綁定用戶頁面 infos = oauth_qq.get_qq_info() # 獲取用戶信息 url = "%s?open_id=%s&nickname=%s" % (reverse("bind_account"), open_id, infos["nickname"]) return HttpResponseRedirect(url) def bind_account(request): # 綁定賬戶 open_id = request.GET.get("open_id") nickname = request.GET.get("nickname") if request.method == "POST" and request.POST: data = request.POST # 接收到前臺form表單傳過來的注冊賬戶信息 user = models.UserProfile() username = data["username"] password = data["password"].split(",")[0] user.username = username password = hash_sha256(password, username) user.password = password user.nickname = data["nickname"] user.departments_id = 1 user.save() oauthqq = models.OAuthQQ() oauthqq.qq_openid = open_id oauthqq.user_id = models.UserProfile.objects.get(username=username).id oauthqq.save() response = HttpResponseRedirect("/web/") request.session["username"] = username # 設置session return response # 返回首頁 return render(request, "qq-bind-account.html", locals())
oauth_client.py
#!/usr/bin/env python # _*_ coding:utf-8 _*_ __author__ = "junxi" import json import urllib, urllib2, urlparse class OAuthQQ: def __init__(self, client_id, client_key, redirect_uri): self.client_id = client_id self.client_key = client_key self.redirect_uri = redirect_uri def get_auth_url(self): """獲取授權頁面的網址""" params = {"client_id": self.client_id, "response_type": "code", "redirect_uri": self.redirect_uri, "scope": "get_user_info", "state": 1} url = "https://graph.qq.com/oauth2.0/authorize?%s" % urllib.urlencode(params) return url def get_access_token(self, code): """根據code獲取access_token""" params = {"grant_type": "authorization_code", "client_id": self.client_id, "client_secret": self.client_key, "code": code, "redirect_uri": self.redirect_uri} # 回調地址 url = "https://graph.qq.com/oauth2.0/token?%s" % urllib.urlencode(params) # 訪問該網址,獲取access_token response = urllib2.urlopen(url).read() result = urlparse.parse_qs(response, True) access_token = str(result["access_token"][0]) self.access_token = access_token return access_token def get_open_id(self): """獲取QQ的OpenID""" params = {"access_token": self.access_token} url = "https://graph.qq.com/oauth2.0/me?%s" % urllib.urlencode(params) response = urllib2.urlopen(url).read() v_str = str(response)[9:-3] # 去掉callback的字符 v_json = json.loads(v_str) openid = v_json["openid"] self.openid = openid return openid def get_qq_info(self): """獲取QQ用戶的資料信息""" params = {"access_token": self.access_token, "oauth_consumer_key": self.client_id, "openid": self.openid} url = "https://graph.qq.com/user/get_user_info?%s" % urllib.urlencode(params) response = urllib2.urlopen(url).read() return json.loads(response)
參考文章
。。。。。。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/41595.html
摘要:寫在前面本周剛在項目中實現了微信第三方網站掃碼登錄。準備與注意事項微信公眾平臺跟微信開放平臺是兩個不同的平臺,別搞混了。參數在微信開放平臺中查看。 寫在前面 本周剛在項目中實現了微信第三方網站掃碼登錄。因為第一次寫相關項目,所以遇到了很多坑。所以寫這篇文章是希望像我之前那樣的小白也能從容的開發,不要浪費無謂的時間,這篇文章盡量寫的詳細簡單。準備與注意事項 微信公眾平臺跟微信開放平臺是...
摘要:使用微博進行第三方登錄進入微博開放平臺申請應用。根據微博的接口寫的微博登錄的一個第一步生成一個網頁地址,訪問后是微博第三方登錄的頁面,登錄會返回一個授權碼必填申請應用時分配的。 OAuth2.0是什么 ?OAuth的英文全稱是Open Authorization,它是一種開放授權協議。OAuth目前共有2個版本,2007年12月的1.0版(之后有一個修正版1.0a)和2010年4月的2...
摘要:前言之前讓網頁公司制作新官網的時候規劃有第三方賬號的登錄功能,但由于當時的一些開放平臺申請步驟比較繁瑣尤其是微信開放平臺,所以一直拖延著,到了最近只能自己添加相關的功能。 前言 之前讓網頁公司制作新官網的時候規劃有第三方賬號的登錄功能,但由于當時的一些開放平臺申請步驟比較繁瑣(尤其是微信開放平臺),所以一直拖延著,到了最近只能自己添加相關的功能。 由于是剛接觸Python和Django...
摘要:本章講如何幫助健忘癥患者,重置用戶密碼。實際上不僅內置了密碼重置,還包括登錄登出密碼修改等功能。總結本章學習了使用第三方庫,高效完成了重置密碼的功能。有疑問請在杜賽的個人網站留言,我會盡快回復。 隨著技術的發展,驗證用戶身份的手段越來越多,指紋、面容、聲紋應有盡有,但密碼依然是最重要的手段。 互聯網處處都有密碼的身影,甚至變成了現代人的一種負擔。像筆者這樣的,動輒幾十個賬號密碼,忘記其...
摘要:我接觸已經很久了,其中微信的就是我貢獻的代碼,然而當時做的時候比較年輕,而且這個項目處于一個很大的代碼重構中,借這次機會重新用正確的姿勢接入了一下三方登錄,可以當做一個學習接入三方的。 為什么要接入三方登錄 如果你的微信服務器要做復雜的邏輯,比如html5、給用戶提供高級的服務,并且有很好看的頁面等等,這種時候你就需要一個正常的web服務器,用戶打通就需要做三方登錄了。 而如果你決定直...
閱讀 1090·2021-11-15 18:00
閱讀 2802·2021-09-22 15:18
閱讀 1964·2021-09-04 16:45
閱讀 750·2019-08-30 15:55
閱讀 3853·2019-08-30 13:10
閱讀 1331·2019-08-30 11:06
閱讀 1983·2019-08-29 12:51
閱讀 2294·2019-08-26 13:55