zoukankan      html  css  js  c++  java
  • ASP.NET MVC应用程序中支持用户使用腾讯QQ和微信以及新浪微博的第三方登录

    什么是第三方授权登录,就是一些大家都会有的帐号如QQ、微信、淘宝、微博等账户。通过那些巨头公司提供的api直接实现登录。

    当然,我们是不可能得到你的用户名和密码的。不了解的人,可能会存在这个疑虑。我们可以通过第三方授权登录得到如昵称、性别、注册地址、年龄、头像等基本信息。当然,我们也可以得到你账户因为的唯一编码,就是OAuthId。什么是OAuth技术?大家自行了解,这里就不细讲了。

    准备资料:

    各平台相关授权appid以及appkey(新浪为App Secret)

    申请地址:

    新浪

        申请入口  http://open.weibo.com/connect

        开发文档 http://open.weibo.com/wiki/%E7%BD%91%E7%AB%99%E6%8E%A5%E5%85%A5

    腾讯QQ

       申请入口:http://connect.qq.com/

       开发文档  http://wiki.connect.qq.com/

    微信 

        申请入口https://open.weixin.qq.com/

        开发文档 https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&verify=1&lang=zh_CN

    以QQ为例:

    从以上文档中可以得知,获得openId以及QQ获得用户信息需要三步,第一步,封装请求链接,然后服务的返回浏览器302跳转至微信或QQ等用户授权窗口

     public ActionResult QQLogin(string returnUrl)
            {
                AuthenticationScope scope=new AuthenticationScope(){
                    State=Guid.NewGuid().ToString().Replace("-", ""),
                    Scope="get_user_info"
                };
                if (!string.IsNullOrEmpty(returnUrl))
                {
                    Session["returnUrl"] = returnUrl;
                }
                Session["requeststate"] = scope.State;
                string url=_tencentHandler.GetAuthorizationUrl(scope);
                return Redirect(url);
            }
     public override string GetAuthorizationUrl(AuthenticationScope scope)
            {
                string url = string.Empty;
                if (string.IsNullOrEmpty(scope.Scope))
                {
                    url = string.Format("{0}/oauth2.0/authorize?response_type=code&client_id={1}&redirect_uri={2}&state={3}", _options.AuthorizeUrl, _options.AppId, string.Concat(_options.Host, _options.Callback), scope.State);
                }
                else
                {
                    url = string.Format("{0}/oauth2.0/authorize?response_type=code&client_id={1}&redirect_uri={2}&state={3}&scope={4}", _options.AuthorizeUrl, _options.AppId, Uri.EscapeDataString(string.Concat(_options.Host, _options.Callback)), scope.State, scope.Scope);
                }
                return url;
            }

     成功后浏览器会跳转至

    redirect_uri传递的链接窗口即QQOAuthController下面的CallBack

    public ActionResult CallBack()
    {
    var verifier = Request.Params["code"];
    string state = Session["requeststate"].ToString();
    QQAuthenticationTicket ticket = new QQAuthenticationTicket()
    {
    Code=verifier,
    Tag = "Tencent.QQ"
    };
    ticket = _tencentHandler.PreAuthorization(ticket);
    ticket = _tencentHandler.AuthenticateCore(ticket);
    UserClaim userClaim = getUserClaimByOpenIdOrUnionId(ticket.OpenId, "", ticket.Tag);
    if (userClaim != null)
    {
    FormsAuthentication.SetAuthCookie(userClaim.User.UserName, true);
    if (Session["returnUrl"] != null && string.IsNullOrEmpty(Session["returnUrl"].ToString()))
    {
    return Redirect(Session["returnUrl"].ToString());
    }
    return RedirectToAction("Index", "Home");
    }
    SocialUser user = _tencentHandler.GetUserInfo(ticket);
    Session["social.current"] = user;
    return RedirectToAction("social", "members");
    }

    这方法的主要作用是依据返回的code,与Authorization Server即(QQ或者微博)进行授权认证,获取token,依据token获取openId以及微信的unionId等张华信息

     public override QQAuthenticationTicket PreAuthorization(QQAuthenticationTicket ticket)
            {
                string tokenEndpoint = string.Concat(_options.AuthorizeUrl, "/oauth2.0/token?grant_type=authorization_code&client_id={0}&client_secret={1}&code={2}&redirect_uri={3}");
                var url = string.Format(
                         tokenEndpoint,
                         Uri.EscapeDataString(_options.AppId),
                         Uri.EscapeDataString(_options.AppSecret),
                         Uri.EscapeDataString(ticket.Code), Uri.EscapeDataString(string.Concat(_options.Host, _options.Callback)));
                string tokenResponse = _httpClient.GetStringAsync(url).Result.ToString();
                if (tokenResponse.IndexOf('&') > 0)
                {
                    var parameters = tokenResponse.Split('&');
                    foreach (var parameter in parameters)
                    {
                        var accessTokens = parameter.Split('=');
                        if (accessTokens[0] == "access_token")
                        {
                            ticket.AccessToken = accessTokens[1];
                        }
                        else if (accessTokens[0] == "refresh_token") 
                        {
                            ticket.RefreshToken = accessTokens[1];
                        }
                        
                    }
                }
                return ticket;
            }
     public override QQAuthenticationTicket AuthenticateCore(QQAuthenticationTicket ticket)
            {
                string tokenEndpoint = string.Concat(_options.AuthorizeUrl, "/oauth2.0/me?access_token={0}");
                var url = string.Format(
                         tokenEndpoint,ticket.AccessToken);
                string tokenResponse = _httpClient.GetStringAsync(url).Result.ToString();
                string strJson = tokenResponse.Replace("callback(", "").Replace(");", "");
                var payload = JsonHelper.DeserializeObject<Callback>(strJson);
                ticket.OpenId=payload.openid;
                return ticket;
            }

    执行到这里时应该已经获取到openId以及token等相关信息,在自身服务器的用户管理中查找这个账户的绑定记录,如果有相关信息依据取出的相关信息进行用户授权写入cookie或者其他操作,如无调用Authorization Server的相关接口获取相关信息,用QQ的昵称头像,新浪微博貌似无法获取相关信息

    protected UserClaim getUserClaimByOpenIdOrUnionId(string openId, string unionId, string tag)
    {
    UserClaim claim = MembershipService.GetExtendSocialByOpenId(openId, tag);
    if (claim != null)
    {
    return claim;
    }
    return MembershipService.GetExtentSocialByUnionId(unionId, tag);
    }
    UserClaim为第三方账户的相关信息类
     public class UserClaim
        {
            /// <summary>
            /// 用户Id
            /// </summary>
            public int Id { get; set; }
            /// <summary>
            /// 用户Id
            /// </summary>
            public int UserId { get; set; }
            /// <summary>
            /// 用户认证类型
            /// </summary>
            public string Tag { get; set; }
            /// <summary>
            /// OpenId
            /// </summary>
            public string OpenId { get; set; }
            /// <summary>
            /// UnionId
            /// </summary>
            public string UnionId { get; set; }
            /// <summary>
            /// Token
            /// </summary>
            public string Token { get; set; }
            /// <summary>
            /// RefreshToken
            /// </summary>
            public string RefreshKey { get; set; }
            public virtual MembershipUser User { get; set; }
            
        }
    其他类似
    最后附上相关代码https://github.com/491134648/Farmer.Social

  • 相关阅读:
    v-show 和 v-if 对 v-chart的影响
    vue axios get请求参数为json对象 而非字符串形式
    把对象字符化 和 把字符对象化
    vue 给url 中文参数 添加编码解码
    Observer(__ob__: Observer) 对象添加属性
    vux 使用swiper 垂直滚动文字 报错[Intervention] Ignored...
    vue 点击当前的标签,获取当前标签的value值
    css 写一个向右的箭头
    Unable to preventDefault inside passive event listener due to target being treated as passive
    在微信浏览器中分享到朋友圈回调函数失败问题
  • 原文地址:https://www.cnblogs.com/shatanku/p/5502094.html
Copyright © 2011-2022 走看看