从 Twitter API 获取用户的电子邮件以进行外部登录验证 ASP.NET MVC C#
Get user's email from Twitter API for External Login Authentication ASP.NET MVC C#
我已经检查了几个相关问题来找到我的问题的答案,但都无济于事。这个问题 Can we get email ID from Twitter oauth API? 让我得到了 Twitter 支持以允许对我的应用程序进行以下许可:
使用这个doc as a guide and the marked answer's 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签名生成器工具生成授权header并使用fiddler向https://api.twitter.com/1.1/account/verify_credentials.json?include_email=true发出GET请求时,我只收到一次电子邮件,我必须重新生成我的应用程序在 Twitter 中输入密钥以再次获取它。
是否有关于如何生成有效签名并发出有效请求以通过 .Net TwitterAuthentication 检索 Twitter 用户电子邮件的文档?
在把我所有的头发都拔光后差点秃顶之后,我终于开始工作了。我发现 Signature 基本字符串与我的代码生成的略有不同。稍作调整后,我能够生成有效的签名基本字符串。
在 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 CA
"B13EC36903F8BF4701D498261A0802EF63642BC3" // DigiCert High Assurance EV Root CA
}),
CallbackPath = new PathString("/twitter/account/ExternalLoginCallback")
};
app.UseTwitterAuthentication(twitterOptions);
最后在我的控制器中,我刚刚打电话给我的助手 class 从 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
}
助手class方法:
这是我为了提出有效请求而调整的部分:
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 Create Twitter App
上创建一个应用
提供所有必要的信息,例如应用程序名称、描述、网站 URL (https://example.com will do for local development), and so on. For your callback url, provide the local url you are using. In my case, https://localhost:44318/signin-twitter and ensure that you tick "request email address from users" save and then regenerate the consumer API Keys under the "Keys and tokens" tab see image below:
完成 Twitter 管理后,
在 Visual Studio 中的解决方案中安装 nuget 包:
Install-Package Microsoft.AspNetCore.Authentication.Twitter
在 visual studio 中更新您的 .NetCore 应用程序启动 Class(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.
该过程已完成,您应该能够在验证后获得用户的电子邮件。有关详细信息,请查看 Twitter external sign-in setup with ASP.NET Core
您必须更改代码以在用户使用 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
这是一个简单干净的解决方案
我已经检查了几个相关问题来找到我的问题的答案,但都无济于事。这个问题 Can we get email ID from Twitter oauth API? 让我得到了 Twitter 支持以允许对我的应用程序进行以下许可:
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签名生成器工具生成授权header并使用fiddler向https://api.twitter.com/1.1/account/verify_credentials.json?include_email=true发出GET请求时,我只收到一次电子邮件,我必须重新生成我的应用程序在 Twitter 中输入密钥以再次获取它。
是否有关于如何生成有效签名并发出有效请求以通过 .Net TwitterAuthentication 检索 Twitter 用户电子邮件的文档?
在把我所有的头发都拔光后差点秃顶之后,我终于开始工作了。我发现 Signature 基本字符串与我的代码生成的略有不同。稍作调整后,我能够生成有效的签名基本字符串。
在 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 CA
"B13EC36903F8BF4701D498261A0802EF63642BC3" // DigiCert High Assurance EV Root CA
}),
CallbackPath = new PathString("/twitter/account/ExternalLoginCallback")
};
app.UseTwitterAuthentication(twitterOptions);
最后在我的控制器中,我刚刚打电话给我的助手 class 从 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
}
助手class方法:
这是我为了提出有效请求而调整的部分:
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 Create Twitter App
上创建一个应用提供所有必要的信息,例如应用程序名称、描述、网站 URL (https://example.com will do for local development), and so on. For your callback url, provide the local url you are using. In my case, https://localhost:44318/signin-twitter and ensure that you tick "request email address from users" save and then regenerate the consumer API Keys under the "Keys and tokens" tab see image below:
完成 Twitter 管理后, 在 Visual Studio 中的解决方案中安装 nuget 包:
Install-Package Microsoft.AspNetCore.Authentication.Twitter
在 visual studio 中更新您的 .NetCore 应用程序启动 Class(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.
该过程已完成,您应该能够在验证后获得用户的电子邮件。有关详细信息,请查看 Twitter external sign-in setup with ASP.NET Core
您必须更改代码以在用户使用 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
这是一个简单干净的解决方案