从 Twitter API 获取用户电子邮件以进行外部登录身份验证 ASP.NET MVC C#

问题描述 投票:0回答:3

我检查了几个相关问题以找到我的问题的答案,但都无济于事。这个问题 我们可以从 Twitter oauth API 获取电子邮件 ID 吗? 让我尽可能获得 Twitter 支持以允许我的应用程序获得以下权限: 使用此 doc 作为指南和标记答案的 code (稍微修改一下)

var resource_url = "https://api.twitter.com/1.1/account/verify_credentials.json";
var postBody = "include_email=true";//
resource_url += "?" + postBody;

生成签名并发出请求以从 Twitter 获取用户详细信息,结果是我的 MVC 应用程序中的 401 Unauthorized

但是,当我使用 twitter 签名生成器工具生成授权标头并使用 fiddler 向 https://api.twitter.com/1.1/account/verify_credentials.json?include_email=true 发出 GET 请求时,我只收到一次电子邮件,我必须在 Twitter 中重新生成我的应用程序密钥才能再次收到它。

是否有关于如何生成有效签名并发出有效请求以通过 .Net TwitterAuthentication 检索 Twitter 用户电子邮件的文档?

c# asp.net twitter twitter-oauth
3个回答
25
投票

在把我头上所有的头发都拔掉之后,我几乎要秃头了,我终于开始工作了。我发现签名基本字符串与我的代码生成的略有不同。经过一些调整,我能够生成有效的签名基本字符串。

Startup.cs 中,我添加了 access_token 和 access_secret 作为声明。我没有使用我的应用程序中找到的那个,因为用户在尝试登录或注册时需要调用一个新的:

var twitterOptions = new Microsoft.Owin.Security.Twitter.TwitterAuthenticationOptions()
{
   ConsumerKey = ConfigurationManager.AppSettings["consumer_key"],
   ConsumerSecret = ConfigurationManager.AppSettings["consumer_secret"],
   Provider = new Microsoft.Owin.Security.Twitter.TwitterAuthenticationProvider
   {
      OnAuthenticated = (context) =>
      {
         context.Identity.AddClaim(new System.Security.Claims.Claim("urn:twitter:access_token", context.AccessToken));
         context.Identity.AddClaim(new System.Security.Claims.Claim("urn:twitter:access_secret", context.AccessTokenSecret));
         return Task.FromResult(0);
      }
   },
   BackchannelCertificateValidator = new Microsoft.Owin.Security.CertificateSubjectKeyIdentifierValidator(new[]
   {
      "A5EF0B11CEC04103A34A659048B21CE0572D7D47", // VeriSign Class 3 Secure Server CA - G2
      "0D445C165344C1827E1D20AB25F40163D8BE79A5", // VeriSign Class 3 Secure Server CA - G3
      "7FD365A7C2DDECBBF03009F34339FA02AF333133", // VeriSign Class 3 Public Primary Certification Authority - G5
      "39A55D933676616E73A761DFA16A7E59CDE66FAD", // Symantec Class 3 Secure Server CA - G4
      "‎add53f6680fe66e383cbac3e60922e3b4c412bed", // Symantec Class 3 EV SSL CA - G3
      "4eb6d578499b1ccf5f581ead56be3d9b6744a5e5", // VeriSign Class 3 Primary CA - G5
      "5168FF90AF0207753CCCD9656462A212B859723B", // DigiCert SHA2 High Assurance Server C‎A 
      "B13EC36903F8BF4701D498261A0802EF63642BC3" // DigiCert High Assurance EV Root CA
    }),
    CallbackPath = new PathString("/twitter/account/ExternalLoginCallback")
};

 app.UseTwitterAuthentication(twitterOptions);

最后在我的控制器中,我刚刚调用我的帮助程序类以从 Twitter 获取姓名和电子邮件:

    if (loginInfo.Login.LoginProvider.ToLower() == "twitter")
    {
        string access_token = loginInfo.ExternalIdentity.Claims.Where(x => x.Type == "urn:twitter:access_token").Select(x => x.Value).FirstOrDefault();
        string access_secret = loginInfo.ExternalIdentity.Claims.Where(x => x.Type == "urn:twitter:access_secret").Select(x => x.Value).FirstOrDefault();
        TwitterDto response = MyHelper.TwitterLogin(access_token, access_secret, ConfigurationManager.AppSettings["consumer_key"], ConfigurationManager.AppSettings["consumer_secret"]);
       // by now response.email should possess the email value you need
    }

Helper类方法:

这是我为了提出有效请求而调整的部分:

baseString = string.Concat("GET&", Uri.EscapeDataString(resource_url) + "&" + Uri.EscapeDataString(request_query), "%26", Uri.EscapeDataString(baseString));

public static TwitterDto TwitterLogin(string oauth_token, string oauth_token_secret, string oauth_consumer_key, string oauth_consumer_secret)
        {
            // oauth implementation details
            var oauth_version = "1.0";
            var oauth_signature_method = "HMAC-SHA1";

            // unique request details
            var oauth_nonce = Convert.ToBase64String(
                new ASCIIEncoding().GetBytes(DateTime.Now.Ticks.ToString()));
            var timeSpan = DateTime.UtcNow
                - new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);
            var oauth_timestamp = Convert.ToInt64(timeSpan.TotalSeconds).ToString();

            var resource_url = "https://api.twitter.com/1.1/account/verify_credentials.json";
            var request_query = "include_email=true";
            // create oauth signature
            var baseFormat = "oauth_consumer_key={0}&oauth_nonce={1}&oauth_signature_method={2}" +
                            "&oauth_timestamp={3}&oauth_token={4}&oauth_version={5}";

            var baseString = string.Format(baseFormat,
                                        oauth_consumer_key,
                                        oauth_nonce,
                                        oauth_signature_method,
                                        oauth_timestamp,
                                        oauth_token,
                                        oauth_version
                                        );

            baseString = string.Concat("GET&", Uri.EscapeDataString(resource_url) + "&" + Uri.EscapeDataString(request_query), "%26", Uri.EscapeDataString(baseString));

            var compositeKey = string.Concat(Uri.EscapeDataString(oauth_consumer_secret),
                                    "&", Uri.EscapeDataString(oauth_token_secret));

            string oauth_signature;
            using (HMACSHA1 hasher = new HMACSHA1(ASCIIEncoding.ASCII.GetBytes(compositeKey)))
            {
                oauth_signature = Convert.ToBase64String(
                    hasher.ComputeHash(ASCIIEncoding.ASCII.GetBytes(baseString)));
            }

            // create the request header
            var headerFormat = "OAuth oauth_consumer_key=\"{0}\", oauth_nonce=\"{1}\", oauth_signature=\"{2}\", oauth_signature_method=\"{3}\", oauth_timestamp=\"{4}\", oauth_token=\"{5}\", oauth_version=\"{6}\"";

            var authHeader = string.Format(headerFormat,
                                    Uri.EscapeDataString(oauth_consumer_key),
                                    Uri.EscapeDataString(oauth_nonce),
                                    Uri.EscapeDataString(oauth_signature),
                                    Uri.EscapeDataString(oauth_signature_method),
                                    Uri.EscapeDataString(oauth_timestamp),
                                    Uri.EscapeDataString(oauth_token),
                                    Uri.EscapeDataString(oauth_version)
                            );


            // make the request

            ServicePointManager.Expect100Continue = false;
            resource_url += "?include_email=true";
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(resource_url);
            request.Headers.Add("Authorization", authHeader);
            request.Method = "GET";

            WebResponse response = request.GetResponse();
            return JsonConvert.DeserializeObject<TwitterDto>(new StreamReader(response.GetResponseStream()).ReadToEnd());
        }
    }

    public class TwitterDto
    {
        public string name { get; set; }
        public string email { get; set; }
    }

这就是获取 Twitter 用户电子邮件所需的全部内容。我希望它可以帮助那些为此苦苦挣扎的人。请注意,问题中提到的步骤也非常重要。

更新版本.netcore 3.1

与上面的解决方案相比,在.netcore中实现twitter API非常简单。首先,您需要在 Twitter 上创建一个应用程序 创建 Twitter 应用程序

提供所有必要的信息,例如应用程序名称、描述、网站URL(https://example.com适用于本地开发)等。对于您的回调 url,请提供您正在使用的本地 url。就我而言,https://localhost:44318/signin-twitter 并确保勾选“请求用户的电子邮件地址”保存,然后在“密钥和令牌”选项卡下重新生成消费者 API 密钥,请参见下图:

完成 Twitter 管理后, 在 Visual Studio 的解决方案中安装 nuget 包:

Install-Package Microsoft.AspNetCore.Authentication.Twitter

在 Visual Studio 中更新您的 .NetCore 应用程序启动类(ConfigureServices 方法),以使用以下代码初始化 Twitter 身份验证机制:

services.AddAuthentication().AddTwitter(options => 
        {
            options.ConsumerKey = twitterConsumerApiKey;
            options.ConsumerSecret = twitterConsumerSecretKey;
            options.RetrieveUserDetails = true;
        }); // twitterConsumerApiKey and twitterConsumerSecretkey can be found under the "Keys and tokens" tab of the Twitter App previously created. 

该过程已完成,您应该能够在身份验证后收到用户的电子邮件。有关更多信息,请查看使用 ASP.NET Core 进行 Twitter 外部登录设置


0
投票

用户使用 twitter 登录后,您必须更改代码以调用 GET account/verify_credentials 方法。将参数 include_email 设置为 true 很重要。当此项设置为 true 时,电子邮件将作为字符串在用户对象中返回。 我正在使用这个库https://www.nuget.org/packages/linqtotwitter 这样我就不必编写处理 twitter api 请求的代码

var twitterCtx = new TwitterContext(authTwitter);
var verifyResponse = await
    (from acct in twitterCtx.Account
    where (acct.Type == AccountType.VerifyCredentials) && (acct.IncludeEmail == true)
    select acct)
    .SingleOrDefaultAsync();

看看我是如何做到这一点的 http://www.bigbrainintelligence.com/Post/get-users-email-address-from-twitter-oauth-ap

这是一个简单干净的解决方案


0
投票

{METHOD}&{URL_WITHOUT_QUERY_PARAMS}&{OTHER_PARAMS}

创建签名时,GET 查询参数不能是

{URL_WITHOUT_QUERY_PARAMS}
的一部分,而是作为
{OTHER_PARAMS}
的一部分。请注意,
{OTHER_PARAMS}
必须按字母顺序排序。

https://oauth.net/core/1.0a/

附录 A.5.1。生成签名基字符串

要生成签名,首先需要生成签名基字符串。该请求包含以下参数(不包括 oauth_signature),这些参数被排序并连接成规范化字符串:

oauth_consumer_key: dpf43f3p2l4k3l03 oauth_令牌: nnch734d00sl2jdk oauth_signature_method: HMAC-SHA1 oauth_时间戳: 1191242096 oauth_nonce: kllo9940pd9333jh oauth_版本: 1.0 文件: 假期.jpg 尺寸: 原来的 以下输入用于生成签名基字符串:

1.)

获取

2.)

http://photos.example.net/photos

3.) file=vacation.jpg&oauth_consumer_key=dpf43f3p2l4k3l03&oauth_nonce=kllo9940pd9333jh&oauth_signature_method=HMAC-SHA1&oauth_timestamp=1191242096&oauth_token=nnch734d00sl2jdk&oauth _版本=1.0&大小=原始

签名基字符串是:

GET&http%3A%2F%2Fphotos.example.net%2Fphotos&file%3Dvacation.jpg%26oauth_consumer_key%3Ddpf43f3p2l4k3l03%26oauth_nonce%3Dkllo9940pd9333jh%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1191242096%26oauth_token%3Dnnch734d00sl2jdk%26oauth_version%3D1.0%26size%3Doriginal

© www.soinside.com 2019 - 2024. All rights reserved.