Сегодня расскажу как реализовывается работа приложения через OAuth, если пользователь передает просто логин и пароль.
Прежде всего потребуется класс OAuthUtility,
код которого есть в blogsapi.
На первом этапе мы проверяем производили ли мы аутентификацию пользователя ранее. Если нет, то обращаемся к твиттеру с логином и паролем, соответствующему нашему приложению (tokens.ConsumerKey,tokens.ConsumerSecret). Получаем назад ключ(response.Token), по которому мы можем построить запрос (OAuthUtility.BuildAuthorizationUri(response.Token)) на получение уникальных логина и пароля для пользователя нашего приложения. Назад возвращается страница, на которой пользователю предлагается ввести логин и пароль, но так как мы не хотим тревожить пользователя, то вводим их за него, незабывая извлечь со страницы authenticity_token. Если логин и пароль правильны, то нам возвращается уникальный PIN, который пользователь должен потом передать нашему приложению, в качестве единоразового пароля для получения постоянного пароля. Опять же парсим страницу вручную, чтобы не тревожить пользователя. И в завершение делаем запрос OAuthUtility.GetAccessToken, чтобы по разовому паролю наше приложение получило постоянный пароль. И сохраняем результат, чтобы больше не повторять этих действий.
В итоге наше приложение, чтобы сделать запрос от лица пользователя передает не логин и пароль, а аж 4 строчки, соответствующие 2м логинам и паролям от них.
Основная выгода - безопастность, и то, что эти строчки намного сложнее чем первоначальные логин и пароль пользователя, что гарантирует сложность их подбора. Но с другой стороны, они не имеют срока давности, поэтому зная их с легкостью можно выполнить действия от лица пользователя-приложения, в отличии от куков или сессий для авторизованных клиентов сайтов.
И общая схема, демонстрирующая весь ужас того, во что превращается простая ранее операция по выполнению действий при помощи логина и пароля:
Код самой функции "залогинивания" в твиттер.
Copy Source | Copy HTML- /// <summary>
- /// Простая попытка залогинится
- /// </summary>
- /// <param name="user"></param>
- /// <returns></returns>
- public override bool LogInto(UserAccaunt user)
- {
- try
- {
- OAuthTokens tokens = Configuration.GetTokens(user.username);
- if(String.IsNullOrEmpty(tokens.AccessToken))
- {
- //нет ключа, производим аутентификацию.
- //залогинимся в твиттер, получим куку и передадим ее дальше
- //0
- OAuthTokenResponse response = OAuthUtility.GetRequestToken(tokens.ConsumerKey,
- tokens.ConsumerSecret, String.Empty);
- //1
- HttpWebRequest myHttpWebRequest = (HttpWebRequest)
- WebRequest.Create(OAuthUtility.BuildAuthorizationUri(response.Token));
- myHttpWebRequest.Method = "GET";
- myHttpWebRequest.AllowAutoRedirect = false;
- // myHttpWebRequest.Headers.Add(HttpRequestHeader.Cookie, sCookie);
- HttpWebResponse myHttpWebResponse = (HttpWebResponse)myHttpWebRequest.GetResponse();
- string result = new StreamReader(myHttpWebResponse.GetResponseStream(), Encoding).ReadToEnd();
- sCookie = CookieParse(myHttpWebResponse.Headers[HttpResponseHeader.SetCookie]);
- myHttpWebResponse.Close();
- ///////////////////////
- Match m = new Regex(@"<input.*?name\W+authenticity_token.+?value\W+(\w+)\W", Regexoptions).Match(result);
- if (!m.Success) throw new Exception("Twitter authenticity_token problems!");
- myHttpWebRequest = MakeRequest("https://twitter.com/oauth/authorize");
- myHttpWebRequest.AllowAutoRedirect = false;
- myHttpWebRequest.Method = "POST";
- myHttpWebRequest.Referer = "http://twitter.com";
- string sQueryString =
- String.Format(
- "authenticity_token={0}&return_to_ssl=false&session%5Busername_or_email%5D={1}&session%5Bpassword%5D={2}&oauth_token={3}",
- m.Groups[1].Value,
- user.username,
- user.password,
- response.Token
- );
- //***************//
- byte[] byteArr = _encoding.GetBytes(sQueryString);
- myHttpWebRequest.ContentLength = byteArr.Length;
- myHttpWebRequest.GetRequestStream().Write(byteArr, 0, byteArr.Length);
- /////////////////////////
- myHttpWebResponse = (HttpWebResponse)myHttpWebRequest.GetResponse();
- sCookie = CookieParse(myHttpWebResponse.Headers[HttpResponseHeader.SetCookie]);
- result = new StreamReader(myHttpWebResponse.GetResponseStream(), Encoding).ReadToEnd();
- myHttpWebResponse.Close();
- //в теории отсюда нужно извлечь PIN для вставки
- m = new Regex(@"\Woauth_pin\W\D+(\d+)\D", Regexoptions).Match(result);
- if(!m.Success) throw new Exception("не удалось получить PIN!");
-
- response = OAuthUtility.GetAccessToken(tokens.ConsumerKey,
- tokens.ConsumerSecret, response.Token, m.Groups[1].Value);
- if (response != null)
- {
- //сохраняем токен, чтобы следующий раз не проходить всю цепочку.
- Configuration.SetTokens(user.username, response);
- }
- }
- LogedInAs = user;
- //Log("Twitter uses only OAuth2.0 authentification. Take care.");
- return true;
- }catch(Exception e1)
- {
- Log("Twitter OAuth "+e1.Message);
- return false;
- }
- }