8

Fondamentalmente voglio salvare l'ID di facebook di un determinato utente in modo da poter ricevere più materiale tramite Facebook. Idealmente, voglio una soluzione che non usi javascript né cookie, ma solo server, ma non c'erano esempi, solo indicazioni, quindi ne ho messo insieme uno di cui possiamo discutere. Ecco il codice che penso funziona quando ho appena collego un utente alla finestra di dialogo OAuth per il mio sito web:Come abilitare Facebook OAuth 2.0 completamente serveride?

https://www.facebook.com/dialog/oauth?client_id=164355773607006&redirect_uri=http://www.kewlbusiness.com/oauth

Poi ho gestirlo come questo per ottenere l'userdata:

class OAuthHandler(webapp2.RequestHandler): 
    def get(self): 
     args = dict(
     code = self.request.get('code'), 
     client_id = facebookconf.FACEBOOK_APP_ID, 
     client_secret = facebookconf.FACEBOOK_APP_SECRET, 
     redirect_uri = 'http://www.koolbusiness.com/oauth', 
    ) 
     file = urllib.urlopen("https://graph.facebook.com/oauth/access_token?" + urllib.urlencode(args)) 
     try: 
     token_response = file.read() 
     finally: 
     file.close() 
     access_token = cgi.parse_qs(token_response)["access_token"][-1] 
     graph = facebook.GraphAPI(access_token) 
     user = graph.get_object("me") 
     self.response.out.write(user["id"]) 
     self.response.out.write(user["name"]) 

Quindi, con questo posso "accedere con Facebook" per il mio sito web senza un sacco di javascript e cookie che non vogliamo. Volevo abilitare "accedi con Facebook" per il mio sito web. Dovrebbe funzionare senza cookie e senza javascript ma la prima cosa che cercano di farti fare è Javascript e cookies. Quindi ho creato una soluzione che sembra funzionare senza cookie e senza javascript, solo OAuth 2.0: puoi dire qualcosa sulla mia "soluzione"? L'uso pratico che sto cercando è l'attivazione della funzione semplice che l'utente FB ha fatto sul mio sito Web e l'ammissione degli account di Facebook per accedere come standardizzato.

Ho solo pensato che dovesse funzionare senza javascript SDK e senza cookie e sembra che sia il caso. Puoi dire quali sono i miei vantaggi e svantaggi con questa "soluzione"? Penso che sia molto meglio di Javascript + Cookie, quindi perché ci inducono a usare javascript e cookie quando l'esempio minimo sembra essere al 100% lato server?

Grazie

Aggiornamento Mi sembra giusto e si comporta a destra e posso anche usare l'userdata con la datatore e rendere il mio nome FB alla prima pagina senza javascript e nessun cookie, basta python:

class FBUser(db.Model): 
    id = db.StringProperty(required=True) 
    created = db.DateTimeProperty(auto_now_add=True) 
    updated = db.DateTimeProperty(auto_now=True) 
    name = db.StringProperty(required=True) 
    profile_url = db.StringProperty() 
    access_token = db.StringProperty(required=True) 
    name = db.StringProperty(required=True) 
    picture = db.StringProperty() 
    email = db.StringProperty() 
    friends = db.StringListProperty() 
    dirty = db.BooleanProperty() 

class I18NPage(I18NHandler): 

    def get(self): 
    if self.request.get('code'): 
      args = dict(
      code = self.request.get('code'), 
      client_id = facebookconf.FACEBOOK_APP_ID, 
      client_secret = facebookconf.FACEBOOK_APP_SECRET, 
      redirect_uri = 'http://www.kewlbusiness.com/', 
     ) 
     logging.debug("client_id"+str(args)) 
      file = urllib.urlopen("https://graph.facebook.com/oauth/access_token?" + urllib.urlencode(args)) 
      try: 
     logging.debug("reading file") 
      token_response = file.read() 
     logging.debug("read file"+str(token_response)) 
      finally: 
      file.close() 
      access_token = cgi.parse_qs(token_response)["access_token"][-1] 
      graph = main.GraphAPI(access_token) 
      user = graph.get_object("me") #write the access_token to the datastore 
     fbuser = main.FBUser.get_by_key_name(user["id"]) 
      logging.debug("fbuser "+str(fbuser)) 

      if not fbuser: 
      fbuser = main.FBUser(key_name=str(user["id"]), 
           id=str(user["id"]), 
           name=user["name"], 
           profile_url=user["link"], 
           access_token=access_token) 
      fbuser.put() 
      elif fbuser.access_token != access_token: 
      fbuser.access_token = access_token 
      fbuser.put() 
      self.render_jinja(
       'home_jinja',request=self.request,fbuser=user,... 

avendo la fbuser variabile per un utente di Facebook e l'utente variabile per un utente Google Now mi ammette di utilizzare Facebook per il mio sito web senza buggy disordinato javascript inutile + biscotto.

Ora è possibile eseguire il rendering e visualizzare il mio nome di Facebook dal mio sito Web, il che è fantastico che finalmente funziona come dovrebbe essere indipedente di javascript e non ha bisogno di un cookie.

Perché la documentazione consiglia javascript + cookie quando serveride OAuth 2.0 è la soluzione più pulita? Sei d'accordo che questa è la soluzione migliore dal momento che non dipende da se usi javascript o cookie?

Aggiornamento possibile domanda duplicata quando io ora ho visto che gli altri ragazzi non potevano uscire con il codice server, hanno dovuto ricorrere alla Javascript SDK e un requisito può essere che deve e dovrebbe funzionare con javascript così ho fatto un po 'di debug e ho scoperto che "cancellavo" il cookie e dovevo cambiare il nome del cookie e sebbene funzionasse vorrei il tuo commento e/o testare come pensi che il mio progetto abbia risolto questo problema. Un link di logout come questo dovrebbe funzionare ma non lo fa. Se accedo fuori due volte funziona e questo è il motivo per cui questo è uno strano bug da quando ho potuto risolvere il problema, ma io ancora non so ciò che rende il logout richiedono un secondo colpo:

https://www.facebook.com/logout.php?next=http://www.myappengineproject.com&access_token=AAACVewZBArF4BACUDwnDap5OrQQ5dx0jsHEKPJkIJJ8GdXlYdni5K50xKw6s8BSIDZCpKBtVWF9maHMoJeF9ZCRRYM1zgZD

Sembra che io non ero l'unico che cerca di evitare del tutto javascript per una soluzione con server OAuth 2.0.La gente potrebbe fare tutto, ma non hanno potuto effettuare il logout:

Facebook Oauth Logout

La documentazione ufficiale per OAuth 2.0 con Facebook dice:

È possibile accedere a un utente fuori della loro sessione di Facebook indirizzandoli a il seguente URL:

https://www.facebook.com/logout.php?next=YOUR_URL&access_token=ACCESS_TOKEN

YOUR_URL deve essere un URL nel tuo sito doma in, come definito nell'app dello sviluppatore .

ho voluto fare tutto ciò che lato server e ho trovato che il modo suggerito di collegamento lascia il cookie in modo che il link di logout non funziona: https://www.facebook.com/logout.php?next=http://{{host}}&access_token={{current_user.access_token}} Non reindirizzare ma non registra l'utente di nostra il mio sito web. Sembrava un Heisenbug poiché questo mi stava cambiando e non c'era molta documentazione. Ho comunque sembrava di essere in grado di ottenere la funzionalità con un gestore che manipola il cookie in modo che a tutti gli effetti l'utente è disconnesso:

class LogoutHandler(webapp2.RequestHandler): 
    def get(self): 
     self.set_cookie("fbsr_" + facebookconf.FACEBOOK_APP_ID, None, expires=time.time() - 86400) 
     self.redirect("/") 
    def set_cookie(self, name, value, expires=None): 

     if value is None: 
      value = 'deleted' 
      expires = datetime.timedelta(minutes=-50000) 
     jar = Cookie.SimpleCookie() 
     jar[name] = value 
     jar[name]['path'] = '/' 
     if expires: 
      if isinstance(expires, datetime.timedelta): 
       expires = datetime.datetime.now() + expires 
      if isinstance(expires, datetime.datetime): 
       expires = expires.strftime('%a, %d %b %Y %H:%M:%S') 
      jar[name]['expires'] = expires 
     self.response.headers.add_header(*jar.output().split(': ', 1)) 

Quindi la mappatura del gestore per/auth/logout e l'impostazione di questa per il collegamento in modo efficace registra l'utente dal mio sito (senza effettuare il login l'utente di facebook, si spera e non testato)

Alcune altre parti del mio codice si sta occupando del token OAuth e le ricerche dei cookie per la comunicazione Oauth:

def get(self): 
    fbuser=None 
    profile = None 
    access_token = None 
    accessed_token = None 
    logout = False 
    if self.request.get('code'): 
     args = dict(
     code = self.request.get('code'), 
     client_id = facebookconf.FACEBOOK_APP_ID, 
     client_secret = facebookconf.FACEBOOK_APP_SECRET, 
     redirect_uri = 'http://self.get_host()/', 
    ) 
     file = urllib.urlopen("https://graph.facebook.com/oauth/access_token?" + urllib.urlencode(args)) 
     try: 
     token_response = file.read() 
     finally: 
     file.close() 
     access_token = cgi.parse_qs(token_response)["access_token"][-1] 
     graph = main.GraphAPI(access_token) 
     user = graph.get_object("me") #write the access_token to the datastore 
     fbuser = main.FBUser.get_by_key_name(user["id"]) 
     logging.debug("fbuser "+fbuser.name) 

     if not fbuser: 
     fbuser = main.FBUser(key_name=str(user["id"]), 
          id=str(user["id"]), 
          name=user["name"], 
          profile_url=user["link"], 
          access_token=access_token) 
     fbuser.put() 
     elif fbuser.access_token != access_token: 
     fbuser.access_token = access_token 
     fbuser.put() 

    current_user = main.get_user_from_cookie(self.request.cookies, facebookconf.FACEBOOK_APP_ID, facebookconf.FACEBOOK_APP_SECRET) 
    if current_user: 
     graph = main.GraphAPI(current_user["access_token"]) 
     profile = graph.get_object("me") 
     accessed_token = current_user["access_token"] 

Non ho fatto un loginha ndler poiché login è fondamentalmente il codice sopra al mio gestore di richieste di root. La mia classe utente è la seguente:

class FBUser(db.Model): 
    id = db.StringProperty(required=True) 
    created = db.DateTimeProperty(auto_now_add=True) 
    updated = db.DateTimeProperty(auto_now=True) 
    name = db.StringProperty(required=True) 
    profile_url = db.StringProperty() 
    access_token = db.StringProperty(required=True) 
    name = db.StringProperty(required=True) 
    picture = db.StringProperty() 
    email = db.StringProperty() 

ho preso in giro insieme due fornitori di base enter image description here e io uso il current_user variabile per l'utente di Facebook e l'utente variabile per l'utente di Google e la fbuser variabile per un utente che è l'accesso e quindi non ha alcuna corrispondenza di cookie.

Il codice cookie di ricerca che uso è il seguente e credo di aver capito e che fa quello che voglio:

def get_user_from_cookie(cookies, app_id, app_secret): 
    """Parses the cookie set by the official Facebook JavaScript SDK. 

    cookies should be a dictionary-like object mapping cookie names to 
    cookie values. 

    If the user is logged in via Facebook, we return a dictionary with the 
    keys "uid" and "access_token". The former is the user's Facebook ID, 
    and the latter can be used to make authenticated requests to the Graph API. 
    If the user is not logged in, we return None. 

    Download the official Facebook JavaScript SDK at 
    http://github.com/facebook/connect-js/. Read more about Facebook 
    authentication at http://developers.facebook.com/docs/authentication/. 
    """ 
    logging.debug('getting user by cookie') 
    cookie = cookies.get("fbsr_" + app_id, "") 
    if not cookie: 
     logging.debug('no cookie found') 
     return None 
    logging.debug('cookie found') 
    response = parse_signed_request(cookie, app_secret) 
    if not response: 
     logging.debug('returning none') 
     return None 

    args = dict(
     code = response['code'], 
     client_id = app_id, 
     client_secret = app_secret, 
     redirect_uri = '', 
    ) 

    file = urllib.urlopen("https://graph.facebook.com/oauth/access_token?" + urllib.urlencode(args)) 
    try: 
     token_response = file.read() 
    finally: 
     file.close() 

    access_token = cgi.parse_qs(token_response)["access_token"][-1] 
    logging.debug('returning cookie') 
    return dict(
     uid = response["user_id"], 
     access_token = access_token, 
    ) 

ho dovuto imparare i cookie per risolvere questo e spero che tu possa commentare più. Emissione il messaggio di benvenuto richiesto 3 variabili, una per google utente, uno per clienti registrati facebook e il fbuser variabile per il caso di cui la risposta:

JavaScript/I cookie vengono utilizzati quando si sta cercando di autenticare un nuovo utente . Non sono presenti nel tuo database e non hai il suo accesso allo .

Quindi ho dovuto usare 3 variabili, forse puoi farlo con solo 2 variabili?

{% if user or current_user or fbuser %} 
     <div id="user-ident"> 
      <span>{% trans %}Welcome,{% endtrans %} <b>{{ current_user.name }}{% if not current_user and user %}{{ user.nickname() }}{% endif %}{% if not current_user and not user and fbuser %}{{ fbuser.name }}{% endif %}</span> 
     </div> 
     {% endif %} 

risposta

1

JavaScript/I cookie vengono utilizzati quando si tenta di autenticare un nuovo utente. Non esistono nel tuo database e non hai il suo accesso.

Quando si accede a un utente, è possibile accedere all'API di Facebook da qualsiasi lingua di programmazione, tramite HTTP, senza cookie/javascript se lo si desidera. C'è un client python, ad esempio: http://github.com/pythonforfacebook/facebook-sdk (era https://github.com/facebook/python-sdk)

+0

Grazie per il collegamento. Questo esempio è stato buono poiché è quello che sto cercando per OAuth e capisco che i cookie vengono utilizzati per la gestione delle sessioni. Penso che tutto funzioni tranne il mio logout e l'esempio fornisce un logouthandler molto conveniente visto che ho visto che altre persone hanno provato a farlo senza javascript e l'hanno trovato complicato –

+0

Il logouthandler funziona per me e quello era il componente finale che mi dava fastidio (disconnettersi). Il collegamento fornito da Facebook non cancella i cookie, così gli utenti rimangono loggati –

+1

Ultimamente al gioco. Ma questo collegamento sembra essere rotto. Quello aggiornato è: https://github.com/pythonforfacebook/facebook-sdk/ – damzam

1

Trovato questo. Sembra buono e si rivolge a più di solo fb. https://code.google.com/p/gae-simpleauth/

+1

Questo è quello che uso oggi e funziona anche con Foursquare. Sto pensando di provare a diventare un fornitore Oauth in modo che io possa aggiungere il mio sito allo stesso modo in cui aggiungo un altro fornitore. È stato svantaggioso creare molti modelli utente diversi, ma ora possiamo ancora utilizzare il modello utente di webapp2 che è un 'ndb.Expando' Suppongo che si possa sviluppare la semplicità in modo da poter aggiungere un provider senza nemmeno ridistribuire una nuova ersione di app, la mia idea è anche mantenere i dati del fornitore nel datastore in modo da poter aggiungere un provider da una sezione web di amministrazione. –

+0

Interessante. facci sapere come va –