auth2.0的功用:首先說一下為什么需要auth2.0,auth2.0是開放平台互聯協議,可以這樣理解,A是行業中的小生,兩手空空;B是行業大佬,財大氣粗,有一大批人(用戶群);這個時候A需要借用B的用戶群信息來構建自己的項目中的某項功能,但是出於資源的保護和各方面原因,B不相信A,不會讓A接入自己的信任體系里面,A是無法直接獲取B那邊用戶群的用戶名和密碼的,同時A又想借用B擁有的用戶群信息來完善自己項目中的某些功能,這個時候就需要auth2.0來做中介,通過一些業務流程來實現A在沒有B的用戶群的直接信息(賬戶和密碼),可以間接的獲取到B那邊的用戶群的其他信息(除了用戶名和密碼,如用戶昵稱等等),至於信息的開發程度,那得看B了。說白了就是如何使得A在沒有B的用戶群的密碼和賬號的情況下獲取B的用戶群的其他的信息,auth2.0就是解決這樣的問題
其實很多擁有大的資源信息的網站或者公司都有自己的開發平台的,用來開放自己的一些資源信息,通過比如說auth2.0等一些折中的手段來達到擁有大的資源信息的網站或者公司和開發者的共贏的局面,因為擁有大的資源信息的網站或者公司的可以根據開發者開發出來的應用的類型來定向的判斷用戶類型,這樣之后,擁有大的資源信息的網站或者公司就可以根據用戶是什么類型的,定向的推送廣告,做大數據分析,與此同時,開發者也能達到開發出自己完整的應用的目的,真正的共贏。
先簡略的講一下auth2.0是怎么工作的,這里有一片好文章,大家可以看一下,這里我也講一下:
其實auth2.0工作有幾種模式:簡化模式,密碼模式,客戶端模式,授權碼模式,其中授權碼模式是使用最多的,這里我就分析一下授權碼模式,qq開放互聯平台就是使用這種模式,如下圖:
首先明確一下角色,user-gent:用戶(或者可以說是用戶瀏覽器); client:第三方網站或者應用; authorization server:認證服務器,它不是被第三方網站或者應用所擁有的,是放在原來的所有者(如騰訊)那里的;resource owner:資源(如騰訊的qq用戶群,為騰訊所擁有)存放的地方,它是可以和authorization server互通的;總共有四個對象。
流程是這樣運轉的:
步驟A:先是user-agent訪問client,client需要確定user-agent是誰,但是client沒有user-agent的用戶和密碼,無法驗證驗證用戶,所以將user-agent通過A步驟將重定向(導向)到authorization-server那里(如果是client是通過qq來驗證用戶,這個時候用戶就會發現自己的瀏覽器跳到qq登錄的界面),同時重定向過程中也會附帶一些信息,方便后面的操作,這個步驟最重要的信息就是redirect url和client identifier這兩個參數
步驟B(user authentication):用戶在登錄界面就會輸入用戶名和密碼給authorization server,authorization server發現用戶名和密碼正確,發現確實有這個用戶存在,就會要用戶是否授權給client給訪問他的個人信息
步驟C:得到了用戶的允許之后,authorization server就會根據步驟A得到redirect url將用戶重定向到client那里,同時攜帶authorization code和一些其他的信息給client,這之前的步驟對用戶來都是可見的,后面的步驟對用戶不可見;
步驟D:這個時候用戶就來到了client這界面了,這個時候client就會獲取authorization code,如果有這個參數,代表用戶已經授權了,client就攜帶authorization code和redirect url訪問authentication server,向其索要訪問用戶信息的access token
步驟E:如果authorization code沒有是有效的,authorization server就會將access token發給client,同時access token是有期限的
步驟F:cleint就會攜帶得到的access token去訪問resource owner,由於resource owner和authorization server是互通的,所以resource owner可以驗證access token是否有效或者過期,如果有效和沒有過期,那么就會允許client訪問之前那個用戶的一些信息了。
其實上面都是看文檔得來的
好了,講了auth2.0(其實肯定由auth1.0,有興趣可以自己去了解)流程之后,下面就是實現了。
環境:tornado, linux(linux mint 類ubuntu),新浪雲,qq互聯驗證平台
新浪雲申請免費域名之用,因為qq互聯驗證平台要一個真正的域名,不像優酷開發平台直接上一個ip地址就可以了。
先講一下新浪雲怎么申請免費域名(又到了看文檔的時候了),這樣子吧,先來圖:
看到了上面的創建應用的按鈕了嗎?那就是你可以申請域名的按鈕了,新浪雲原理是這樣子的,就是你將你的小應用開發好,然后將你的應用調試成其要求的環境,通過git或者svn這類的版本控制器將你的應用傳到其要求的地方,然后你就可以通過其給你自定義的域名(域名是你創建的應用的時候,你自己指定的,我這里指定的是zhougch501.sinaapp.com)來訪問你的應用了,其間的部署的工作,sina雲已經幫你做好了,你不用擔心,方便不?
這之間有幾個要注意地方:1.如何通過git或者svn來將自己的應用傳上去,可以看這里,我個人推薦使用git,如果不會使用git,可以看這里,好了,我就創建一個應用做示范吧
當然先是點擊創建應用按鈕,這里我創建的應用是zhougch502
點擊創建之后:
選擇開發語言python2.7
然后就是創建羅,創建成功了之后就要進入應用的管理界面了,進入應用管理界面之后就可以點擊代碼管理了,然后他就會讓你選擇是git還是svn,這里我選擇的是git了
選擇了git了之后就會在頁面中顯示如何將將代碼上傳到新浪雲了,頁面最下面的藍色的鏈接有更細的說怎么做,你可以去看一下。
2.如何將自己的應用調試新浪雲要求的環境,這里面有詳細的介紹(又到了看文檔的時候了)
ok,到了講解如何使用新浪雲給的域名來在qq互聯平台使用qq來實現auth2.0的認證流程,這里有了上面我講解auth2.0的知識准備,這里就簡單多了
先是看qq互聯平台給的auth2.0文檔,為什么還要看文檔^~^,因為qq互聯平台對auth2.0標准認證流程做了一些改動,同時qq互聯平台提供了兩種接入方式,有網站接入和app接入,這里我講解的是網站的接入。好了,在這個之前,我還要做一些准備工作。看這里 ,其實就是在qq互聯平台上里面創建一個應用,和在新浪雲里面一樣,有木有,哈哈哈。流程截圖如下:
看到了申請地址了沒有,進入了之后就可以點擊管理中心了,然后點擊創建應用,然后選擇應用類型為網站:
然后就是應用的信息填寫,里面的信息怎么填寫,填寫界面都給出相應的信息和文檔(又要看文檔,醉了),里面網站地址就是之前在新浪雲上面免費申請的網址,看到了吧,之前的工作是有用的
好了,這之后就有了qq互聯平台的appid和appkey,不知道appid和appkey的孩子們,看這里,在未審核項里面就有你的剛剛創建的應用
點擊你的應用進去之后就可以看到你的appid和appkey了
ok,准備工作已經完成了,然后你就可以根據我之前講的auth2.0知識來參考qq互聯給的文檔來實現使用qq登錄讓用戶授權來獲取用戶信息。qq互聯平台上也有代碼示例,是使用PHP來實現的,會寫程序的人都能看得懂的。
然后就是最后我的實現,大家可以點擊這里試一下。
下面我在linux使用tornado(python)實現代碼,可以參考一下,注意:這里代碼是部署到新浪雲的代碼了
# -*- coding: utf-8 -*- import tornado.wsgi import os.path import httplib import urllib import urllib2 import sae from urllib import quote class BaseHandler(tornado.web.RequestHandler): def get_current_user(self): return self.get_secure_cookie("username") class LoginHandler(BaseHandler): def get(self): self.render('login.html') class WelcomeHandler(BaseHandler): # get code def get(self): if self.get_argument("code", None) and str(self.get_argument("state", None)) == "test": # get token code = self.get_argument("code") redirect_url = quote("http://zhougch501.sinaapp.com/") req_url = "https://graph.qq.com/oauth2.0/token?grant_type=authorization_code&client_id=101265051&client_secret=b238da816c4e4dcb598836084dcea067&redirect_uri=" + redirect_url + "&code=" + code req = urllib2.Request(req_url) res_data = urllib2.urlopen(req) res = res_data.read() res = res.split("&") access_token = res[0].split("=") access_token = access_token[1] # 獲取用戶的openid req_url = "https://graph.qq.com/oauth2.0/me?access_token=" + access_token req = urllib2.Request(req_url) res_data = urllib2.urlopen(req) res = res_data.read() # get openid # callback( {"client_id":"YOUR_APPID","openid":"YOUR_OPENID"} ) res = res.split(",") res = res[1].split(":") res = res[1].split("\"") openid = res[1] # 獲取用戶的信息 req_url = "https://graph.qq.com/user/get_user_info?access_token=" + access_token + "&oauth_consumer_key=101265051&openid=" + openid req = urllib2.Request(req_url) res_data = urllib2.urlopen(req) res = res_data.read() res.replace("{", "") res.replace("\"", "") res = res.split(",") name = "" # info = {} for index in range(len(res)): if index == 3: name = (res[index].split(":"))[1] self.render("index.html", info=name) else: if self.current_user: self.render('index.html', user=self.current_user) else: self.redirect("/login") class LoginQQHandler(BaseHandler): def get(self): redirect_url = quote("http://zhougch501.sinaapp.com/") req_url = "https://graph.qq.com/oauth2.0/authorize?response_type=code&client_id=101265051&redirect_uri=" + redirect_url + "&state=test" self.redirect(req_url) class LogoutHandler(BaseHandler): def get(self): # if (self.get_argument("logout", None)): self.clear_cookie("username") self.redirect("/") settings = { "template_path": os.path.join(os.path.dirname(__file__), "templates"), "static_path": os.path.join(os.path.dirname(__file__), "static"), "cookie_secret": "bZJc2sWbQLKos6GkHn/VB9oXwQt8S0R0kRvJ5/xJ89E=", "xsrf_cookies": True, "login_url": "/login" } app = tornado.wsgi.WSGIApplication([ (r'/', WelcomeHandler), (r'/login', LoginHandler), (r'/loginWithQQ', LoginQQHandler), (r'/logout', LogoutHandler) ], **settings) application = sae.create_wsgi_app(app)