grails Bcrypt एक ही इनपुट के लिए विभिन्न हैश उत्पन्न करता है?




(2)

एक बीक्रिप्ट हैश में salt शामिल salt और नतीजतन यह एल्गोरिदम एक ही इनपुट के लिए अलग हैंश देता है। रूबी में इसे प्रदर्शित करने की अनुमति दें।

> require 'bcrypt'
> p = BCrypt::Password.create "foobar"
=> "$2a$10$DopJPvHidYqWVKq.Sdcy5eTF82MvG1btPO.81NUtb/4XjiZa7ctQS"
> r = BCrypt::Password.create "foobar"
=> "$2a$10$FTHN0Dechb/IiQuyeEwxaOCSdBss1KcC5fBKDKsj85adOYTLOPQf6"
> p == "foobar"
=> true
> r == "foobar"
=> true

नतीजतन, बीसीआरपीटी का उपयोग आपके उदाहरण में प्रस्तुत तरीके से उपयोगकर्ताओं को खोजने के लिए नहीं किया जा सकता है। इसके बजाय एक वैकल्पिक अस्पष्ट क्षेत्र का उपयोग किया जाना चाहिए, उदाहरण के लिए उपयोगकर्ता का नाम या ई-मेल पता।

मैंने अभी अपनी नई grails परियोजना में एक पंजीकरण कार्यक्षमता जोड़ा। इसका परीक्षण करने के लिए, मैंने एक ईमेल और पासवर्ड देकर पंजीकृत किया। मैं डेटाबेस में सहेजने से पहले पासवर्ड हैशिंग के लिए bcrypt एल्गोरिदम का उपयोग कर रहा हूं।

हालांकि जब मैं पंजीकरण करते समय मैंने उसी ईमेल और पासवर्ड से लॉगिन करने का प्रयास किया, तो लॉगिन विफल रहता है। मैंने एप्लिकेशन को डीबग किया और पाया कि एक ही पासवर्ड के लिए जेनरेट किया गया हैश अलग है जब मैं डाटाबेस से पहले से ही एक हैश की तुलना करने की कोशिश करता हूं और इसलिए लॉगिन विफल हो रहा है (Login.findByEmailAndPassword (params.email, हैशपास्ड) LoginController में ग्रोवी रिटर्न शून्य )।

यहां मेरा डोमेन क्लास पंजीकरण.groovy है:

class Registration {

   transient springSecurityService

   String fullName
   String password
   String email

   static constraints = {
      fullName(blank:false)
      password(blank:false, password:true)
      email(blank:false, email:true, unique:true)
   }

   def beforeInsert = {
      encodePassword()
   }

   protected void encodePassword() {
      password = springSecurityService.encodePassword(password)
   }
}

यहां मेरा LoginController.groovy है:

class LoginController {

   /**
    * Dependency injection for the springSecurityService.
    */
   def springSecurityService

   def index = {
      if (springSecurityService.isLoggedIn()) {
         render(view: "../homepage")
      }
      else {
         render(view: "../index")
      }
   }

   /**
    * Show the login page.
    */
   def handleLogin = {

      if (springSecurityService.isLoggedIn()) {
         render(view: "../homepage")
         return
      }

      def hashPassd = springSecurityService.encodePassword(params.password)
      // Find the username
      def user = Registration.findByEmailAndPassword(params.email,hashPassd)
      if (!user) {
         flash.message = "User not found for email: ${params.email}"
         render(view: "../index")
         return
      } else {
         session.user = user
         render(view: "../homepage")
      }
   }
}

यहां मेरे Config.groovy से एक स्निपेट है, जिसमें हैश पासवर्ड के लिए bcrypt एल्गोरिदम का उपयोग करने और कुंजी के राउंड की संख्या का उपयोग करने के लिए grails कह रहा है:

grails.plugins.springsecurity.password.algorithm = 'bcrypt'
grails.plugins.springsecurity.password.bcrypt.logrounds = 16

जनवरी सही है - डिजाइन द्वारा bcrypt प्रत्येक इनपुट स्ट्रिंग के लिए एक ही हैश उत्पन्न नहीं करता है। लेकिन यह जांचने का एक तरीका है कि एक हैश पासवर्ड वैध है, और यह संबंधित पासवर्ड एन्कोडर में शामिल है। तो अपने नियंत्रक ( def passwordEncoder ) में passwordEncoder एन्कोडर बीन के लिए एक निर्भरता इंजेक्शन जोड़ें और लुकअप को बदलें

def handleLogin = {

   if (springSecurityService.isLoggedIn()) {
      render(view: "../homepage")
      return
   }

   def user = Registration.findByEmail(params.email)
   if (user && !passwordEncoder.isPasswordValid(user.password, params.password, null)) {
      user = null
   }

   if (!user) {
      flash.message = "User not found for email: ${params.email}"
      render(view: "../index")
      return
   }

   session.user = user
   render(view: "../homepage")
}

ध्यान दें कि आप isPasswordValid कॉल के लिए पासवर्ड एन्कोड नहीं करते हैं - cleartext सबमिट पासवर्ड में पास करें।

इसके अलावा - पूरी तरह से असंबंधित - सत्र में उपयोगकर्ता को स्टोर करना एक बुरा विचार है। लेखक प्रिंसिपल आसानी से उपलब्ध है और यूजर आईडी को स्टोर करने के लिए उपयोगकर्ता को आवश्यक रूप से पुनः लोड करना आसान बनाता है (उदाहरण के लिए User.get(springSecurityService.principal.id) । डिस्कनेक्ट संभावित संभावित बड़े हाइबरनेट ऑब्जेक्ट्स को संग्रहीत करना देव मोड में बहुत अच्छा काम करता है जब आप हों केवल आपके सर्वर का उपयोगकर्ता, लेकिन स्मृति का एक महत्वपूर्ण अपशिष्ट हो सकता है और डिस्कनेक्ट होने वाली वस्तुओं के आसपास काम करने के लिए आपको मजबूर करता है (उदाहरण के लिए merge का उपयोग करना आदि)।