วิธีที่ปลอดภัยที่สุดในการตั้งค่าคุกกี้สำหรับฟีเจอร์จดจำฉัน [ซ้ำกัน]

ฉันสนใจที่จะเขียนโค้ดคุณลักษณะ remember me บนหน้าเข้าสู่ระบบที่จะบันทึกคุกกี้บนคอมพิวเตอร์ส่วนบุคคลเป็นระยะเวลานานเท่าใด ฉันรู้ว่ามีอันตรายในเรื่องนี้ ดังนั้นฉันจึงต้องการแน่ใจว่าฉันทำสิ่งนี้ด้วยวิธีที่ถูกต้อง

ฉันเคยได้ยินเกี่ยวกับคนที่สร้างลิงก์ระหว่างตารางฐานข้อมูลและคุกกี้เพื่อตรวจสอบ แต่ไม่แน่ใจว่าต้องทำอย่างไร หรือแนะนำหรือไม่ ฉันยังใหม่กับคุกกี้ ดังนั้นโปรดอธิบายวิธีที่ดีที่สุดเท่าที่จะเป็นไปได้ ฉันไม่มีตัวอย่างใดๆ เพราะอย่างที่ฉันพูดไป ฉันไม่เคยเขียนโค้ดนี้มาก่อนและต้องการให้แน่ใจว่าฉันทำมันด้วยวิธีที่ถูกต้อง และได้รับข้อมูลจากคนที่ทำมัน

ฉันไม่แน่ใจว่าคุกกี้ของ Facebook จะคงอยู่ตลอดไปหรือไม่ ฉันรู้แค่ว่าในคอมพิวเตอร์ของฉัน ฉันไม่เคยต้องเข้าสู่ระบบอีกเลย เว้นแต่ฉันจะลบประวัติของตัวเอง ผมอาจอยากทำแบบเดียวกับที่พวกเขาทำ

ขอบคุณล่วงหน้า!


person kdjernigan    schedule 16.03.2013    source แหล่งที่มา
comment
ไม่มีเวทย์มนตร์ใดที่จะจดจำคุกกี้ของฉันได้ ลองนึกภาพการสร้างรหัสผ่านสุ่มใหม่เมื่อคุณตั้งค่า เก็บไว้ในฐานข้อมูล และเมื่อใดก็ตามที่ผู้ใช้ส่งคุกกี้ ให้ใช้คุกกี้นั้นเพื่อเข้าสู่ระบบแทนชื่อผู้ใช้และรหัสผ่านจริง เมื่อหมดอายุ (คุกกี้ทุกตัวหมดอายุ บางครั้งหากไม่ได้ใช้งานเป็นเวลานาน บางครั้งหลังจากหนึ่งปี บางครั้งเมื่อผู้ใช้ออกจากระบบอย่างชัดเจน) ให้ลบออกจากฐานข้อมูล   -  person Dave    schedule 17.03.2013


คำตอบ (3)


ฉันยังไม่ได้เขียนโค้ดนี้ด้วยตัวเอง แต่ฉันจะแก้ไขปัญหาดังนี้:

1. สร้างตารางที่สามารถใช้เพื่อบังคับการตรวจสอบความถูกต้องเมื่อผู้ใช้แสดงคุกกี้เพื่อความคงอยู่:

create table RememberMe
(
   user_id    int(10)  NOT NULL,
   user_token char(10)  NOT NULL,
   token_salt int(6)   NOT NULL,
   time       int(10)  NOT NULL,
   PRIMARY KEY (user_id),
   CONSTRAINT nameYourConstraint 
              FOREIGN KEY (user_id) 
              REFERENCES userTableName (whatever_user_id_equals)
)

หากต้องการเติมข้อมูลในตารางนี้ ฉันจะเพิ่มโค้ดบางบรรทัดในการเข้าสู่ระบบ สำหรับตัวอย่างนี้ ฉันจะใช้รหัสเทียม

// userID variable has been sanitized already so
// check if user clicked remember me
// and if the user logged in successfully:
if ( rememberMe == checked && login() == true )
{
     // random number to serve as our key:
     randomNumber = random( 99, 999999  );

     // convert number to hexadecimal form:
     token = toHex( ( randomNumber**randomNumber ) );

     // encrypt our token using SHA1 and the randomNumber as salt
     key = encrypt( token, randomNumber, SHA1 );

     // get the number of seconds since unix epoch:
     // (this will be 10 digits long until approx 2030)
     timeNow = unix_time()

     // check to see if user is in table already:
     sql = "SELECT user_id FROM RememberMe
            WHERE user_id = 'userID'";

     // connect to database:
     db = new DBCon();
     
     result = db->query( sql );
     
         // number of rows will always be 1 if user is in table:
         if ( result->rows != 1 )
             exists = true;
         else 
             exists = false;
     
     result->free_memory();
     
         if ( exists == true )
         {
             sql = "UPDATE RememberMe SET
                    user_id    = 'userID'
                    user_token = 'token'
                    token_salt = 'randomNumber'
                    time       = 'timeNow'";
         }
         else
         {
             sql = "INSERT INTO RememberMe
                    VALUES( 'userID', 'token', 'randomNumber', 'timeNow' )";
         }
     
     result = db->query( sql );
     
         // the affected rows will always be 1 on success
         if ( result->affected_rows != 1 )
         {
            print( "A problem occurred.\nPlease log in again." );
            quit();
         }

     result->free_memory();

     // create a new cookie named cookiemonster and store the key in it:
     // (we're not actually storing a score or birthday, its a false flag)
     set_cookie( "CookieMonster", escape("score="+ userID +"birthday="+ key );
}

สิ่งที่โค้ดนี้ทำคือตรวจสอบว่าผู้ใช้ได้ตรวจสอบการจำฉันแล้วหรือไม่ และมันเติมตารางฐานข้อมูลด้วยคีย์ โทเค็น และเกลือสำหรับผู้ใช้ตลอดจนเวลา (เพื่อให้คุณสามารถบังคับใช้ข้อจำกัดเวลาในการจดจำฉัน คุณสมบัติ).

จากที่นี่ คุณสามารถเพิ่มโค้ดลงในเว็บไซต์ของคุณเพื่อตรวจสอบว่าคุกกี้ CookieMonster ได้รับการตั้งค่าไว้หรือไม่ และ หากเป็นเช่นนั้น คุณสามารถทำตามขั้นตอนเหล่านี้เพื่อบังคับใช้ความถูกต้องได้:

  1. แยกรหัสผู้ใช้และรหัสออกจากคุกกี้ที่แสดง

  2. ค้นหาฐานข้อมูลด้วย userID เพื่อดูว่า

       --> a) user has requested to be remembered
    
       --> b) check the time to see if they cookie is still valid
    
       --> c) extract the token and salt from database table record
    
  3. เรียกใช้โทเค็นและเกลือผ่านการเรียกใช้ฟังก์ชัน encrypt() และจับคู่กับคีย์ที่นำเสนอ

  4. หากทุกอย่างเรียบร้อยดี ให้สร้างเซสชันใหม่และเข้าสู่ระบบผู้ใช้

ตอนนี้ทุกครั้งที่ผู้ใช้มาที่ไซต์ของคุณ พวกเขาจะต้องเข้าสู่ระบบ และ ในกรณีที่คอมพิวเตอร์ของพวกเขาถูกบุกรุก ผู้โจมตีจะไม่สามารถเข้าถึงรหัสผ่านของพวกเขาได้

หมายเหตุด้านข้าง: คุณควรกำหนดให้ผู้ใช้ของคุณแสดงรหัสผ่านเสมอเมื่อเปลี่ยนรหัสผ่านหรืออีเมล วิธีนี้หากคุกกี้ของผู้ใช้ตกไปอยู่ในมือของผู้ไม่ประสงค์ดี ผู้โจมตีของคุณจะไม่สามารถขโมยบัญชีได้

person Charles Addis    schedule 16.03.2013
comment
ฉันชอบสิ่งนี้...ฉันสังเกตเห็นในสคริปต์การเข้าสู่ระบบของคุณ สิ่งเดียวที่ทำคืออัปเดตโทเค็นและรายละเอียดทั้งหมด..แต่ไม่ได้ตรวจสอบจริงๆ เพื่อดูว่ามีคุกกี้อยู่หรือไม่...ฉันสับสนเล็กน้อยเกี่ยวกับเรื่องนั้น . ไม่ควรทำเช่นนี้หลังจากตรวจสอบว่าโทเค็นและสิ่งที่ถูกต้องระหว่างตารางและคุกกี้แล้วอัปเดตรายละเอียดเป็นตัวเลขใหม่พร้อมเวลาใหม่หรือไม่ หรือมันทำอะไรที่ฉันไม่เห็น? - person kdjernigan; 17.03.2013
comment
ใช่ ขอโทษที ฉันรู้ว่ามันน่าสับสนเล็กน้อย ฉันแค่พยายามจะเข้าใจแนวคิดนี้ ฉันพูดไปที่ไหนสักแห่งในนั้น (ฉันคิดว่า!) ว่าจำเป็นต้องเพิ่มโค้ดบางตัวเพื่อตรวจสอบว่าคุกกี้ได้รับการตั้งค่าหรือไม่ นี่คือโค้ดหลอกทั้งหมดเพื่อให้สามารถย้ายเป็นภาษาใดก็ได้ อย่างไรก็ตาม ฟังก์ชั่นส่วนใหญ่นั้นอิงจากฟังก์ชั่นในไลบรารี PHP - person Charles Addis; 17.03.2013
comment
ทุกหน้าในเว็บไซต์ของคุณควรตรวจสอบคุกกี้ ไม่ใช่เพียงหน้าเดียว (อย่างน้อยหน้าใดก็ได้ที่อาจเป็นจุดเริ่มต้น) หากมีการตั้งค่าคุกกี้ ให้ใช้ ID ผู้ใช้และดึงข้อมูลจากฐานข้อมูล หากไม่เป็นเช่นนั้น รหัสนี้จะถูกเรียกใช้เมื่อผู้ใช้เข้าสู่ระบบ สมมติว่าคุณต้องการให้ฟังก์ชัน 'จดจำฉัน' จดจำผู้คนเป็นเวลาสองสัปดาห์ [ ซึ่งระบุไว้ในโค้ดของคุณโดยใช้เวลาปัจจุบันเป็นวินาทีแล้วลบออกจากเวลา ว่าคุกกี้ถูกตั้งค่าไว้ เมื่อคุณลบเสร็จแล้ว คุณสามารถเปรียบเทียบผลลัพธ์กับขีดจำกัดเวลาได้] - person Charles Addis; 17.03.2013

หนึ่งในเทคนิคที่ดีที่สุดสำหรับคุกกี้ถาวรที่ฉันเคยพบเห็นคือ ของ Barry Jaspan:

  1. เมื่อผู้ใช้เข้าสู่ระบบสำเร็จโดยทำเครื่องหมายที่ จดจำฉัน ระบบจะออกคุกกี้การเข้าสู่ระบบเพิ่มเติมจากคุกกี้การจัดการเซสชันมาตรฐาน
  2. คุกกี้การเข้าสู่ระบบประกอบด้วยชื่อผู้ใช้ ตัวระบุซีรีส์ และโทเค็น ซีรีส์และโทเค็นเป็นตัวเลขสุ่มที่คาดเดาไม่ได้จากพื้นที่ขนาดใหญ่ที่เหมาะสม ทั้งสามจะถูกเก็บไว้ด้วยกันในตารางฐานข้อมูล
  3. When a non-logged-in user visits the site and presents a login cookie, the username, series, and token are looked up in the database.
    1. If the triplet is present, the user is considered authenticated. The used token is removed from the database. A new token is generated, stored in database with the username and the same series identifier, and a new login cookie containing all three is issued to the user.
    2. หากมีชื่อผู้ใช้และซีรีส์แต่โทเค็นไม่ตรงกัน ถือว่าถูกขโมย ผู้ใช้จะได้รับคำเตือนที่รุนแรง และเซสชันที่จดจำของผู้ใช้ทั้งหมดจะถูกลบ
    3. หากไม่มีชื่อผู้ใช้และซีรีส์ คุกกี้การเข้าสู่ระบบจะถูกละเว้น

ฉันขอแนะนำให้คุณอ่านบทความทั้งหมด เนื้อหาข้างต้นเป็นส่วนสำคัญ

นอกจากนี้ คุณจะต้องการออกคุกกี้เหล่านี้ผ่านการเชื่อมต่อ SSL เท่านั้น และตั้งค่าสถานะ secure และ httponly บนคุกกี้

เนื่องจากหมายความว่าผู้ใช้จะได้รับการตรวจสอบสิทธิ์เฉพาะในขณะที่เชื่อมต่อกับเซิร์ฟเวอร์ผ่าน SSL ฉันจึงตั้งค่า Strict-Transport-Security เพิ่มเติม ส่วนหัว HTTP เพื่อบังคับให้เบราว์เซอร์ใช้ SSL เสมอในอนาคต และคุกกี้ธรรมดาเพิ่มเติม เช่น persistent_login_available=yes สำหรับการเชื่อมต่อที่ไม่ใช่ SSL หากเบราว์เซอร์เยี่ยมชมไซต์ผ่านการเชื่อมต่อที่ไม่ใช่ SSL และเซิร์ฟเวอร์เห็นคุกกี้ persistent_login_available เบราว์เซอร์จะเปลี่ยนเส้นทางผู้เยี่ยมชมไปยังเวอร์ชัน SSL และตรวจสอบสิทธิ์ผู้ใช้ผ่านคุกกี้ที่ปลอดภัย

ด้วยกระบวนการนี้ คุณจะปลอดภัยที่สุดเท่าที่จะเป็นไปได้ คุณเป็นผู้ตัดสินใจ อาจ เกินความจำเป็นเล็กน้อยสำหรับความต้องการของคุณ

person deceze♦    schedule 16.03.2013
comment
ฉันขอขอบคุณบทความและมันก็แน่นอน ให้คำแนะนำแก่ฉันบ้าง ฉันไม่แน่ใจมากหรือน้อยว่าจะเขียนโค้ดนี้อย่างไร แต่มีคนด้านล่างนี้ให้ตัวอย่างวิธีการเขียนโค้ดแก่ฉัน ฉันขอความคิดเห็นของคุณเกี่ยวกับแนวคิดโค้ดโดยรวมและตรวจสอบให้แน่ใจว่าเป็นโค้ดที่ดีที่จะใช้ได้หรือไม่ - person kdjernigan; 17.03.2013

กลยุทธ์นี้ถือเป็นแนวทางปฏิบัติที่ดีที่สุด: ดูบทความนี้: http://jaspan.com/improved_persistent_login_cookie_best_practice

person Ryan    schedule 16.03.2013
comment
ฉันขอขอบคุณบทความและมันก็แน่นอน ให้คำแนะนำแก่ฉันบ้าง ฉันไม่แน่ใจมากหรือน้อยว่าจะเขียนโค้ดนี้อย่างไร แต่มีคนด้านล่างนี้ให้ตัวอย่างวิธีการเขียนโค้ดแก่ฉัน ฉันขอความคิดเห็นของคุณเกี่ยวกับแนวคิดโค้ดโดยรวมและตรวจสอบให้แน่ใจว่าเป็นโค้ดที่ดีที่จะใช้ได้หรือไม่ - person kdjernigan; 17.03.2013