2010-07-21 27 views
9

के साथ django ऑब्जेक्ट्स बनाना I एक एपीआई के साथ काम कर रहा है जो मुझे अपने एपीआई के साथ लेनदेन के लिए अपारदर्शी "संदर्भ आईडी" उत्पन्न करना चाहता है, दूसरे शब्दों में, अद्वितीय संदर्भ जो उपयोगकर्ता अनुमान लगा सकते हैं या अनुमान लगा सकते हैं मार्ग। ('का अनुमान लगा' है उचित अंग्रेज़ी?)एक यादृच्छिक प्राथमिक कुंजी

यह है कि मैं क्या एक साथ वर्तमान में काट दिया गया है:

randomRef = randint(0, 99999999999999) 
while Transaction.objects.filter(transactionRef = randomRef).count(): 
    randomRef = randint(0, 99999999999999) 

Transaction.objects.create(user=user, transactionRef=randomRef, price=999) 

दुर्भाग्य से मेरी डेटाबेस पल में लेनदेन कमी रह गई है। मुझे एहसास हुआ है कि मेरी विधि विशेष रूप से थ्रेड सुरक्षित नहीं है (कहें कि मैं एक ही django कोड को कई mod_wsgi apache थ्रेड पर चला रहा हूं, वे सभी एक ही यादृच्छिक आरएफ उत्पन्न कर सकते हैं!)

क्या किसी को भी एक अच्छी चाल मिली है मेरे लिए यादृच्छिक प्राथमिक कुंजी उत्पन्न करें?

+2

हाँ, "अनुमान" ठीक है। – derekerdmann

उत्तर

16

क्यों न केवल सामान्य अनुक्रमिक आईडी को एन्क्रिप्ट करें? किसी ऐसे व्यक्ति को जो एन्क्रिप्शन कुंजी नहीं जानता है, आईडी केवल यादृच्छिक लगती है। आप एक रैपर लिख सकते हैं जो स्वचालित रूप से डीबी के रास्ते पर आईडी को डिक्रिप्ट करता है, और इसे डीबी से रास्ते पर एन्क्रिप्ट करता है।

+2

+1। आप भी इस तरह टकराव से बचें। –

+0

यह एक अच्छा विचार है, धन्यवाद। मैंने उपयोगकर्ता को मानक और मानक लेनदेन का संयोजन माना है। लेकिन, यह अद्वितीय होने की गारंटी नहीं है। क्या आप एन्क्रिप्ट करने के लिए एक अच्छा पायथन फ़ंक्शन सुझा सकते हैं? मैंने m2crypto को किसी अन्य पैकेज के लिए एक शर्त के रूप में स्थापित किया है, लेकिन वास्तव में इसका उपयोग अभी तक नहीं किया है। – rdrey

+0

क्षमा करें @AlexBliskovsky, मैं एक crypto n00b हूँ। क्या एन्क्रिप्टेड आउटपुट को एक छोटे पूर्णांक में निर्दिष्ट करने का कोई तरीका है? क्या यह अवधारणात्मक रूप से संभव है (यह सुनिश्चित करने के लिए कि कोई टक्कर नहीं है जब तक कि हम सुनिश्चित न करें कि सादे पाठ का डोमेन एन्क्रिप्टेड टेक्स्ट के डोमेन से छोटा है)? – xster

2

आप अपने डेटाबेस में लेनदेन आरफ कॉलम को अद्वितीय होने में सक्षम होना चाहिए। इस तरह, डेटाबेस एक ही लेनदेन के साथ लेनदेन को जोड़ने की अनुमति नहीं देगा Ref मान। एक संभावना randomly generate UUIDs है - यादृच्छिक यूयूआईडी टकराव की संभावना बेहद छोटी है।

2

यादृच्छिक पूर्णांक अद्वितीय नहीं हैं, और प्राथमिक कुंजी अद्वितीय होना चाहिए। कुंजी क्षेत्र एक चार (32) बनाने के लिए और इसके स्थान पर इस कोशिश:

from uuid import uuid4 as uuid 
randomRef = uuid().hex 

UUIDs विशिष्टता प्रदान बहुत अच्छे हैं।

+1

uuid4 द्वारा उत्पन्न दो यूयूआईडी अद्वितीय होने की गारंटी नहीं है, वहां केवल एक बहुत छोटा मौका (लेकिन गैर-शून्य) मौका है टक्कर। –

+0

धन्यवाद, मैंने पहले कभी यूयूआईडी के बारे में नहीं सुना है, वे मेरे वर्तमान रैंडिंट से काफी अच्छे लगते हैं। क्या मुझे यह सुनिश्चित करने के लिए अभी भी एक लूप के माध्यम से चीजें चलाना चाहिए कि यूयूआईडी अप्रयुक्त है? – rdrey

+0

यदि आप एक गैर-अद्वितीय कुंजी डालने का प्रयास करते हैं तो आपकी डेटाबेस परत अपवाद फेंक देगी। आप उस अपवाद को पकड़ सकते हैं और एक और यूयूआईडी बना सकते हैं। हालांकि जब मैंने इसे पोस्ट किया तो मैंने सोचा कि यह एक अच्छा जवाब था, अगर आप उन्हें लागू कर सकते हैं तो एलेक्स मार्टेलि और एम्बर दोनों ने बेहतर सुझाव दिए हैं। –

2

os.urandom(n) "क्रिप्टोग्राफिक उपयोग के लिए उपयुक्त एन यादृच्छिक बाइट्स की एक स्ट्रिंग लौटा सकता है"। बस सुनिश्चित करें कि n से ऊपर "अद्वितीय" कुंजी की संख्या का वर्ग है, जिसे आप पहचानना चाहते हैं, और आप टकराव का जोखिम जितना चाहें उतना कम कर सकते हैं। उदाहरण के लिए, यदि आपको लगता है कि आप शायद एक अरब लेनदेन (लगभग 2**30) के साथ समाप्त हो सकते हैं, n=8 पर्याप्त हो सकता है (लेकिन इसे सुरक्षित खेलें और कुछ हद तक n का उपयोग करें ;-)।

11

मैं एक सार इस सवाल के आधार पर निर्मित: https://gist.github.com/735861

एम्बर के सलाह के बाद, निजी कुंजी एन्क्रिप्टेड रहे हैं और डेस का उपयोग कर decrypted। एन्क्रिप्टेड कुंजी को आधार 36 में दर्शाया गया है, लेकिन जब तक प्रतिनिधित्व अद्वितीय नहीं है तब तक कोई अन्य चरित्र-आधारित प्रतिनिधित्व कार्य करेगा।

कोई भी मॉडल जिसे इस तरह के एन्क्रिप्टेड निजी कुंजी प्रतिनिधित्व की आवश्यकता होगी केवल कोड में दिखाए गए मॉडल और प्रबंधक से प्राप्त होना चाहिए।

यहाँ कोड का मांस है:

import struct 
from Crypto.Cipher import DES 
from django.db import models 

class EncryptedPKModelManager(models.Manager): 
    """Allows models to be identified based on their encrypted_pk value.""" 
    def get(self, *args, **kwargs): 
     encrypted_pk = kwargs.pop('encrypted_pk', None) 
     if encrypted_pk: 
      kwargs['pk'] = struct.unpack('<Q', self.model.encryption.decrypt(
       struct.pack('<Q', encrypted_pk) 
      ))[0] 
     return super(EncryptedPKModelManager, self).get(*args, **kwargs) 


class EncryptedPKModel(models.Model): 
    """Adds encrypted_pk property to children.""" 
    encryption = DES.new('8charkey') # Change this 8 character secret key 

    def _encrypted_pk(self): 
     return struct.unpack('<Q', self.encryption_obj.encrypt(
      str(struct.pack('<Q', self.pk)) 
     ))[0] 

    encrypted_pk = property(_encrypted_pk) 

    class Meta: 
     abstract = True 

एक Transaction वस्तु transaction कहा जाता है के लिए, transaction.encrypted_pk निजी कुंजी की एक एन्क्रिप्टेड प्रतिनिधित्व लौट आते हैं। Transaction.objects.get(encrypted_pk=some_value) एन्क्रिप्टेड निजी कुंजी प्रतिनिधित्व के आधार पर वस्तुओं की खोज करेगा।

यह ध्यान दिया जाना चाहिए कि यह कोड केवल निजी कुंजी के लिए काम करता है जिसे लंबे मूल्यों के रूप में सही ढंग से प्रदर्शित किया जा सकता है।

6

jbrendel ने एक कक्षा बनाई है जिसे आप आसानी से कस्टम आईडी प्राप्त करने के लिए प्राप्त कर सकते हैं।

https://github.com/jbrendel/django-randomprimary

+0

धन्यवाद, इस मुद्दे के साथ किसी और के लिए उपयोगी लगता है एक दिन! – rdrey

+1

यह django व्यवस्थापक के साथ काम नहीं करता प्रतीत होता है। यह मुझे रिक्त आईडी के साथ एक नया रिकॉर्ड सहेजने नहीं देगा क्योंकि यह एक आवश्यक फ़ील्ड है; अगर मैं एक आईडी परिभाषित करता हूं तो यादृच्छिक व्यक्ति उत्पन्न नहीं होता है। शायद यह केवल पिछले Django संस्करण में काम किया? – sherbang

+0

@ शेरबैंग इसे व्यवस्थापक के साथ काम करने के लिए, बस 'self.id:' भाग को संशोधित करें। यदि आप टिप्पणियों में बारीकी से देखते हैं, तो यह कहता है "# जाहिर है, हम पहले से ही हमारी आईडी जानते हैं, इसलिए हमें यहां कुछ खास करने की ज़रूरत नहीं है।" – shreks7

संबंधित मुद्दे