Rejestracja wspierana Facebookiem w Django
27 December 2010
Comments
Facebook niedawno wprowadził kolejny społecznościowy widget - formularz rejestracji wspierany danymi z Facebooka (Facebook registration tool). Jeżeli wchodzący na twoją stronę użytkownik ma konto na Facebooku i jest tam zalogowany to w formularzu rejestracji zobaczy swoje dane i wystarczy że kliknie "Zarejestruj się":

Przygotowania - aplikacja na Facebooku
- Na początek musimy stworzyć aplikację na Facebooku potrzebną do obsługi widżeta. W jej ustawieniach pod zakładką "Strona Aplikacji" musimy podać domenę, na której będziemy jej używać (domena naszego serwisu).
- Mając aplikację zapisujemy jej identyfikator oraz "App Secret" - możemy dodać to od razu do settingsów projektu Django.
Wstawiamy widżet na stronę
Widżet Facebook registration tool możemy wstawić poprzez ramkę lub XFBML. W przypadku ramki wystarczy wkleić coś takiego:<iframe src="http://www.facebook.com/plugins/registration.php?
client_id=ID_APLIKACJI_FB&
redirect_uri=http://www.twojadomena.com/url/odbiorczy/&
fields=name,birthday,gender,location,email"
scrolling="auto"
frameborder="no"
style="border:none"
allowTransparency="true"
width="100%"
height="310px">
</iframe>
Odbiór danych rejestracji
Facebook na podany adres URL odeśle wszystkie dane (jeżeli użytkownik zezwoli na to naszej aplikacji i będzie chciał się zarejestrować). W POST dostaniemy dane pod zmienną signed_request składającą się z podpisu i danych zakodowany w base64. Musimy rozbić łańcuch na podpis i dane (po kropce), rozkodować za pomocą base64 dane (w formacie JSON) a następnie sprawdzić czy podpis jest poprawny (generowany z wysłanych danych oraz "App Secret" naszej aplikacji). Po potwierdzeniu poprawności podpisu można wykorzystać dane takie jak email, login, czy ID użytkownika Facebooka, który się chce zarejestrować. Oto przykład widoku oraz funkcji obsługujące podpisane żądania Facebooka:from random import choice
import hashlib
import urllib2
import json
import base64
import hmac
def parse_signed_request(signed_request, app_secret):
"""Return dictionary with signed request data.
Code taken from https://github.com/facebook/python-sdk"""
try:
l = signed_request.split('.', 2)
encoded_sig = str(l[0])
payload = str(l[1])
except IndexError:
raise ValueError("'signed_request' malformed")
sig = base64.urlsafe_b64decode(encoded_sig + "=" * ((4 - len(encoded_sig) % 4) % 4))
data = base64.urlsafe_b64decode(payload + "=" * ((4 - len(payload) % 4) % 4))
data = json.loads(data)
if data.get('algorithm').upper() != 'HMAC-SHA256':
raise ValueError("'signed_request' is using an unknown algorithm")
else:
expected_sig = hmac.new(app_secret, msg=payload, digestmod=hashlib.sha256).digest()
if sig != expected_sig:
raise ValueError("'signed_request' signature mismatch")
else:
return data
def fb_registration(request):
"""
Register a user from Facebook-aided registration form
"""
if request.POST:
if 'signed_request' in request.POST:
# parse and check data
data = parse_signed_request(request.POST['signed_request'], settings.FACEBOOK_CONNECT_SECRET)
# lets try to check if user exists based on username or email
try:
check_user = User.objects.get(username=data['registration']['name'])
except:
pass
else:
return HttpResponseRedirect('/user/login/')
try:
check_user = User.objects.get(email=data['registration']['email'])
except:
pass
else:
return HttpResponseRedirect('/user/login/')
# user does not exist. We create an account
# in this example I assume that he will login via Facebook button or RPXnow
# so no password is needed for him - using random password to make Django happy
randompass = ''.join([choice('1234567890qwertyuiopasdfghjklzxcvbnm') for i in range(7)])
user = User.objects.create_user(data['registration']['name'], data['registration']['email'], randompass)
user.save()
user = authenticate(username=data['registration']['name'], password=randompass)
if user is not None:
# save in user profile his facebook id. In this case for RPXNow login widget
fbid = 'http://www.facebook.com/profile.php?id=%s' % data['user_id']
r = RPXAssociation(user=user, identifier=fbid)
r.save()
login(request, user)
return HttpResponseRedirect('/')
return render_to_response('userpanel/fb_registration.html', {}, context_instance=RequestContext(request, userpanelContext(request)))
RkBlog
Comment article