Задать вопрос
Screatch
@Screatch
Ruby On Rails front-end developer

Как теперь авторизовать скрипт для работы с Vkontakte?

Есть задача, настроить поиск видео через Vkontakte API с сервера.



Авторизация до недавнего времени решалась не очень красиво, но работало.



application_id = '123456'<br>
    application_secret = 'secretapplicationkey'<br>
    code_url = 'http://oauth.vk.com/oauth/authorize?client_id=***&scope=video&redirect_uri=http://vasja.ru&response_type=code&_hash=0'<br>
    email = 'vasja@vasja.ru'<br>
    password = 'password'<br><br>
    # Settings<br>
    tokenExpire = Settings.vkontakte[:expires]<br>
    token = Settings.vkontakte[:access_token]<br><br>
    if Time.current >= tokenExpire<br>
      puts '=== Logging in to vk.com and getting cookies ==='<br>
      resp = Net::HTTP.post_form(URI.parse('http://vk.com/login.php'),<br>
                                 {'m' => '1', 'email' => email, 'pass' => password})<br>
      cookies = resp.response['set-cookie']<br>
      remixsid = cookies.split('remixsid=')[1].split(';')[0].split(',')[0]<br><br>
      puts '=== Logging in once again with the cookies ==='<br>
      # Подключаемся снова к http://vk.com<br>
      header = { "Cookie" => 'remixsid=' + remixsid }<br>
      data = open(code_url, header)<br><br>
      resultURL = data.base_uri.to_s<br><br>
      puts '== Parsing URL for code param ==='<br>
      codeParams = Rack::Utils.parse_query URI(resultURL).query<br>
      code = codeParams['code']<br>
    end<br><br>
    puts '=== Authorizing ==='<br>
    if Time.current >= tokenExpire<br>
      app = VK::Serverside.new app_id: application_id, app_secret: application_secret<br>
      app.authorize code<br>
      Settings.vkontakte = { :access_token => app.access_token, :expires => (Time.current + app.expires_in) }<br>
    else<br>
      app = VK::Serverside.new app_id: application_id, app_secret: application_secret, access_token: token<br>
    end<br>




Дальше уже работали с API как обычно используя обёртку над API vk-ruby

Но тут где-то в 20-ых числах сентября Vkontakte вдруг внезапно изменили порядок авторизацию, чем сломали огромное количество скриптов и сервисов разных направлений (Так например Loginza тоже оказалась под ударом). Об этом писали например на античате.



Теперь просто так

resp = Net::HTTP.post_form(URI.parse('http://vk.com/login.php'),<br>
                                 {'m' => '1', 'email' => email, 'pass' => password})<br>


уже не залогинится, он просто не авторизует и уже невозможно далее получить куку Remixsid.



Пробовали пойти легальным путём и воспользоватся github.com/7even/vkontakte_api (Сервер приложения)

Токен получаем, всё замечательно только вот при попытке воспользоваться video.search получаем ошибку:

User authorization failed: method is unavailable with server auth.



Собственно вопрос. Как теперь малой кровью можно авторизоваться в vkontakte с сервера и получить полноценный access_token для дальнейшего использования с API.



Заранее благодарю за любую помощь в решении этого вопроса :)
  • Вопрос задан
  • 18746 просмотров
Подписаться 15 Оценить Комментировать
Пригласить эксперта
Ответы на вопрос 5
Я просто заменил
http://vk.com/?act=login&email=$email&pass=$pass
на
http://login.vk.com/?act=login&email=$email&pass=$pass
и мой скрипт заработал.
Ответ написан
Комментировать
mamantoha
@mamantoha
Например, вот так:
# encoding: utf-8

require 'net/http'
require 'pp'

email = ARGV[0]
pass  = ARGV[1]

client_id     = '1915108'
scope         = 'friends'
redirect_uri  = 'http://oauth.vk.com/blank.html'
display       = 'wap'
response_type = 'token'

cookie = {}

puts "Открытие диалога авторизации"
# http://vk.com/developers.php?id=-1_37230422&s=1
url = "http://oauth.vk.com/oauth/authorize?client_id=#{client_id}&scope=#{scope}&redirect_uri=#{redirect_uri}&display=#{display}&response_type=#{response_type}&_hash=0"
puts url
uri = URI(url)

request = Net::HTTP::Get.new(uri.request_uri)

response = Net::HTTP.start(uri.host, uri.port){ |http| http.request(request) }

puts "Парсим ответ"
params = {
  _origin: response.body[/name="_origin" value="(.+?)"/, 1],
  ip_h:    response.body[/name="ip_h" value="(.+?)"/, 1],
  to:      response.body[/name="to" value="(.+?)"/, 1]
}

puts "Отправка формы"
url = /<form method="post" action="(.+?)"/.match(response.body)[1]
puts url
uri = URI(url)

params.merge!(email: email, pass: pass)

request = Net::HTTP::Post.new(uri.request_uri)
request.set_form_data(params)

response = Net::HTTP.start(uri.host, uri.port,
  :use_ssl => uri.scheme == 'https') {|http|
  http.request(request)
}

puts response['set-cookie']

cookie['l'] = /l=(.+?);/.match(response['set-cookie'])[1] rescue raise("Неверный логин или пароль")
cookie['p'] = /p=(.+?);/.match(response['set-cookie'])[1]

puts response.code
if response.code == '302'
  url = response['location']
end

puts "Разрешение доступа и получения куки"
uri = URI(url)
puts url

request = Net::HTTP::Get.new(uri.request_uri)

response = Net::HTTP.start(uri.host, uri.port,
  :use_ssl => uri.scheme == 'https') {|http|
  http.request(request)
}

cookie['remixsid'] = /remixsid=(.+?);/.match(response['set-cookie'])[1]
header = { "Cookie" => cookie.inject(''){ |memo, c| memo << "#{c[0]}=#{c[1]};" } }

# если пользователь этого еще не делал(response.code == '200'), надо дать приложению права
puts response.code
if response.code == '302'
  url = response['location']
end

puts "Установка куки"
uri = URI(url)
puts url

request = Net::HTTP::Get.new(uri.request_uri, header)

response = Net::HTTP.start(uri.host, uri.port,
  :use_ssl => uri.scheme == 'https') {|http|
  http.request(request)
}

puts "Получения access_token"
puts response.code
if response.code == '302'
  url = response['location']
  puts url
  access_token = /access_token=(.+?)&/.match(url)[1]
elsif response.code == '200'
  url = /<form method="POST" action="(.+?)"/.match(response.body)[1]
  puts url
  uri = URI(url)

  # Разрешаем доступ и отправляем форму
  request = Net::HTTP::Post.new(uri.request_uri, header)

  response = Net::HTTP.start(uri.host, uri.port,
    :use_ssl => uri.scheme == 'https') {|http|
    http.request(request)
  }

  puts response.code
  if response.code == '302'
    url = response['location']
    access_token = /access_token=(.+?)&/.match(url)[1]
  end
end

puts url
puts 'access_token=' + access_token
Ответ написан
Комментировать
masterrr
@masterrr
Ответ написан
Комментировать
7even
@7even
Получите подходящий токен один раз вручную (передав в scope параметр offline, чтобы токен был бесконечным), положите его в какой-нибудь yaml-конфиг на сервере и оттуда считывайте для обращения к API.
Ответ написан
@z0mb1ek
mamantoha правильно сделал, могу скинуть такой же код на java
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы