Comment décoder l'url base64 en python?
pour les applications FBML Facebook envoie un paramètre signed_request expliqué ici:
http://developers.facebook.com/docs/authentication/canvas
Ils ont donné la version de php de décodage de cette demande signée:
Comment faire la même chose en python?
j'ai essayé le module base64 mais je reçois une erreur de rembourrage incorrecte:
>>> base64.urlsafe_b64decode("eyJhbGdvcml0aG0iOiJITUFDLVNIQTI1NiIsImV4cGlyZXMiOjEyNzk3NDYwMDAsIm9hdXRoX3Rva2VuIjoiMjk1NjY2Njk1MDY0fDIuRXpwem5IRVhZWkJVZmhGQ2l4ZzYzUV9fLjM2MDAuMTI3OTc0NjAwMC0xMDAwMDA0ODMyNzI5MjN8LXJ6U1pnRVBJTktaYnJnX1VNUUNhRzlNdEY4LiIsInVzZXJfaWQiOiIxMDAwMDA0ODMyNzI5MjMifQ")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/base64.py", line 112, in urlsafe_b64decode
return b64decode(s, '-_')
File "/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/base64.py", line 76, in b64decode
raise TypeError(msg)
TypeError: Incorrect padding
6 réponses
apparemment, vous avez manqué les deux derniers caractères en copiant la chaîne originale encodée en base64. Suffixez la chaîne de caractères avec deux signes is-equal (=) et elle sera décodée correctement.
j'ai partagé un extrait de code pour l'analyse du paramètre signed_request dans une application canvas facebook basée sur python à http://sunilarora.org/parsing-signedrequest-parameter-in-python-bas:
import base64
import hashlib
import hmac
import simplejson as json
def base64_url_decode(inp):
padding_factor = (4 - len(inp) % 4) % 4
inp += "="*padding_factor
return base64.b64decode(unicode(inp).translate(dict(zip(map(ord, u'-_'), u'+/'))))
def parse_signed_request(signed_request, secret):
l = signed_request.split('.', 2)
encoded_sig = l[0]
payload = l[1]
sig = base64_url_decode(encoded_sig)
data = json.loads(base64_url_decode(payload))
if data.get('algorithm').upper() != 'HMAC-SHA256':
log.error('Unknown algorithm')
return None
else:
expected_sig = hmac.new(secret, msg=payload, digestmod=hashlib.sha256).digest()
if sig != expected_sig:
return None
else:
log.debug('valid signed request received..')
return data
Alternative à @dae.la solution d'eklen, vous pouvez ajouter ===
:
s = 'iEPX-SQWIR3p67lj_0zigSWTKHg'
base64.urlsafe_b64decode(s + '===')
cela fonctionne parce que Python se plaint seulement de l'absence de rembourrage, mais pas de rembourrage supplémentaire.
import base64
import simplejson as json
def parse_signed_request( signed_request ):
encoded_sig, payload = signed_request.split('.',2)
data = json.loads(base64.b64decode( payload.replace('-_', '+/') ))
return data
surprenant, mais la réponse actuellement acceptée n'est pas exactement correcte. Comme d'autres réponses l'indiquent, c'est quelque chose appelé encodage base64url, et cela fait partie de RFC7515.
En Gros, ils ont remplacé les caractères " + " et " / " par " - " et " _ "respectivement; et en plus, ils ont supprimé les caractères traînants"=", parce que vous pouvez toujours dire combien de caractères vous manquez, simplement en regardant la longueur de chaîne encodée.
voici un exemple de RFC7515 in C#:
static string base64urlencode(byte [] arg)
{
string s = Convert.ToBase64String(arg); // Regular base64 encoder
s = s.Split('=')[0]; // Remove any trailing '='s
s = s.Replace('+', '-'); // 62nd char of encoding
s = s.Replace('/', '_'); // 63rd char of encoding
return s;
}
static byte [] base64urldecode(string arg)
{
string s = arg;
s = s.Replace('-', '+'); // 62nd char of encoding
s = s.Replace('_', '/'); // 63rd char of encoding
switch (s.Length % 4) // Pad with trailing '='s
{
case 0: break; // No pad chars in this case
case 2: s += "=="; break; // Two pad chars
case 3: s += "="; break; // One pad char
default: throw new System.Exception(
"Illegal base64url string!");
}
return Convert.FromBase64String(s); // Standard base64 decoder
}