


Detailed explanation of examples of ASP.NET implementing OAuth2.0 authorized login for QQ, WeChat, and Sina Weibo
Apr 25, 2017 am 10:44 AMThis article mainly introduces examples of OAuth2.0 authorized login for QQ, WeChat, and Sina Weibo. It mainly uses GET and POST remote interfaces to return corresponding data. The relevant codes are listed here for your reference.
Whether it is Tencent or Sina, if you look at their APIs, PHP has a complete interface, but the support for C# does not seem to be that complete, and there is none. Tencent does not have it at all, and Sina provides a third party. And it may not be upgraded later. NND, using a third-party library often requires only one class library, and various configurations must be written according to their agreement. It is annoying and messy, so I simply write it myself. Later expansion is also easy. After reading the interface, start I thought it was difficult, but after referring to several source codes, I found that it is not that difficult. It is nothing more than GET or POST requesting their interface to obtain the return value. Without further ado, here are just a few codes for reference. . .
The characteristic of my writing method is that it uses Session. After instantiating the object, it calls Login() to jump to the login page. After calling Callback() on the callback page, it can be written independently from Session or Get the access_token or the user's unique identifier in the function (such as GetOpenID()) to facilitate the next step. The so-called binding is to take out the user's unique identifier, insert it into the database, and bind it to the account.
1. First is the base class of all OAuth classes, and put some methods that need to be public
public abstract class BaseOAuth { public HttpRequest Request = HttpContext.Current.Request; public HttpResponse Response = HttpContext.Current.Response; public HttpSessionState Session = HttpContext.Current.Session; public abstract void Login(); public abstract string Callback(); #region 內(nèi)部使用函數(shù) /// <summary> /// 生成唯一隨機(jī)串防CSRF攻擊 /// </summary> /// <returns></returns> protected string GetStateCode() { Random rand = new Random(); string data = DateTime.Now.ToString("yyyyMMddHHmmssffff") + rand.Next(1, 0xf423f).ToString(); MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider(); byte[] md5byte = md5.ComputeHash(UTF8Encoding.Default.GetBytes(data)); return BitConverter.ToString(md5byte).Replace("-", ""); } /// <summary> /// GET請求 /// </summary> /// <param name="url"></param> /// <returns></returns> protected string GetRequest(string url) { HttpWebRequest httpWebRequest = System.Net.WebRequest.Create(url) as HttpWebRequest; httpWebRequest.Method = "GET"; httpWebRequest.ServicePoint.Expect100Continue = false; StreamReader responseReader = null; string responseData; try { responseReader = new StreamReader(httpWebRequest.GetResponse().GetResponseStream()); responseData = responseReader.ReadToEnd(); } finally { httpWebRequest.GetResponse().GetResponseStream().Close(); responseReader.Close(); } return responseData; } /// <summary> /// POST請求 /// </summary> /// <param name="url"></param> /// <param name="postData"></param> /// <returns></returns> protected string PostRequest(string url, string postData) { HttpWebRequest httpWebRequest = System.Net.WebRequest.Create(url) as HttpWebRequest; httpWebRequest.Method = "POST"; httpWebRequest.ServicePoint.Expect100Continue = false; httpWebRequest.ContentType = "application/x-www-form-urlencoded"; //寫入POST參數(shù) StreamWriter requestWriter = new StreamWriter(httpWebRequest.GetRequestStream()); try { requestWriter.Write(postData); } finally { requestWriter.Close(); } //讀取請求后的結(jié)果 StreamReader responseReader = null; string responseData; try { responseReader = new StreamReader(httpWebRequest.GetResponse().GetResponseStream()); responseData = responseReader.ReadToEnd(); } finally { httpWebRequest.GetResponse().GetResponseStream().Close(); responseReader.Close(); } return responseData; } /// <summary> /// 解析JSON /// </summary> /// <param name="strJson"></param> /// <returns></returns> protected NameValueCollection ParseJson(string strJson) { NameValueCollection mc = new NameValueCollection(); Regex regex = new Regex(@"(\s*\""?([^""]*)\""?\s*\:\s*\""?([^""]*)\""?\,?)"); strJson = strJson.Trim(); if (strJson.StartsWith("{")) { strJson = strJson.Substring(1, strJson.Length - 2); } foreach (Match m in regex.Matches(strJson)) { mc.Add(m.Groups[2].Value, m.Groups[3].Value); } return mc; } /// <summary> /// 解析URL /// </summary> /// <param name="strParams"></param> /// <returns></returns> protected NameValueCollection ParseUrlParameters(string strParams) { NameValueCollection nc = new NameValueCollection(); foreach (string p in strParams.Split('&')) { string[] ps = p.Split('='); nc.Add(ps[0], ps[1]); } return nc; } #endregion }
2. QQ’s OAuth class
public class QQOAuth : BaseOAuth { public string AppId = ConfigurationManager.AppSettings["OAuth_QQ_AppId"]; public string AppKey = ConfigurationManager.AppSettings["OAuth_QQ_AppKey"]; public string RedirectUrl = ConfigurationManager.AppSettings["OAuth_QQ_RedirectUrl"]; public const string GET_AUTH_CODE_URL = "https://graph.qq.com/oauth2.0/authorize"; public const string GET_ACCESS_TOKEN_URL = "https://graph.qq.com/oauth2.0/token"; public const string GET_OPENID_URL = "https://graph.qq.com/oauth2.0/me"; /// <summary> /// QQ登錄,跳轉(zhuǎn)到登錄頁面 /// </summary> public override void Login() { //-------生成唯一隨機(jī)串防CSRF攻擊 string state = GetStateCode(); Session["QC_State"] = state; //state 放入Session string parms = "?response_type=code&" + "client_id=" + AppId + "&redirect_uri=" + Uri.EscapeDataString(RedirectUrl) + "&state=" + state; string url = GET_AUTH_CODE_URL + parms; Response.Redirect(url); //跳轉(zhuǎn)到登錄頁面 } /// <summary> /// QQ回調(diào)函數(shù) /// </summary> /// <param name="code"></param> /// <param name="state"></param> /// <returns></returns> public override string Callback() { string code = Request.QueryString["code"]; string state = Request.QueryString["state"]; //--------驗證state防止CSRF攻擊 if (state != (string)Session["QC_State"]) { ShowError("30001"); } string parms = "?grant_type=authorization_code&" + "client_id=" + AppId + "&redirect_uri=" + Uri.EscapeDataString(RedirectUrl) + "&client_secret=" + AppKey + "&code=" + code; string url = GET_ACCESS_TOKEN_URL + parms; string str = GetRequest(url); if (str.IndexOf("callback") != -1) { int lpos = str.IndexOf("("); int rpos = str.IndexOf(")"); str = str.Substring(lpos + 1, rpos - lpos - 1); NameValueCollection msg = ParseJson(str); if (!string.IsNullOrEmpty(msg["error"])) { ShowError(msg["error"], msg["error_description"]); } } NameValueCollection token = ParseUrlParameters(str); Session["QC_AccessToken"] = token["access_token"]; //access_token 放入Session return token["access_token"]; } /// <summary> /// 使用Access Token來獲取用戶的OpenID /// </summary> /// <param name="accessToken"></param> /// <returns></returns> public string GetOpenID() { string parms = "?access_token=" + Session["QC_AccessToken"]; string url = GET_OPENID_URL + parms; string str = GetRequest(url); if (str.IndexOf("callback") != -1) { int lpos = str.IndexOf("("); int rpos = str.IndexOf(")"); str = str.Substring(lpos + 1, rpos - lpos - 1); } NameValueCollection user = ParseJson(str); if (!string.IsNullOrEmpty(user["error"])) { ShowError(user["error"], user["error_description"]); } Session["QC_OpenId"] = user["openid"]; //openid 放入Session return user["openid"]; } /// <summary> /// 顯示錯誤信息 /// </summary> /// <param name="code">錯誤編號</param> /// <param name="description">錯誤描述</param> private void ShowError(string code, string description = null) { if (description == null) { switch (code) { case "20001": description = "<h2>配置文件損壞或無法讀取,請檢查web.config</h2>"; break; case "30001": description = "<h2>The state does not match. You may be a victim of CSRF.</h2>"; break; case "50001": description = "<h2>可能是服務(wù)器無法請求https協(xié)議</h2>可能未開啟curl支持,請嘗試開啟curl支持,重啟web服務(wù)器,如果問題仍未解決,請聯(lián)系我們"; break; default: description = "<h2>系統(tǒng)未知錯誤,請聯(lián)系我們</h2>"; break; } Response.Write(description); Response.End(); } else { Response.Write("<h3>error:<h3>" + code + "<h3>msg:<h3>" + description); Response.End(); } } }
3. Sina Weibo’s OAuth class
public class SinaOAuth : BaseOAuth { public string AppKey = ConfigurationManager.AppSettings["OAuth_Sina_AppKey"]; public string AppSecret = ConfigurationManager.AppSettings["OAuth_Sina_AppSecret"]; public string RedirectUrl = ConfigurationManager.AppSettings["OAuth_Sina_RedirectUrl"]; public const string GET_AUTH_CODE_URL = "https://api.weibo.com/oauth2/authorize"; public const string GET_ACCESS_TOKEN_URL = "https://api.weibo.com/oauth2/access_token"; public const string GET_UID_URL = "https://api.weibo.com/2/account/get_uid.json"; /// <summary> /// 新浪微博登錄,跳轉(zhuǎn)到登錄頁面 /// </summary> public override void Login() { //-------生成唯一隨機(jī)串防CSRF攻擊 string state = GetStateCode(); Session["Sina_State"] = state; //state 放入Session string parms = "?client_id=" + AppKey + "&redirect_uri=" + Uri.EscapeDataString(RedirectUrl) + "&state=" + state; string url = GET_AUTH_CODE_URL + parms; Response.Redirect(url); //跳轉(zhuǎn)到登錄頁面 } /// <summary> /// 新浪微博回調(diào)函數(shù) /// </summary> /// <returns></returns> public override string Callback() { string code = Request.QueryString["code"]; string state = Request.QueryString["state"]; //--------驗證state防止CSRF攻擊 if (state != (string)Session["Sina_State"]) { ShowError("The state does not match. You may be a victim of CSRF."); } string parms = "client_id=" + AppKey + "&client_secret=" + AppSecret + "&grant_type=authorization_code&code=" + code + "&redirect_uri=" + Uri.EscapeDataString(RedirectUrl); string str = PostRequest(GET_ACCESS_TOKEN_URL, parms); NameValueCollection user = ParseJson(str); Session["Sina_AccessToken"] = user["access_token"]; //access_token 放入Session Session["Sina_UId"] = user["uid"]; //uid 放入Session return user["access_token"]; } /// <summary> /// 顯示錯誤信息 /// </summary> /// <param name="description">錯誤描述</param> private void ShowError(string description = null) { Response.Write("<h2>" + description + "</h2>"); Response.End(); } }
4. WeChat’s OAuth class
public class WeixinOAuth : BaseOAuth { public string AppId = ConfigurationManager.AppSettings["OAuth_Weixin_AppId"]; public string AppSecret = ConfigurationManager.AppSettings["OAuth_Weixin_AppSecret"]; public string RedirectUrl = ConfigurationManager.AppSettings["OAuth_Weixin_RedirectUrl"]; public const string GET_AUTH_CODE_URL = "https://open.weixin.qq.com/connect/qrconnect"; public const string GET_ACCESS_TOKEN_URL = "https://api.weixin.qq.com/sns/oauth2/access_token"; public const string GET_USERINFO_URL = "https://api.weixin.qq.com/sns/userinfo"; /// <summary> /// 微信登錄,跳轉(zhuǎn)到登錄頁面 /// </summary> public override void Login() { //-------生成唯一隨機(jī)串防CSRF攻擊 string state = GetStateCode(); Session["Weixin_State"] = state; //state 放入Session string parms = "?appid=" + AppId + "&redirect_uri=" + Uri.EscapeDataString(RedirectUrl) + "&response_type=code&scope=snsapi_login" + "&state=" + state + "#wechat_redirect"; string url = GET_AUTH_CODE_URL + parms; Response.Redirect(url); //跳轉(zhuǎn)到登錄頁面 } /// <summary> /// 微信回調(diào)函數(shù) /// </summary> /// <param name="code"></param> /// <param name="state"></param> /// <returns></returns> public override string Callback() { string code = Request.QueryString["code"]; string state = Request.QueryString["state"]; //--------驗證state防止CSRF攻擊 if (state != (string)Session["Weixin_State"]) { ShowError("30001"); } string parms = "?appid=" + AppId + "&secret=" + AppSecret + "&code=" + code + "&grant_type=authorization_code"; string url = GET_ACCESS_TOKEN_URL + parms; string str = GetRequest(url); NameValueCollection msg = ParseJson(str); if (!string.IsNullOrEmpty(msg["errcode"])) { ShowError(msg["errcode"], msg["errmsg"]); } Session["Weixin_AccessToken"] = msg["access_token"]; //access_token 放入Session Session["Weixin_OpenId"] = msg["openid"]; //access_token 放入Session return msg["access_token"]; } /// <summary> /// 顯示錯誤信息 /// </summary> /// <param name="code">錯誤編號</param> /// <param name="description">錯誤描述</param> private void ShowError(string code, string description = null) { if (description == null) { switch (code) { case "20001": description = "<h2>配置文件損壞或無法讀取,請檢查web.config</h2>"; break; case "30001": description = "<h2>The state does not match. You may be a victim of CSRF.</h2>"; break; case "50001": description = "<h2>接口未授權(quán)</h2>"; break; default: description = "<h2>系統(tǒng)未知錯誤,請聯(lián)系我們</h2>"; break; } Response.Write(description); Response.End(); } else { Response.Write("<h3>error:<h3>" + code + "<h3>msg:<h3>" + description); Response.End(); } } }
5. web.config configuration information
<appSettings> <!--QQ登錄相關(guān)配置--> <add key="OAuth_QQ_AppId" value="123456789" /> <add key="OAuth_QQ_AppKey" value="25f9e794323b453885f5181f1b624d0b" /> <add key="OAuth_QQ_RedirectUrl" value="http://www.domain.com/oauth20/qqcallback.aspx" /> <!--新浪微博登錄相關(guān)配置--> <add key="OAuth_Sina_AppKey" value="123456789" /> <add key="OAuth_Sina_AppSecret" value="25f9e794323b453885f5181f1b624d0b" /> <add key="OAuth_Sina_RedirectUrl" value="http://www.domain.com/oauth20/sinacallback.aspx" /> <!--微信登錄相關(guān)配置--> <add key="OAuth_Weixin_AppId" value="wx123456789123" /> <add key="OAuth_Weixin_AppSecret" value="25f9e794323b453885f5181f1b624d0b" /> <add key="OAuth_Weixin_RedirectUrl" value="http://www.domain.com/oauth20/weixincallback.aspx" /> </appSettings>
The above is the detailed content of Detailed explanation of examples of ASP.NET implementing OAuth2.0 authorized login for QQ, WeChat, and Sina Weibo. For more information, please follow other related articles on the PHP Chinese website!

Hot AI Tools

Undress AI Tool
Undress images for free

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Clothoff.io
AI clothes remover

Video Face Swap
Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Article

Hot Tools

Notepad++7.3.1
Easy-to-use and free code editor

SublimeText3 Chinese version
Chinese version, very easy to use

Zend Studio 13.0.1
Powerful PHP integrated development environment

Dreamweaver CS6
Visual web development tools

SublimeText3 Mac version
God-level code editing software (SublimeText3)
