python:2.7 Django:1.6 pip install redis
Wenn es um dedizierte Seiten geht, sind Login + Cookies bei Konten üblich. Manchmal möchten Sie jedoch für jeden Benutzer eine dedizierte URL eingeben, ohne sich anzumelden. Beispielsweise stellen wir Benutzern kein Konto zur Verfügung, da es üblich ist, zum Zeitpunkt der Erstregistrierung oder für aktuelle Smartphone-Spiele keine Anmelde-ID für E-Mails auszugeben.
Ich habe Angst vor Wörterbuchangriffen und Round-Robin-Angriffen, daher sollte es in Ordnung sein, wenn Sie Maßnahmen dagegen ergreifen
↓ Es ist wahrscheinlich schneller, den Code zu lesen
m.py
from uuid import uuid4
# 1.Ausstellung eines Einwegausweises
_uuid4 = str(uuid4())
print 'uuid4:', _uuid4
# 2.Daumen zur Überprüfung der Einweg-ID
uuid4_char_list = [ord(_char) for _char in _uuid4]
print 'uuid4_char_list:', uuid4_char_list
checksum = sum(uuid4_char_list)
print 'checksum:', checksum
# 3.URL-Ausgabe
print "http://hoge/page?token={}%20cs={}".format(_uuid4, checksum)
Ausführungsergebnis
> python m.py
uuid4: 6da25bb0-5d9c-4c1e-becc-51e3d5078fe4
uuid4_char_list: [54, 100, 97, 50, 53, 98, 98, 48, 45, 53, 100, 57, 99, 45, 52, 99, 49, 101, 45, 98, 101, 99, 99, 45, 53, 49, 101, 51, 100, 53, 48, 55, 56, 102, 101, 52]
checksum: 2606
http://hoge/page?token=6da25bb0-5d9c-4c1e-becc-51e3d5078fe4%20cs=2606
Bei der Überprüfung wird oft gesagt: "Ist es nicht gefährlich, als Prüfsumme analysiert zu werden? 』
Ich werde die Logik korrigieren, indem ich den Ort ertrage, an dem ich sagen möchte, dass es keinen seltsamen Hacker gibt, der unser entvölkertes System analysiert.
m.py
# -*- coding: utf-8 -*-
from __future__ import absolute_import, unicode_literals
import binascii
from uuid import uuid4
def checksum_base64_crc(_str):
"""
Invertiert die eingegebene Zeichenfolge, base64 codiert sie und gibt die crc32-Prüfsumme zurück
:param _str: str
:rtype : int
"""
#Umkehren
_str_r = _str[::-1]
#base64 codieren und crc32-Prüfsumme nehmen
return binascii.crc32(binascii.b2a_base64(_str_r))
# 1.Ausstellung eines Einwegausweises
_uuid4 = str(uuid4())
print 'uuid4:', _uuid4
# 2.Daumen zur Überprüfung der Einweg-ID
checksum = checksum_base64_crc(_uuid4)
print 'checksum:', checksum
# 3.URL-Ausgabe
print "http://hoge/page?token={}%20cs={}".format(_uuid4, checksum)
Ausführungsergebnis 2
>python m.py
uuid4: 6a1d87e0-0518-4aa0-a2ca-cced091f254b
checksum: -2147023629
http://hoge/page?token=6a1d87e0-0518-4aa0-a2ca-cced091f254b%20cs=-2147023629
Wenn zu viele Token ausgegeben werden, befürchte ich, dass die DB wächst. Es ist praktisch, Daten zu verwalten, die mit der Zeit verschwinden und keine Probleme mit Redis haben. Da die Daten mit der Zeit verschwinden, ist es später einfacher, wenn Sie die URL als Gegenmaßnahme gegen Anfragen im Protokoll beibehalten.
token_manager.py
# -*- coding: utf-8 -*-
from __future__ import absolute_import, unicode_literals
import binascii
from redis import Redis
from uuid import uuid4
def checksum_base64_crc(_str):
"""
Invertiert die eingegebene Zeichenfolge, base64 codiert sie und gibt die crc32-Prüfsumme zurück
:param _str: str
:rtype : int
"""
#Umkehren
_str_r = _str[::-1]
#base64 codieren und crc32-Prüfsumme nehmen
return binascii.crc32(binascii.b2a_base64(_str_r))
class IncorrectCheckSumError(Exception):
#Falsche Prüfsumme
pass
class TokenExpiredError(Exception):
#Token abgelaufen
pass
class TokenRepository(object):
"""
Das Token für die URL wird für einen bestimmten Zeitraum in Redis gespeichert und verwaltet
"""
EXPIRE_SEC = 3600
_KEY_BASE = "project_name/url/disposable/{}"
_cli = None
@property
def client(self):
"""
:rtype : Redis
"""
if self._cli is None:
self._cli = Redis(host='localhost', port=6379, db=10)
return self._cli
return self._cli
def get_key(self, token):
return self._KEY_BASE.format(str(token))
def set(self, token, value):
self.client.setex(self.get_key(token), value, self.EXPIRE_SEC)
return
def get(self, token):
"""
Gibt den zugehörigen Wert zurück
:param token:
:return: str
"""
value = self.client.get(self.get_key(token))
return str(value)
def exist(self, token):
"""
Überprüfen Sie, ob das Token im Repository vorhanden ist
:param token: unicode or string
:rtype: bool
"""
return bool(self.get(token))
class TokenManager(object):
@classmethod
def validate(cls, token, check_sum):
"""
Überprüfen Sie, ob das Token korrekt ist
:param token: unicode or str
:param check_sum: int
:rtype : bool
"""
token = str(token)
check_sum = int(check_sum)
#Überprüfen Sie, ob das Token mit der Prüfsumme korrekt ist
if checksum_base64_crc(token) != check_sum:
raise IncorrectCheckSumError
user_id = TokenRepository().get(token)
return bool(user_id)
@classmethod
def generate(cls, user_id):
"""
Token und Prüfsumme generieren
:param user_id:
:return: str, int
"""
#Generieren
token = str(uuid4())
#Token und Benutzer generiert_Speichern Sie die ID, indem Sie sie mit redis verknüpfen
TokenRepository().set(token, user_id)
return token, checksum_base64_crc(token)
@classmethod
def get_user_id_from_token(cls, token, check_sum):
"""
vom Token zum Benutzer_ID subtrahieren
:param token: str or unicode
:param check_sum: int
:rtype: str
"""
token = str(token)
if not cls.validate(token, check_sum):
raise TokenExpiredError
return TokenRepository().get(token)
# 1.Geben Sie eine Einweg-URL ein
url_base = "http://hogehoge.com/hoge?token={}&cs={}"
user_id = "1111222333"
_token, check_sum = TokenManager.generate(user_id)
url = url_base.format(_token, str(check_sum))
print url
# 2.Straßentest
assert TokenManager.get_user_id_from_token(_token, check_sum) == str(user_id)
Blick auf die Django Seite
# -*- coding: utf-8 -*-
from __future__ import absolute_import, unicode_literals
from django.http import HttpResponse
from django.views.generic import View
class ExclusiveView(View):
def get(self, request, *args, **kwargs):
# HTTP GET
token = request.GET.get("token", None)
check_sum = request.GET.get("cs", None)
#vom Token zum Benutzer_ID subtrahieren
error_message = None
message = None
try:
user_id = TokenManager.get_user_id_from_token(token, check_sum)
message = "Ihr Benutzer_ID ist{}ist".format(user_id)
except IncorrectCheckSumError:
error_message = "Unzulässiger Parameter"
except TokenExpiredError:
error_message = "Seite abgelaufen"
if error_message:
message = error_message
return HttpResponse(message,
mimetype='text/html; charset=UTF-8',
*args, **kwargs)
URL-Ausgabe
>python m.py
http://hogehoge.com/hoge?token=e359b20e-4c60-48da-9294-2ea9fcca0a6c&cs=-2066385284
■ Zugriff mit dem Browser Normales System
■ Zugriff mit dem Browser Anormales System
Recommended Posts