Maison  >  Article  >  Applet WeChat  >  Explication détaillée d'exemples d'ASP.NET implémentant la connexion autorisée OAuth2.0 pour QQ, WeChat et Sina Weibo

Explication détaillée d'exemples d'ASP.NET implémentant la connexion autorisée OAuth2.0 pour QQ, WeChat et Sina Weibo

Y2J
Y2Joriginal
2017-04-25 10:44:091548parcourir

Cet article présente principalement des exemples de connexion autorisée OAuth2.0 pour QQ, WeChat et Sina Weibo. Il utilise principalement les interfaces distantes GET et POST pour renvoyer les données correspondantes. Les codes pertinents sont répertoriés ici pour votre référence.

Qu'il s'agisse de Tencent ou de Sina, si vous regardez leurs API, PHP a une interface complète, mais le support de C# ne semble pas si complet, et il n'y en a pas chez Tencent. tout, et Sina fournit un tiers. Et il ne peut pas être mis à niveau plus tard. NND, l'utilisation d'une bibliothèque tierce ne nécessite souvent qu'une seule bibliothèque de classes, et diverses configurations doivent être écrites selon leur accord. Je l'écris simplement moi-même. L'expansion ultérieure est également facile. Après avoir lu l'interface, j'ai pensé que c'était difficile, mais après avoir consulté plusieurs codes sources, j'ai trouvé que ce n'était rien de plus qu'une requête GET ou POST. leur interface pour obtenir la valeur de retour. Sans plus tarder, voici juste quelques codes pour référence. . .

La caractéristique de ma méthode d'écriture est qu'elle utilise Session. Après avoir instancié l'objet, elle appelle Login() pour accéder à la page de connexion. Après avoir appelé Callback() sur la page de rappel, il peut être écrit depuis. Session ou indépendamment. Obtenez le access_token ou l'identifiant unique de l'utilisateur dans la fonction (comme GetOpenID()) pour faciliter l'étape suivante. La soi-disant liaison consiste à extraire l'identifiant unique de l'utilisateur, à l'insérer dans la base de données et à le lier au compte.

1. Tout d'abord, la classe de base de toutes les classes OAuth, mettez quelques méthodes qui doivent être publiques

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 内部使用函数
  /// <summary>
  /// 生成唯一随机串防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参数
    StreamWriter requestWriter = new StreamWriter(httpWebRequest.GetRequestStream());
    try
    {
      requestWriter.Write(postData);
    }
    finally
    {
      requestWriter.Close();
    }

    //读取请求后的结果
    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(&#39;&&#39;))
    {
      string[] ps = p.Split(&#39;=&#39;);
      nc.Add(ps[0], ps[1]);
    }
    return nc;
  }

  #endregion

}

2. 🎜>

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登录,跳转到登录页面
  /// </summary>
  public override void Login()
  {
    //-------生成唯一随机串防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); //跳转到登录页面
  }

  /// <summary>
  /// QQ回调函数
  /// </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>可能是服务器无法请求https协议</h2>可能未开启curl支持,请尝试开启curl支持,重启web服务器,如果问题仍未解决,请联系我们";
          break;
        default:
          description = "<h2>系统未知错误,请联系我们</h2>";
          break;
      }
      Response.Write(description);
      Response.End();
    }
    else
    {
      Response.Write("<h3>error:<h3>" + code + "<h3>msg:<h3>" + description);
      Response.End();
    }
  }

}

3. La classe OAuth de Sina Weibo

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>
  /// 新浪微博登录,跳转到登录页面
  /// </summary>
  public override void Login()
  {
    //-------生成唯一随机串防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); //跳转到登录页面
  }

  /// <summary>
  /// 新浪微博回调函数
  /// </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. La classe OAuth de WeChat

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>
  /// 微信登录,跳转到登录页面
  /// </summary>
  public override void Login()
  {
    //-------生成唯一随机串防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); //跳转到登录页面
  }

  /// <summary>
  /// 微信回调函数
  /// </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>接口未授权</h2>";
          break;
        default:
          description = "<h2>系统未知错误,请联系我们</h2>";
          break;
      }
      Response.Write(description);
      Response.End();
    }
    else
    {
      Response.Write("<h3>error:<h3>" + code + "<h3>msg:<h3>" + description);
      Response.End();
    }
  }

}

5.web.config informations de configuration

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn