2011-09-01 9 views
16

This question has been asked here before। स्वीकार्य उत्तर शायद प्रश्नकर्ता और उत्तरदाता दोनों के लिए स्पष्ट था --- लेकिन मेरे लिए नहीं। मैंने अधिक सटीकता प्राप्त करने के लिए उपर्युक्त प्रश्न पर टिप्पणी की है, लेकिन कोई प्रतिक्रिया नहीं थी। I also approached the meta Q&A उनकी कब्र से प्रश्नों को वापस लाने के तरीके के बारे में सहायता के लिए, और कोई जवाब नहीं मिला।ओपनआईडी का उपयोग करने वाली वेबसाइट से पृष्ठों का अनुरोध कैसे करें?

जवाब यहाँ सवाल इसके बाद के संस्करण के लिए गया था:

ग्राहक के दृष्टिकोण से, एक OpenID लॉगिन बहुत किसी भी अन्य वेब-आधारित प्रवेश के समान है। ग्राहक के लिए एक परिभाषित प्रोटोकॉल नहीं है; यह एक सामान्य वेब सत्र है जो आपके ओपनआईडी प्रदाता के आधार पर भिन्न होता है। इस कारण से, मुझे संदेह है कि ऐसी कोई पुस्तकालय मौजूद है। आपको शायद इसे स्वयं कोड करना होगा।

मुझे पता है कि log onto a website with Python पहले से ही Urllib2 मॉड्यूल का उपयोग करके। लेकिन यह मेरे लिए यह अनुमान लगाने के लिए पर्याप्त नहीं है कि ओपनआईडी को प्रमाणित कैसे किया जाए।

मैं वास्तव में my StackOverflow inbox in json format प्राप्त करने के लिए, जिसके लिए मैं में लॉग इन करने की जरूरत है कोशिश कर रहा हूँ।

किसी एक संक्षिप्त परिचय या कि कैसे करना है पर एक अच्छी ट्यूटोरियल लिए एक लिंक प्रदान कर सकता है?

+0

के रूप में भी उपलब्ध है पीएस: मैंने जानबूझकर डुप्लिकेटिंग के संबंध में इस पोस्ट को पहले ही मॉडरेटर ध्यान के लिए ध्वजांकित किया था। – Benjamin

उत्तर

3

इस उत्तर का सार क्या दूसरों नीचे कहा है, विशेष रूप से RedBaron के अलावा एक विधि मैं Google खाते का प्रयोग StackOverflow इनबॉक्स में प्राप्त करने के लिए इस्तेमाल किया गया।

Firefox के छेड़छाड़ डाटा डेवलपर टूल का उपयोग करके और Stackoverflow पर लॉग ऑन, एक देख सकते हैं कि OpenID इस तरह से काम करता है:

  1. StackOverflow किसी दिए गए सेवा (यहाँ गूगल), पोस्ट में परिभाषित से प्रमाणीकरण का अनुरोध करता है डेटा;
  2. Google खाते प्रमाणीकरण के सबूत के रूप में पहले से मौजूद कुकी के लिए लेता है और जांचता है;
  3. यदि कोई कुकी नहीं मिलती है, तो Google प्रमाणीकरण का अनुरोध करता है और कुकी सेट करता है;
  4. कुकी सेट होने के बाद, StackOverflow उपयोगकर्ता के प्रमाणीकरण को स्वीकार करता है।

उपरोक्त प्रक्रिया को सारांशित करता है, जो वास्तव में अधिक जटिल है, क्योंकि कई रीडायरेक्ट और कुकी एक्सचेंज वास्तव में होते हैं।

क्योंकि एक ही प्रक्रिया को पुन: उत्पन्न करना प्रोग्रामेटिक रूप से किसी भी तरह से कठिन साबित हुआ (और यह मेरी निरक्षरता हो सकती है), विशेष रूप से सभी लोकेल विनिर्देशों के साथ कॉल करने के लिए यूआरएल का शिकार करने की कोशिश कर रहा है। मैंने पहले Google खाते पर लॉग ऑन करने का विकल्प चुना, अच्छी तरह से योग्य कुकी और फिर Stackoverflow पर लॉगिन करें, जो प्रमाणीकरण के लिए कुकी का उपयोग करेगा।

यह केवल निम्नलिखित पायथन मॉड्यूल का उपयोग करके किया जाता है: urllib, urllib2, cookielib और BeautifulSoup।

यहां (सरलीकृत) कोड है, यह सही नहीं है, लेकिन यह चाल है। विस्तारित संस्करण Github पर पाया जा सकता है।

#!/usr/bin/env python 

import urllib 
import urllib2 
import cookielib 
from BeautifulSoup import BeautifulSoup 
from getpass import getpass 

# Define URLs 
google_accounts_url = 'http://accounts.google.com' 
authentication_url = 'https://accounts.google.com/ServiceLoginAuth' 
stack_overflow_url = 'https://stackoverflow.com/users/authenticate' 
genuwine_url = 'https://stackoverflow.com/inbox/genuwine' 

# Build opener 
jar = cookielib.CookieJar() 
opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(jar)) 

def request_url(request):  
    ''' 
     Requests given URL. 
    '''  
    try: 
     response = opener.open(request) 
    except: 
     raise 
    return response 


def authenticate(username='', password=''):   
    ''' 
     Authenticates to Google Accounts using user-provided username and password, 
     then authenticates to StackOverflow. 
    ''' 
    # Build up headers 
    user_agent = 'Mozilla/5.0 (Ubuntu; X11; Linux i686; rv:8.0) Gecko/20100101 Firefox/8.0' 
    headers = {'User-Agent' : user_agent} 

    # Set Data to None 
    data = None 

    # Build up URL request with headers and data  
    request = urllib2.Request(google_accounts_url, data, headers) 
    response = request_url(request) 

    # Build up POST data for authentication 
    html = response.read() 
    dsh = BeautifulSoup(html).findAll(attrs={'name' : 'dsh'})[0].get('value').encode() 

    auto = response.headers.getheader('X-Auto-Login') 

    follow_up = urllib.unquote(urllib.unquote(auto)).split('continue=')[-1] 

    galx = jar._cookies['accounts.google.com']['/']['GALX'].value 

    values = {'continue' : follow_up, 
       'followup' : follow_up, 
       'dsh' : dsh, 
       'GALX' : galx, 
       'pstMsg' : 1, 
       'dnConn' : 'https://accounts.youtube.com', 
       'checkConnection' : '', 
       'checkedDomains' : '', 
       'timeStmp' : '', 
       'secTok' : '', 
       'Email' : username, 
       'Passwd' : password, 
       'signIn' : 'Sign in', 
       'PersistentCookie' : 'yes', 
       'rmShown' : 1} 

    data = urllib.urlencode(values) 

    # Build up URL for authentication 
    request = urllib2.Request(authentication_url, data, headers) 
    response = request_url(request) 

    # Check if logged in 
    if response.url != request._Request__original: 
     print '\n Logged in :)\n' 
    else: 
     print '\n Log in failed :(\n' 

    # Build OpenID Data  
    values = {'oauth_version' : '', 
       'oauth_server' : '', 
       'openid_username' : '', 
       'openid_identifier' : 'https://www.google.com/accounts/o8/id'} 

    data = urllib.urlencode(values) 

    # Build up URL for OpenID authetication 
    request = urllib2.Request(stack_overflow_url, data, headers) 
    response = request_url(request) 

    # Retrieve Genuwine 
    data = None 
    request = urllib2.Request(genuwine_url, data, headers) 
    response = request_url(request) 
    print response.read() 


if __name__ == '__main__': 
    username = raw_input('Enter your Gmail address: ') 
    password = getpass('Enter your password: ') 
    authenticate(username, password) 
+0

उह, क्यों HTMLParser और सुंदर सूप की तरह कुछ नहीं? – ThiefMaster

+0

@ थिफमास्टर: यदि आपको लगता है कि इस उद्देश्य के लिए HTMLSarser से सुंदर सूप बेहतर क्यों है, तो जवाब देने और संशोधित करने के लिए स्वतंत्र महसूस करें। – Benjamin

+0

दो सरल फ़ंक्शन कॉल बनाम सबक्लासिंग और 6 इंडेंटेशन स्तर – ThiefMaster

0

आपको किसी भी "लॉगिन" पृष्ठ पर कुकीज़ लागू करने की आवश्यकता है, पाइथन में आप cookiejar का उपयोग करते हैं। उदाहरण के लिए:

jar = cookielib.CookieJar() 
myopener = urllib2.build_opener(urllib2.HTTPCookieProcessor(jar)) 
#myopener now supports cookies. 
.... 
11

खैर मैं अपने आप को OpenID लेकिन आपकी पोस्ट (और इनाम !!) के बारे में ज्यादा पता नहीं है मुझे दिलचस्पी है।

This link ओपनआईडी प्रमाणीकरण अनुक्रम का सटीक प्रवाह बताता है (v1.0 के लिए कम से कम। नया संस्करण 2.0 है)। मैं जो कर सकता था, उससे कुछ कदम

  1. आप स्टैक ओवरफ्लो का लॉगिन पृष्ठ प्राप्त करते हैं जो ओपनआईडी (फॉर्म फ़ील्ड के रूप में) का उपयोग करके लॉगिन करने का विकल्प भी प्रदान करेगा।
  2. आप अपना ओपनआईडी भेजते हैं जो वास्तव में यूरी का एक रूप है और उपयोगकर्ता नाम/ईमेल नहीं है (यदि यह Google प्रोफाइल है तो यह आपकी प्रोफाइल आईडी है)
  3. स्टैक ओवरफ्लो तब आपके आईडी प्रदाता (इस मामले में Google) से कनेक्ट होगा और भेज देगा आप प्रवेश पृष्ठ और जहां बाद में पुनर्निर्देशित करना चाहिए करने के लिए एक और लिंक गूगल के लिए एक रीडायरेक्ट (मान लीजिए कि एक)
  4. आप प्रवेश कर सकते हैं करने के लिए गूगल पारंपरिक
  5. गूगल एक क्रिप्टोग्राफिक टोकन प्रदान करता है (अजगर से पोस्ट विधि का उपयोग कर) पेज प्रदान की (इस चरण के बारे में बिल्कुल यकीन नहीं है) आपके लॉगिन अनुरोध पर वापस
  6. आप नई आवश्यकता भेजते हैं इस टोकन के साथ पर।
  7. स्टैक ओवरफ्लो इस टोकन के साथ Google से संपर्क करेगा। यदि प्रामाणिकता स्थापित की गई है, तो यह एक सत्र आईडी
  8. बाद में STackOverflow के अनुरोधों में यह सत्र आईडी होना चाहिए
  9. लॉग आउट करने के बारे में कोई विचार नहीं !!

This link ओपनआईडी में विभिन्न प्रतिक्रियाओं और उनके क्या मतलब के बारे में बताता है। तो हो सकता है कि जब आपका कोड आपका ग्राहक हो तो यह आसान हो जाएगा।विकी पेज से

लिंक OpenID Explained

संपादित करें: का उपयोग करते हुए छेड़छाड़ डाटा Firefox के लिए पर जोड़ें, घटनाओं के निम्न क्रम का निर्माण किया जा सकता है।

  1. उपयोगकर्ता SO लॉगिन पृष्ठ का अनुरोध भेजता है। फॉर्म फ़ील्ड में ओपनआईडी दर्ज करने पर परिणामस्वरूप पृष्ठ एक Google पेज पर 302 रीडायरेक्ट भेजता है। रीडायरेक्ट URL में बहुत से ओपनआईडी पैरामीटर हैं (जो Google सर्वर के लिए हैं)। उनमें से एक वापसी_to = https://stackoverflow.com/users/authenticate/?s=some_value है।
  2. उपयोगकर्ता को Google लॉगिन पेज के साथ प्रस्तुत किया गया है। लॉगिन पर कुछ 302 हैं जो उपयोगकर्ता को Google दायरे में रीडायरेक्ट करते हैं।
  3. अंत में एक 302 प्राप्त होता है जो उपयोगकर्ता पुनर्निर्देश आपरेशन कुकी के का एक बहुत उत्पन्न हो रही हैं की इस पूरी श्रृंखला जो सही ढंग से
  4. संग्रहीत किया जाना चाहिए ताकि तक पहुँचने पर के दौरान की 'return_to' में पहले
  5. निर्दिष्ट पृष्ठ stackoverflow करने के लिए पेज (जिसे Google द्वारा 302'd किया गया था), एसओ सर्वर आपके अनुरोध को संसाधित करता है और प्रतिक्रिया हेडर में gauth और usr नामक कुकीज सेट करने के लिए "सेट-कुकी" फ़ील्ड भेजता है, जिसमें 302 से stackoverflow.com के साथ मूल्य के साथ एक सेट होता है। यह चरण आपके लॉगिन को पूरा करता है
  6. आपका क्लाइंट बस कुकी usr
  7. स्टोर करता है जब तक आप कुकी को किसी भी अनुरोध के साथ कुकी भेजने के लिए रीमेबर करते हैं।
  8. अब आप अनुरोध के साथ यूएसआर कुकी भेजने के लिए अपने इनबॉक्स का अनुरोध कर सकते हैं।

मेरा सुझाव है कि आप अपने पायथन क्लाइंट को कोडिंग शुरू करें और प्रतिक्रियाओं का ध्यानपूर्वक अध्ययन करें। ज्यादातर मामलों में यह न्यूनतम उपयोगकर्ता हस्तक्षेप के साथ 302 की श्रृंखला होगी (अपना Google उपयोगकर्ता नाम और पासवर्ड भरने और साइट पेज को अनुमति देने के अलावा)।

हालांकि इसे आसान बनाने के लिए, आप बस अपने ब्राउज़र का उपयोग करके SO में लॉगिन कर सकते हैं, सभी कुकी मानों की प्रतिलिपि बना सकते हैं और कुकी मूल्य सेट के साथ urllib2 का उपयोग करके अनुरोध कर सकते हैं।

बेशक यदि आप ब्राउज़र पर लॉग आउट करते हैं, तो आपको फिर से लॉगिन करना होगा और अपने पायथन प्रोग्राम में कुकी मान बदलना होगा।

+0

ठीक है, इसलिए मैं StackOverflow में लॉग इन करता हूं, जो मुझे उदाहरण के लॉगिन पेज पर रीडायरेक्ट करता है। Google, जो एक बार लॉग इन हो गया है, मुझे फिर से एसओ पर रीडायरेक्ट करता है। लेकिन एसओ में लॉग इन करने के लिए आप किस यूआरएल का अनुरोध करते हैं? आम तौर पर, आप एक यूआरएल का अनुरोध करते हैं, जो आपको 301 त्रुटि भेजता है, और उसके बाद आपको प्रमाणीकरण शीर्षलेख मिलते हैं, फिर आप उपयोगकर्ता नाम और पासवर्ड के साथ अनुरोध शीर्षलेख में योजना और दायरे जोड़ते हैं। अब अगर मैं http://stackoverflow.com या http://stackoverflow.com/users/login का अनुरोध करता हूं, तो मुझे पहले स्थान पर कोई भी 301 त्रुटि नहीं मिलती है। – Benjamin

+0

मुझे लगता है कि एक बार जब आप अपने Google खाते में लॉग इन करेंगे, तो उसे एसओ पर रीडायरेक्ट भेजना चाहिए (सफल प्रमाणीकरण के बाद और साइट पेज को अनुमति दें)। रीडायरेक्ट यूआरएल में एक पैरामीटर होना चाहिए जिसमें SO द्वारा Google द्वारा उत्पन्न क्रिप्टो टोकन शामिल हो। एक बार जब आप उस SO पृष्ठ पर रीडायरेक्ट कर लेते हैं, तो SO सर्वर टोकन को संसाधित करता है और यदि आपके सही सत्र के लिए कुकी सेट सही होती है। फिर आप एसओ में लॉग इन हैं। जब तक आप अनुरोध के साथ कुकी भेजते हैं तब तक आप SO से किसी भी पृष्ठ का अनुरोध कर सकते हैं और SO उस पृष्ठ को आपके पास वापस कर देगा। – RedBaron

+0

फ़ायरफ़ॉक्स का उपयोग करके मुझे पता चलता है कि Google खाते में लॉगिन करने के बाद निम्न पृष्ठ का उपयोग किया जाता है। http://stackauth.com/auth/global/write?authToken=SomeValue। अब Google इस साइट पर रीडायरेक्ट करता है या एसओ ने पहले के संचार में ब्राउज़र को इस लिंक पर रीडायरेक्ट करने के लिए कहा था जब एक बार पूरा हो गया है, जिसे मैं नहीं जानता। आपको शायद प्रत्येक अनुरोध की प्रतिक्रिया का विश्लेषण करना चाहिए और इसका विश्लेषण करना चाहिए ताकि आप लापता लिंक (301 प्रतिक्रिया की कमी) – RedBaron

0

मैंने एक साधारण स्क्रिप्ट बनाई है जो मोज़िला फ़ायरफ़ॉक्स कुकीज़ का उपयोग करके stackoverflow.com पर लॉग इन करता है। यह पूरी तरह से स्वचालित नहीं है, क्योंकि आपको मैन्युअल रूप से लॉगिन करने की आवश्यकता है, लेकिन यह सब मैं करने में कामयाब रहा हूं।

विज्ञान एफएफ के नवीनतम संस्करणों के लिए वास्तविक है (मैं 8.0.1 का उपयोग कर रहा हूं), लेकिन आपको नवीनतम स्क्लाइट डीएल प्राप्त करने की आवश्यकता है, क्योंकि डिफ़ॉल्ट जो कि अजगर 2.7 के साथ आता है डीबी नहीं खोल सकता है। आप इसे यहाँ प्राप्त कर सकते हैं: http://www.sqlite.org/sqlite-dll-win32-x86-3070900.zip

import urllib2 
import webbrowser 
import cookielib 
import os 
import sqlite3 
import re 
from time import sleep 

#login in Firefox. Must be default browser. In other cases log in manually 
webbrowser.open_new('http://stackoverflow.com/users/login') 

#wait for user to log in 
sleep(60) 

#Process profiles.ini to get path to cookies.sqlite 
profile = open(os.path.join(os.environ['APPDATA'],'Mozilla','Firefox','profiles.ini'), 'r').read() 

COOKIE_DB = os.path.join(os.environ['APPDATA'],'Mozilla','Firefox','Profiles',re.findall('Profiles/(.*)\n',profile)[0],'cookies.sqlite') 
CONTENTS = "host, path, isSecure, expiry, name, value" 

#extract cookies for specific host 
def get_cookies(host): 
    cj = cookielib.LWPCookieJar() 
    con = sqlite3.connect(COOKIE_DB) 
    cur = con.cursor() 
    sql = "SELECT {c} FROM moz_cookies WHERE host LIKE '%{h}%'".format(c=CONTENTS, h=host) 
    cur.execute(sql) 
    for item in cur.fetchall(): 
     c = cookielib.Cookie(0, item[4], item[5], 
      None, False, 
      item[0], item[0].startswith('.'), item[0].startswith('.'), 
      item[1], False, 
      item[2], 
      item[3], item[3]=="", 
      None, None, {}) 
     cj.set_cookie(c) 
    return cj 

host = 'stackoverflow' 

cj = get_cookies(host) 

opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cj)) 

response = opener.open('http://stackoverflow.com').read() 

# if username in response - Auth successful 
if 'Stanislav Golovanov' in response: 
    print 'Auth successful' 
+1

आप शायद इस कोड में त्रुटियों के बारे में जानते हैं, लेकिन मैं उनका उल्लेख करता हूं ताकि सभी जानते हों। 1. पोर्टेबल नहीं (केवल विंडोज़ पर काम करता है)। 2. अगर 1 से अधिक फ़ायरफ़ॉक्स प्रोफाइल है तो काम नहीं करता है 3. अगर उपयोगकर्ता 60 सेकंड के भीतर लॉग इन नहीं करता है तो काम नहीं करता है 4. 60 सेकेंड से तेज़ में लॉग इन होने पर भी प्रतीक्षा करना है 5. बेकार सर्वर-साइड – rds

5

मैं जानता हूँ कि यह पुरातत्व के करीब है, एक पोस्ट दो वर्ष है कि खुदाई, लेकिन मैं सिर्फ मान्य जवाब से कोड की एक नई उन्नत संस्करण लिखा था, इसलिए मैंने सोचा कि यह इसे यहाँ साझा करने के लिए शांत हो सकता है , क्योंकि इस प्रश्न/उत्तर को लागू करने के लिए मेरे लिए एक बड़ी मदद मिली है।

तो, यहाँ क्या अलग है:

  • यह है कि urllib2 से अधिक बढ़ा हुआ रूप है नई requests पुस्तकालय उपयोग करता है;
  • यह Google और stackexchange के ओपनिड प्रदाता का उपयोग करके प्रमाणीकरण का समर्थन करता है।
  • यह रास्ता छोटा और सरल पढ़ने के लिए, हालांकि यह कम प्रिंटआउट

यहाँ है है कोड:

#!/usr/bin/env python 

import sys 
import urllib 
import requests 
from BeautifulSoup import BeautifulSoup 

def get_google_auth_session(username, password): 
    session = requests.Session() 
    google_accounts_url = 'http://accounts.google.com' 
    authentication_url = 'https://accounts.google.com/ServiceLoginAuth' 
    stack_overflow_url = 'http://stackoverflow.com/users/authenticate' 

    r = session.get(google_accounts_url) 
    dsh = BeautifulSoup(r.text).findAll(attrs={'name' : 'dsh'})[0].get('value').encode() 
    auto = r.headers['X-Auto-Login'] 
    follow_up = urllib.unquote(urllib.unquote(auto)).split('continue=')[-1] 
    galx = r.cookies['GALX'] 

    payload = {'continue' : follow_up, 
       'followup' : follow_up, 
       'dsh' : dsh, 
       'GALX' : galx, 
       'pstMsg' : 1, 
       'dnConn' : 'https://accounts.youtube.com', 
       'checkConnection' : '', 
       'checkedDomains' : '', 
       'timeStmp' : '', 
       'secTok' : '', 
       'Email' : username, 
       'Passwd' : password, 
       'signIn' : 'Sign in', 
       'PersistentCookie' : 'yes', 
       'rmShown' : 1} 

    r = session.post(authentication_url, data=payload) 

    if r.url != authentication_url: # XXX 
     print "Logged in" 
    else: 
     print "login failed" 
     sys.exit(1) 

    payload = {'oauth_version' : '', 
       'oauth_server' : '', 
       'openid_username' : '', 
       'openid_identifier' : ''} 
    r = session.post(stack_overflow_url, data=payload) 
    return session 

def get_so_auth_session(email, password): 
    session = requests.Session() 
    r = session.get('http://stackoverflow.com/users/login') 
    fkey = BeautifulSoup(r.text).findAll(attrs={'name' : 'fkey'})[0]['value'] 

    payload = {'openid_identifier': 'https://openid.stackexchange.com', 
       'openid_username': '', 
       'oauth_version': '', 
       'oauth_server': '', 
       'fkey': fkey, 
       } 
    r = session.post('http://stackoverflow.com/users/authenticate', allow_redirects=True, data=payload) 
    fkey = BeautifulSoup(r.text).findAll(attrs={'name' : 'fkey'})[0]['value'] 
    session_name = BeautifulSoup(r.text).findAll(attrs={'name' : 'session'})[0]['value'] 

    payload = {'email': email, 
       'password': password, 
       'fkey': fkey, 
       'session': session_name} 

    r = session.post('https://openid.stackexchange.com/account/login/submit', data=payload) 
    # check if url changed for error detection 
    error = BeautifulSoup(r.text).findAll(attrs={'class' : 'error'}) 
    if len(error) != 0: 
     print "ERROR:", error[0].text 
     sys.exit(1) 
    return session 

if __name__ == "__main__": 
    prov = raw_input('Choose your openid provider [1 for StackOverflow, 2 for Google]: ') 
    name = raw_input('Enter your OpenID address: ') 
    pswd = getpass('Enter your password: ') 
    if '1' in prov: 
     so = get_so_auth_session(name, pswd) 
    elif '2' in prov: 
     so = get_google_auth_session(name, pswd) 
    else: 
     print "Error no openid provider given" 

    r = so.get('http://stackoverflow.com/inbox/genuwine') 
    print r.json() 

कोड एक github gist

HTH

+0

और मैंने एक कमांड लाइन टूल का उपयोग करके स्टैक ओवरफ्लो (और चैट) से कनेक्ट करने के लिए इसका उपयोग करके एक प्रोजेक्ट प्रकाशित किया है: http://github.com/guyzmo/pystackoverflow – zmo

संबंधित मुद्दे