|
Hi
I'm trying to implement OAuth using Google's implementation. First of all I create a few of the parameters using methods from OAuthBase.cs as follows:
string consumerKey = "anonymous";
string consumerSecret = "anonymous";
Uri uri = new Uri("https://www.google.com/accounts/OAuthGetRequestToken");
OAuthBase oAuth = new OAuthBase();
string nonce = oAuth.GenerateNonce();
string timeStamp = oAuth.GenerateTimeStamp();
string str = "https://www.google.com/accounts/OAuthGetRequestToken";
string str2 = "oauth_consumer_key=www.google.com&oauth_nonce=1932530&oauth_timestamp=1277400332&oauth_signature_method=HMAC-SHA1&oauth_version=1.0";
and the methods in the OAuthBase class:
public virtual string GenerateNonce()
{
return random.Next(123400, 9999999).ToString();
}
public virtual string GenerateTimeStamp()
{
TimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0);
string timeStamp = ts.TotalSeconds.ToString();
timeStamp = timeStamp.Substring(0, timeStamp.IndexOf("."));
return timeStamp;
}
Then I create the signature as follows:
string sig = oAuth.GenerateSignature(uri,
consumerKey, consumerSecret,
string.Empty, string.Empty,
"GET", timeStamp, nonce,
OAuthBase.SignatureTypes.HMACSHA1, out str, out str2 );
using this method from OAuthBase.cs:
public string GenerateSignature(Uri url, string consumerKey, string consumerSecret, string token, string tokenSecret, string httpMethod, string timeStamp, string nonce, SignatureTypes signatureType, out string normalizedUrl, out string normalizedRequestParameters)
{
normalizedUrl = null;
normalizedRequestParameters = null;
switch (signatureType)
{
case SignatureTypes.PLAINTEXT:
return HttpUtility.UrlEncode(string.Format("{0}&{1}", consumerSecret, tokenSecret));
case SignatureTypes.HMACSHA1:
string signatureBase = GenerateSignatureBase(url, consumerKey, token, tokenSecret, httpMethod, timeStamp, nonce, HMACSHA1SignatureType, out normalizedUrl, out normalizedRequestParameters);
HMACSHA1 hmacsha1 = new HMACSHA1();
hmacsha1.Key = Encoding.ASCII.GetBytes(string.Format("{0}&{1}", UrlEncode(consumerSecret), string.IsNullOrEmpty(tokenSecret) ? "" : UrlEncode(tokenSecret)));
return GenerateSignatureUsingHash(signatureBase, hmacsha1);
case SignatureTypes.RSASHA1:
throw new NotImplementedException();
default:
throw new ArgumentException("Unknown signature type", "signatureType");
}
}
Here is the GenerateSignatureBase method that gets called if the signature type equals HMACSHA1:
public string GenerateSignatureBase(Uri url, string consumerKey, string token, string tokenSecret, string httpMethod, string timeStamp, string nonce, string signatureType, out string normalizedUrl, out string normalizedRequestParameters) {
if (token == null) {
token = string.Empty;
}
if (tokenSecret == null) {
tokenSecret = string.Empty;
}
if (string.IsNullOrEmpty(consumerKey)) {
throw new ArgumentNullException("consumerKey");
}
if (string.IsNullOrEmpty(httpMethod)) {
throw new ArgumentNullException("httpMethod");
}
if (string.IsNullOrEmpty(signatureType)) {
throw new ArgumentNullException("signatureType");
}
normalizedUrl = null;
normalizedRequestParameters = null;
List<QueryParameter> parameters = GetQueryParameters(url.Query);
parameters.Add(new QueryParameter(OAuthVersionKey, OAuthVersion));
parameters.Add(new QueryParameter(OAuthNonceKey, nonce));
parameters.Add(new QueryParameter(OAuthTimestampKey, timeStamp));
parameters.Add(new QueryParameter(OAuthSignatureMethodKey, signatureType));
parameters.Add(new QueryParameter(OAuthConsumerKeyKey, consumerKey));
if (!string.IsNullOrEmpty(token)) {
parameters.Add(new QueryParameter(OAuthTokenKey, token));
}
parameters.Sort(new QueryParameterComparer());
normalizedUrl = string.Format("{0}://{1}", url.Scheme, url.Host);
if (!((url.Scheme == "http" && url.Port == 80) || (url.Scheme == "https" && url.Port == 443)))
{
normalizedUrl += ":" + url.Port;
}
normalizedUrl += url.AbsolutePath;
normalizedRequestParameters = NormalizeRequestParameters(parameters);
StringBuilder signatureBase = new StringBuilder();
signatureBase.AppendFormat("{0}&", httpMethod.ToUpper());
signatureBase.AppendFormat("{0}&", UrlEncode(normalizedUrl));
signatureBase.AppendFormat("{0}", UrlEncode(normalizedRequestParameters));
return signatureBase.ToString();
}
I then use the string builder to build the string that I will pass to the WebRequest as follows:
sig = HttpUtility.UrlEncode(sig);
StringBuilder sb = new StringBuilder(uri.ToString());
sb.AppendFormat("?oauth_consumer_key={0}&", consumerKey);
sb.AppendFormat("oauth_nonce={0}&", nonce);
sb.AppendFormat("oauth_timestamp={0}&", timeStamp);
sb.AppendFormat("oauth_signature_method={0}&", "HMAC-SHA1");
sb.AppendFormat("oauth_version={0}&", "1.0");
sb.AppendFormat("scope={0}&", "https://mail.google.com/mail/feed/atom");
sb.AppendFormat("oauth_signature={0}", sig);
I then create a WebRequest as follows and pass it the string:
string s = sb.ToString();
WebRequest w = WebRequest.Create(s);
..where 'string s' equals:
"https://www.google.com/accounts/OAuthGetRequestToken?oauth_consumer_key=anonymous&oauth_nonce=1221378&oauth_timestamp=1277825766&oauth_signature_method=HMAC-SHA1&oauth_version=1.0&scope=https://mail.google.com/mail/feed/atom&oauth_signature=n5HsVCqhujRoMzBKbRXa%2fC6hk2M%3d"
As soon as I call:
Stream objStream = w.GetResponse().GetResponseStream();
I get the following error: The remote server returned an error: (400) Bad Request.
So please could anyone tell me whether you can see what's wrong with my code or the string that I pass in.
|
|
|
|
|
If you copy and paste your generated url into the browser you should get a better error. I get:
Timestamp is too far from current time: 1277830114
|
|
|
|
|
I simply get a HTTP 400 error
|
|
|
|
|
Building on the excellent work by Ennis:
Etienne_123 wrote: TimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0);
I think the problem is one of those DateTimes is UTC, the other isn't.
[ADDED] Obviously a timespan is location-independent, it should be based on consistent data though [/ADDED]
|
|
|
|
|
Thanks for the reply. I tried using this:
DateTime dn = DateTime.Now;
DateTime dt = new DateTime(1970, 1, 1, 0, 0, 0, 0);
TimeSpan tss = dn.Subtract(dt);
string timespan = tss.TotalSeconds.ToString();
..still does not work. I'm doing it according to the specifications laid out here[^], which specifies that "Unless otherwise specified by the Service Provider, the timestamp is expressed in the number of seconds since January 1, 1970 00:00:00 GMT. The timestamp value MUST be a positive integer and MUST be equal or greater than the timestamp used in previous requests" . Could it be that Google requires a different timestamp?
|
|
|
|
|
From what I read on a little Google action, the format is OK; however the number may be off if your time isn't correct, e.g. due to summer time. One thing you could do is an experiment with a number of hours added/subtracted to see what gives (e.g. a for loop from -12 to +12, and TimeSpan.Add).
|
|
|
|
|
Still does not work. I tried every time setting. I uploaded a screenshot of a more detailed error message from VS here[^]
|
|
|
|
|
that contains a timestamp with a fractional part!
|
|
|
|
|
Yes I figured Then I reverted back to using this:
TimeSpan ts = DateTime.Now - new DateTime(1970, 1, 1, 0, 0, 0, 0);
string timeStamp = ts.TotalSeconds.ToString();
timeStamp = timeStamp.Substring(0, timeStamp.IndexOf("."));
..which removes the fractional part. Still no luck
|
|
|
|
|
|
Hi,
Can any one tell me the way to remove or delete the blank pages in a PDF document either using VB.Net or C#?
Thanks and Regards.
Kalyan
modified on Monday, July 5, 2010 7:12 AM
|
|
|
|
|
Hallo everybody,
I'm doing a sample of project which has a base class and other two or more subclasses of the base class.
The base class is directly connected to a database when the time is to run.
My questions are the following:
1. Is it necessary to embed the connection properties every-time in the subclasses?
2. The same question, but little confusing for me, here it goes:
cmd = new SqlCommand("sql statement", con);// found in one of the subclasses
Both cmd and con are instances of the class SqlCommand and SqlConnection respectively.
Why is con necessary here? I mean, once a connection is established in a base class and inherited in the subclasses,
then why?
If I might not be clear enough, please let me know.
Thank you
|
|
|
|
|
Yonathan1111 wrote: If I might not be clear enough, please let me know
Its not clear what your question is. post some code.
|
|
|
|
|
Thank you for your cooperation.
I don't have code sample, it is a design. I'm asking what logic should I follow?
Thanks
|
|
|
|
|
Yonathan1111 wrote: 1. Is it necessary to embed the connection properties every-time in the subclasses?
No, you can put the connection data anywhere, as long as the subclass can reach it at run time.
Yonathan1111 wrote: Why is con necessary here?
The SqlCommand object needs access to the SqlConnection object in order to know which database it is referring to. Your program could be accessing multiple databases.
It's time for a new signature.
|
|
|
|
|
Thank you
You gave me a hint.
Thanks
|
|
|
|
|
The Connection and Command should be embedded in a separate Data Access Layer class, which the others all use as necessary.
|
|
|
|
|
Thank you very much, that is what I want.
Thnks
|
|
|
|
|
Hello All,
I'm writing a dll that paints on the screen a gdi object.
How would you recomed me to perform automated UI test ?
I would like to draw the gdi object on the screen and compare it with a storded image.
I know I can caputre the screen and compare it to that image, but i was thinking maybe using the visual studio 2010 UI Automated test.
Thanks,
berlus
|
|
|
|
|
I don't personally believe in automated GUI tests.
|
|
|
|
|
Hello experts,
which advantages does one of these two methods
return (string.Format("Device #{0}", devNr));
return ("Device #" + devNr.ToString()); have over the other one?
They seem to produce identical results.
Ciao,
luker
|
|
|
|
|
They produce identical results. The first one is consider better because it uses less memory. The second version allocates memory for 3 strings ("Device #", result of devNr.ToString() and result of entire statement), which makes application consume more memory. The first one isn't (to my knowledge) creating such an overhead. If you need to use second form it's better to use StringBuilder class. And personally I consider first form more readable.
|
|
|
|
|
lukasz_nowakowski wrote: And personally I consider first form more readable.
I agree, String.Format is more readable, especially when you have a few more arguments.
|
|
|
|
|
I totally agree the 1st form is better, just on readability alone.
I'd question your point about the StringBuilder as a replacement for the second form, creating an instance of this type has some overhead, for small concatenations the string builder is worse than the code supplied in the OP, but it has become received wisdom that StringBuilder is more efficient.
I posted a link a while back http://www.yoda.arachsys.com/csharp/stringbuilder.html[^] to an archive of stuff John Skeet has written about c# amongst others. He has tested the received wisdom, and found it wanting, the section "So I Should Use StringBuilder Everywhere, Right?" is really the nub of the problem.
It's worth doing the test he suggests, for "small" concats the overhead of the StringBuilder outweighs the benefits (and dirties the code). For multiple concats (e.g. in a loop)
StringBuilder<code> is much more efficient.<br />
<div class="signature"><small>Dalek Dave: There are many words that some find offensive, Homosexuality, Alcoholism, Religion, Visual Basic, Manchester United, Butter.<br />
Pete o'Hanlon: If it wasn't insulting tools, I'd say you were dumber than a bag of spanners.</small></div>
|
|
|
|
|
Interestingly, the String.Format uses a StringBuilder...
|
|
|
|
|