天天看點

網站內建QQ登入功能

最近在做一個項目時,客戶要求網站能夠內建QQ登入的功能,以前沒做過這方面的開發,于是去QQ的開放平台官網研究了一下相關資料,經過自己的艱苦探索,終于實作了內建QQ登入的功能,現在把相關的開發經驗總結一下,希望對有這方面需求的朋友有所幫助。

一.前期準備

首先你需要登入QQ的開發平台注冊一個賬号,QQ互聯平台官方位址:

http://connect.qq.com/  進去後注冊一個開發賬号,完了登入背景會有類似如下的一個背景,填好相關資訊,具體可以參考下圖。最後我們會有一個APP ID和APP KEY ,有了這兩個東西才能實作後面的內建QQ登入功能。
網站內建QQ登入功能

二.開發工作

當我們的賬号稽核後,QQ開發平台會給我們一個APP ID和APP KEY,有了這兩個,我們就可以進行開發的工作了。

QQ的登入采用的是OAuth2.0協定,OAuth(開放授權)是一個開放标準,允許使用者授權第三方網站通路他們存儲在另外的服務提供者上的資訊,而不需要将使用者名和密碼提供給第三方網站或分享他們資料的所有内容。具體的内容可以參考QQ的API文檔http://wiki.connect.qq.com/oauth2-0%e7%ae%80%e4%bb%8b

QQ的開發平台已經有PHP,JAVA,JS等版本的SDK了,如果是要用到這些語言進行開發的可以直接參考這些SDK,我這邊直接講一下ASP.NET版本(MVC)的開發。

第一步.先在WebConfig中的 <appSettings>節點下加入如下配置

<add key=

"QQAppID"

value=

"QQ平台給的APP ID"

/>

<add key=

"QQAppKey"

value=

"QQ開發平台給的APP KEY"

/>

<add key=

"QQCallBack"

value=

"http://www.mylanqiu.com/Account/QQConnect/"

/>

<add key=

"QQAuthorizeURL"

value=

"https://graph.qq.com/oauth2.0/authorize"

/>

第二步.在Controllers中加一個登陸的Action(我這邊用的是MVC的開發方式,如果是傳統.NET的可以直接在.aspx的Page_Load事件裡加如下方法)

public

ActionResult LoginQQ()

{

string

state = 

new

Random(100000).Next(99, 99999).ToString();

//随機數

Session[

"QQState"

] = state;

string

appID = ConfigurationManager.AppSettings[

"QQAppID"

];

string

qqAuthorizeURL = ConfigurationManager.AppSettings[

"QQAuthorizeURL"

];

string

callback = ConfigurationManager.AppSettings[

"QQCallBack"

];

string

authenticationUrl = 

string

.Format(

"{0}?client_id={1}&response_type=code&redirect_uri={2}&state={3}"

, qqAuthorizeURL, appID, callback, state);

//互聯位址

return

new

RedirectResult(authenticationUrl);

}

這一步主要是實作去QQ平台進行身份驗證,直覺點也就是點選後會去出現如下截圖的畫面

網站內建QQ登入功能

第三步.在點選了上圖的同意登入後(也就是已經使用QQ号在QQ平台登入),QQ平台會通過我們上面配置的回調位址也就是我這邊填的

http://www.mylanqiu.com/Account/WeiboConnect/

傳回到這個頁面,并會傳回一個code給我們,我們到時會使用這個code再去QQ開發平台擷取access_token,并通過這個access_token擷取登入的相關使用者資訊。具體代碼如下:

/// <summary>

/// QQ回調頁面

/// </summary>

public

ActionResult QQConnect()

{

if

(!

string

.IsNullOrEmpty(Request.Params[

"code"

]) && !

string

.IsNullOrEmpty(Request.Params[

"state"

]))

{

var

code = Request.Params[

"code"

];

var

state = Request.Params[

"state"

];

string

requestState = Session[

"QQState"

] == 

null

""

: Session[

"QQState"

].ToString();

if

(state == requestState)

{

try

{

QQOAuthHelper QAuthHelper = 

new

QQOAuthHelper();

//這是一個輔助類,代碼會在下面給出

QQOauthInfo qqOauthInfo = QAuthHelper.GetOauthInfo(code);

string

openID = QAuthHelper.GetOpenID(qqOauthInfo);

//擷取用的OpenID,這個ID是QQ給我們的使用者的唯一ID,可以作為我們系統使用者唯一性的判斷存在我們自己的庫中

Session[

"QQOpenID"

] = openID;

string

nickName = QAuthHelper.GetUserInfo(qqOauthInfo, openID);

//擷取使用者的昵稱

UserAccount userAccount = AccountBLL.GetUserAccountByOpenID(OAuthPlatform.QQ.ToString(), openID);

if

(userAccount != 

null

)

//判斷是否是已用該OpenID是否已在我們的庫中,若已存在則允許登入

{

SetAuthCookie(userAccount);

Response.Write(

"<script> window.opener.location.reload();window.close();</script>"

);

}

ViewData[

"NickName"

] = nickName;

}

catch

(Exception ex)

{

return

new

RedirectResult(

"~/Error/Error.htm"

);

}

}

else

{

return

new

RedirectResult(

"~/Error/Error.htm"

);

}

}

else

{

return

new

RedirectResult(

"~/Error/Error.htm"

);

}

return

View();

}

通過上面的步驟就可以實作網站內建QQ登入了。下面給出輔助類的源代碼:

using

System;

using

System.Text;

using

System.Configuration;

using

System.Collections.Generic;

using

System.Linq;

using

System.Net;

using

System.Web;

using

System.IO;

namespace

Com.ABC.Mylanqiu.BLL

{

public

class

QQOAuthHelper

{

string

appID = ConfigurationManager.AppSettings[

"QQAppID"

];

string

appKey = ConfigurationManager.AppSettings[

"QQAppKey"

];

/// <summary>

/// 擷取oauth資訊

/// </summary>

/// <param name="code"></param>

/// <returns></returns>

public

QQOauthInfo GetOauthInfo(

string

code)

{

string

callback = System.Web.HttpUtility.UrlEncode(ConfigurationManager.AppSettings[

"QQCallBack"

], Encoding.UTF8);

string

url = 

string

.Format(

"https://graph.qq.com/oauth2.0/token?grant_type={0}&client_id={1}&client_secret={2}&code={3}&redirect_uri={4}"

"authorization_code"

, appID, appKey, code, callback);

string

res = LoadHtmlUserGetType(url, Encoding.UTF8);

QQOauthInfo qqOauthInfo = 

new

QQOauthInfo();

qqOauthInfo.AccessToken = CutString(res, 

"access_token="

"&expires_in="

);

qqOauthInfo.ExpiresIn = CutString(res, 

"&expires_in="

"&refresh_token="

);

qqOauthInfo.RefreshToken = res.Split(

new

string

[] { 

"&refresh_token="

}, StringSplitOptions.None)[1];

return

qqOauthInfo;

}

/// <summary>

/// 截取字元串中兩個字元串中的字元串

/// </summary>

/// <param name="str">字元串</param>

/// <param name="startStr">開始字元串</param>

/// <param name="endStr">結束字元串</param>

/// <returns></returns>

private

string

CutString(

string

str, 

string

startStr, 

string

endStr)

{

int

begin, end;

begin = str.IndexOf(startStr, 0) + startStr.Length; 

//開始位置

end = str.IndexOf(endStr, begin); 

//結束位置

return

str.Substring(begin, end - begin); 

//取搜尋的條數,用結束的位置-開始的位置,并傳回

}

/// <summary>

/// 通過GET方式擷取頁面的方法

/// </summary>

/// <param name="urlString">請求的URL</param>

/// <param name="encoding">頁面編碼</param>

/// <returns></returns>

public

string

LoadHtmlUserGetType(

string

urlString, Encoding encoding)

{

HttpWebRequest httpWebRequest = 

null

;

HttpWebResponse httpWebRespones = 

null

;

Stream stream = 

null

;

string

htmlString = 

string

.Empty;

try

{

httpWebRequest = WebRequest.Create(urlString) 

as

HttpWebRequest;

}

catch

(Exception ex)

{

throw

new

Exception(

"建立頁面請求時發生錯誤!"

, ex);

}

httpWebRequest.UserAgent = 

"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; .NET CLR 2.0.50727; Maxthon 2.0)"

;

try

{

httpWebRespones = (HttpWebResponse)httpWebRequest.GetResponse();

stream = httpWebRespones.GetResponseStream();

}

catch

(Exception ex)

{

throw

new

Exception(

"接受伺服器傳回頁面時發生錯誤!"

, ex);

}

StreamReader streamReader = 

new

StreamReader(stream, encoding);

try

{

htmlString = streamReader.ReadToEnd();

}

catch

(Exception ex)

{

throw

new

Exception(

"讀取頁面資料時發生錯誤!"

, ex);

}

streamReader.Close();

stream.Close();

return

htmlString;

}

/// <summary>

/// 擷取QQ賬号的OpenID

/// </summary>

/// <param name="qqOauthInfo"></param>

/// <returns></returns>

public

string

GetOpenID(QQOauthInfo qqOauthInfo)

{

string

res = LoadHtmlUserGetType(

"https://graph.qq.com/oauth2.0/me?access_token="

+ qqOauthInfo.AccessToken, Encoding.UTF8);

return

CutString(res, 

@"openid"":"""

@"""}"

);

}

/// <summary>

/// 擷取QQ昵稱

/// </summary>

/// <param name="qqOauthInfo"></param>

/// <param name="openID"></param>

/// <returns></returns>

public

string

GetUserInfo(QQOauthInfo qqOauthInfo, 

string

openID)

{

string

urlGetInfo = 

string

.Format(

@"https://graph.qq.com/user/get_user_info?access_token={0}&oauth_consumer_key={1}&openid={2}"

, qqOauthInfo.AccessToken,appID, openID);

string

resUserInfo = LoadHtmlUserGetType(urlGetInfo, Encoding.UTF8);

return

CutString(resUserInfo, 

@"""nickname"": """

@""","

);

}

}

public

class

QQOauthInfo

{

public

string

AccessToken { 

get

set

; }

public

string

ExpiresIn { 

get

set

; }

public

string

RefreshToken { 

get

set

; }

}

}

四.Demo效果

大家可以直接通路

http://www.mylanqiu.com

看一下實際的效果,最後感謝大家的閱讀,如對你有所幫助就多多轉發,以幫助更多人,正所謂:贈人玫瑰 手有餘香!如有不足,還請指正!

繼續閱讀