По принцип искам да запазя facebook ID на даден потребител, за да мога да получавам повече материали чрез Facebook. В идеалния случай искам решение, което нито използва javascript, нито бисквитка, само от страна на сървъра, но нямаше пример, само указания, така че събрах едно, което можем да обсъдим. Ето кода, който според мен работи, когато просто свържа потребител към диалоговия прозорец OAuth за моя уебсайт:
https://www.facebook.com/dialog/oauth?client_id=164355773607006&redirect_uri=http://www.kewlbusiness.com/oauth
След това го обработвам така, за да получа потребителските данни:
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"])
Така че с това мога да „вляза с Facebook“ за моя уебсайт без много разхвърлян javascript и бисквитки, които не искаме. Исках да активирам „влизане с Facebook“ за моя уебсайт. Трябва да работи без бисквитки и без javascript, но първото нещо, което се опитват да ви накарат да направите, е Javascript и бисквитки. Така че направих решение, което изглежда работи без бисквитки и без javascript, само OAuth 2.0: Можете ли да кажете нещо за моето „решение“? Практическата употреба, която търся, е активиране на проста функция кой FB потребител е направил какво на моя уебсайт и допускане на акаунти във Facebook за влизане по начина, който се стандартизира.
Просто си помислих, че трябва да работи без javascript SDK и без бисквитка и изглежда, че е така. Можете ли да кажете какви са моите предимства и недостатъци с това "решение"? Мисля, че е много по-добро от Javascript + Cookie, така че защо ни подвеждат да използваме javascript и бисквитка, когато минималният пример изглежда 100% сървърен?
Благодаря ти
Актуализация Изглежда правилно и се държи правилно и мога също да използвам потребителските данни с datator и да изобразя FB името си на първа страница без javascript и без бисквитка, само с 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,...
наличието на променливата fbuser за потребител на facebook и променливата потребител за потребител на google вече ми позволява да използвам facebook за моя уебсайт без бъгове, разхвърлян ненужен javascript + бисквитка.
Сега мога да изобразя и видя името си във facebook от моя уебсайт, което е страхотно, че най-накрая работи както трябва, независимо от javascript и не се нуждае от бисквитка.
Защо документацията препоръчва javascript + бисквитка, когато сървърният OAuth 2.0 е най-чистото решение? Съгласни ли сте, че това е най-доброто решение, тъй като не зависи от това дали използвате javascript или бисквитка?
Актуализация Възможен дублиран въпрос, когато сега видях, че други момчета не могат да излязат със сървърен код, те трябваше да прибегнат до Javascript SDK и изискване може да бъде, че трябва и трябва да работи без javascript така че направих малко отстраняване на грешки и открих, че "изчистването" на бисквитката и трябваше да променя името на бисквитката и въпреки че работи, бих искал вашия коментар и/или да тествам как според вас моят проект е решил това. Връзка за излизане като тази би трябвало да работи, но не става. Ако изляза два пъти, това работи и затова това е странен бъг, тъй като мога да го поправя, но все още не знам какво кара излизането да изисква второ посещение:
https://www.facebook.com/logout.php?next=http://www.myappengineproject.com&access_token=AAACVewZBArF4BACUDwnDap5OrQQ5dx0jsHEKPJkIJJ8GdXlYdni5K50xKw6s8BSIDZCpKBtVWF9maHMoJeF9ZCRRYM1zgZD
Изглежда, че не бях единственият, който се опитваше да избегне напълно javascript за решение с OAuth 2.0 сървър. Хората можеха да правят всичко, но не можеха да излязат:
Официалната документация за OAuth 2.0 с Facebook казва:
Можете да излезете от даден потребител от сесията му във Facebook, като го насочите към следния URL адрес:
https://www.facebook.com/logout.php?next=ВАШИЯ_URL&access_token=ACCESS_TOKEN
YOUR_URL трябва да бъде URL в домейна на вашия сайт, както е дефинирано в приложението за разработчици.
Исках да направя всичко от страна на сървъра и открих, че предложеният начин за свързване оставя бисквитката, така че връзката за излизане да не работи: https://www.facebook.com/logout.php?next=http://{{host}}&access_token={{current_user.access_token}}
Пренасочва, но не регистрира потребителя на моя уебсайт. Изглеждаше като Heisenbug, тъй като това се променяше за мен и нямаше много документация. Така или иначе изглежда, че успях да постигна функционалността с манипулатор, който манипулира бисквитката, така че на практика потребителят да излезе от системата:
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))
Така че съпоставянето на манипулатора към /auth/logout и настройването на това към връзката ефективно отписва потребителя от моя сайт (без да излиза от Facebook, надявам се и нетествано)
Някои други части от моя код обработват OAuth токените и търсенето на бисквитки за 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"]
Не направих loginhandler, тъй като login основно е кодът по-горе в моя root манипулатор на заявки. Моят потребителски клас е както следва:
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()
Подиграх заедно два основни доставчика И използвам променливата current_user за потребителя на facebook и променливата потребител за потребителя на google и променливата fbuser за потребител, който влиза и следователно няма съвпадение на бисквитка.
Кодът за търсене на бисквитки, който използвам, е следният и мисля, че го разбирам и че прави това, което искам:
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,
)
Трябваше да науча бисквитките, за да реша това и се надявам, че можете да коментирате повече. Извеждането на приветстващото съобщение изисква 3 променливи, една за потребител на Google, една за влязъл във Facebook потребител и променливата fbuser за случая, посочен в отговора:
JavaScript/бисквитките се използват, когато се опитвате да удостоверите нов потребител. Това не съществува във вашата база данни и вие нямате неговия accessToken.
Така че трябваше да използвам 3 променливи, може би можете да го направите само с 2 променливи?
{% 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 %}