2010-01-09 47 views
16

Tôi đang tạo trang web PHP liên quan đến việc người dùng đăng ký và tôi tự hỏi về các phương pháp hay nhất cho mã "xác nhận email".Thực tiễn tốt nhất cho mã xác nhận email

Người dùng mới phải xác nhận địa chỉ email của họ - tôi làm điều này bằng cách tạo mã và gửi mã cho người dùng trong email, sau đó họ có thể sử dụng để kích hoạt tài khoản của anh ấy. Thay vì lưu trữ quan trọng này trong một cơ sở dữ liệu, tôi đang sử dụng một workaround ít tiện dụng: mã là kết quả của:

md5("xxxxxxxxx".$username."xxxxxxxxxxx".$timestamp."xxxxxxxxx"); 

đâu $ timestamp đề cập đến thời gian sử dụng sáng tạo. Về tổng thể tôi khá hài lòng với điều này, nhưng sau đó tôi đã suy nghĩ, điều này là đủ an toàn? Và những gì về khả năng va chạm? Và tôi cũng cần tạo mã để đặt lại mật khẩu, v.v. Nếu tôi đã sử dụng phương pháp tương tự, một xung đột có thể khiến một người dùng vô tình đặt lại mật khẩu của người dùng khác. Và điều đó không tốt.

Vậy bạn làm những việc này như thế nào? Suy nghĩ của tôi là một bảng có định dạng sau:

codePK (int, a-I), userID (int), type (int), code (varchar 32), date (timestamp) 

Trường hợp 'loại' là 1, 2 hoặc 3 có nghĩa là "kích hoạt", "thay đổi email" hoặc "đặt lại mật khẩu". Đây có phải là cách hay để làm điều đó không? Bạn có cách nào tốt hơn không?

Sử dụng phương pháp tương tự như trên, tôi có thể tự động xóa bất kỳ thứ gì trong hai ngày mà không sử dụng cron-jobs không? Máy chủ của tôi (nearfreespeech.net) không hỗ trợ chúng. Nếu có thể tôi muốn tránh có một cron-job trên một máy chủ bên ngoài mà wget của một kịch bản mà xóa mọi thứ, vì đó chỉ là lộn xộn = P.

Cảm ơn!
Mala

Cập nhật:
Để làm rõ: Tôi đã nhận ra cách duy nhất để bảo mật và an toàn đi về nhiệm vụ này là bằng cách sử dụng một cơ sở dữ liệu, đó là những gì các chức năng ban đầu đã cố gắng để tránh. Câu hỏi của tôi là về cách bảng (hoặc bảng?) Nên được cấu trúc. Ai đó đề nghị tôi làm với codePK và chỉ làm cho mã một PK. Vì vậy, trong ngắn hạn, câu hỏi của tôi là: đây là những gì bạn làm gì?

+0

Thực tiễn tốt nhất cho mã xác nhận e-mail? Để chúng ra ... – Leo

+1

Điều quan trọng là người dùng có địa chỉ email hợp lệ trong hồ sơ, nếu chỉ để đặt lại mật khẩu. Trong khi người ta có thể tuyên bố "đó là trách nhiệm của người dùng", đây là thế giới thực mà chúng ta đang xử lý ... Ngay khi người đầu tiên "KHÔNG BAO GIỜ quên mật khẩu", hãy quên mật khẩu của anh ta, có thể là một hoặc hai tuần, hệ thống sẽ là "người ngu ngốc nhất". – Mala

Trả lời

10

Khi tôi cần những loại thủ đoạn đó là bình thường của một trong hai lý do, cả hai được đề cập bởi bạn:

  1. Là một chính được sử dụng cho các email xác minh gửi đến người dùng
  2. Như một chìa khóa được sử dụng để liên kết đặt lại mật khẩu

Tất nhiên sẽ có nhiều trường hợp khác bạn cân nhắc sử dụng công trình như vậy.

Trước hết, bạn nên luôn sử dụng một số loại muối bị ẩn và chỉ bạn biết. Lưu ý rằng muối này phải khác nhau cho mỗi người dùng. Ví dụ, muối có thể được tính là sha256(something random). Muối này sau đó sẽ được lưu trữ trong cơ sở dữ liệu cùng với tên người dùng và mật khẩu (được băm với muối).

Điều tôi sẽ làm khi gửi liên kết đặt lại mật khẩu là tạo một muối khác (không cấp cho người dùng quyền truy cập vào bất kỳ thứ gì được băm bằng muối của bạn. Anh biết mật khẩu của mình, vì vậy sử dụng bruteforce anh có khả năng tìm ra muối của bạn) . Các muối khác, mà về cơ bản chỉ là một băm của một chuỗi ngẫu nhiên (bạn có thể muốn đi cho md5 ở đây, như bạn đã đề cập rằng chiều dài là một vấn đề), sau đó bạn nên lưu vào cơ sở dữ liệu của bạn.

Thông thường, bạn chỉ có thể thoát khỏi việc thêm cột bổ sung vào bảng người dùng của mình. Điều này, tuy nhiên, cũng có một vài vấn đề, chủ yếu là khi mật khẩu đã được thiết lập lại hoặc người dùng đã được kích hoạt, bạn sẽ xóa khóa khỏi cơ sở dữ liệu, kết quả là hầu hết các hàng có giá trị null. .

Điều này về cơ bản nắm tới:

  • Hash mật khẩu của người dùng bằng cách sử dụng muối độc đáo-cho-the-user ( có lẽ là một, muối bí mật toàn cầu).
  • Tạo khóa bằng cách băm một số nguồn ngẫu nhiên hoặc giả ngẫu nhiên như dấu thời gian, mt_rand() hoặc thậm chí random.org nếu bạn thực sự muốn các nội dung ngẫu nhiên.
  • bao giờ sử dụng muối toàn cầu của bạn hoặc muối mà là duy nhất cho người sử dụng cho bất cứ điều gì băm mà người dùng được quyền truy cập vào, bao gồm các phím reset mật khẩu, mã khóa kích hoạt, vv

Xin lưu ý rằng tôi không có có nghĩa là một chuyên gia an ninh, và tôi có lẽ đã quên một số thứ, và tôi có thể đã đề cập đến một số điều thực hành rất xấu. Chỉ 5 xu của tôi ;-)

1

Đã đủ an toàn cho đến thời điểm bạn xuất bản phương thức của mình trên Internet! Điều này là bởi vì bạn đang dựa vào an ninh bởi sự tối tăm, đó không phải là một ý tưởng hay.

Bạn nên sử dụng một số chức năng băm có khóa hoặc MAC lý tưởng, kết hợp khóa bí mật chỉ được biết với bạn.

+2

rõ ràng là 'x'es không thực sự' x'es trong mã – Mala

+0

Trong trường hợp đó, bạn đã tạo ra một hàm băm có khóa và bạn tốt để đi. Tôi có lẽ đã đoán rằng ...;) –

+0

;) xin lỗi tôi nghĩ rằng tôi đã chỉ định rằng - nhưng dường như tôi chỉnh sửa bit, nơi tôi rõ ràng nói rằng ... trong mọi trường hợp tôi tự hỏi nếu cấu trúc bảng/bằng cách sử dụng một bảng duy nhất cho tất cả các mã là thích hợp – Mala

0

Tại sao không tạo chỉ mục duy nhất cho trường mã? Vì vậy, sẽ không bao giờ có collsisions?

Ngoài ra, nếu bạn không cần phải tạo ra băm từ người dùng nhập vào và kết hợp nó vào cơ sở dữ liệu băm (xác nhận email, mật khẩu reset vv) - bạn có thể thêm chuỗi ngẫu nhiên cho cơ thể băm, như md5('xxx'.$username.'xxx'.time().'xxx'.rand())

+0

thì tôi sẽ không thể kiểm tra nó mà không sử dụng cơ sở dữ liệu - toàn bộ điểm của hàm đó là để tránh sử dụng chúng.Nếu tôi sẽ sử dụng cơ sở dữ liệu, thì tôi có thể để toàn bộ chuỗi là hoàn toàn ngẫu nhiên – Mala

2

Tại sao lại sử dụng bất kỳ dữ liệu nào của người dùng làm cơ sở cho khóa ủy quyền?

Tôi đoán bạn đang lưu trữ dữ liệu không kích hoạt trong cơ sở dữ liệu vậy tại sao không chỉ thêm một bản ghi bổ sung đơn giản là một khóa ngẫu nhiên (có lẽ là md5'ed uniqid với một số thao tác bổ sung) và sau đó kiểm tra lại?

+0

Ban đầu tôi đã cố gắng tránh phải sử dụng cơ sở dữ liệu cho điều này - do đó sử dụng userdata – Mala

+1

Thành thật mà nói, tôi không thể giúp đỡ nhưng nghĩ rằng một cơ sở dữ liệu là con đường để đi, nếu không bạn sẽ bị băm/thao tác một nhóm dữ liệu tĩnh khá hạn chế. –

0

Tại sao không yêu cầu người dùng nhập tên người dùng mã của họ, do đó loại bỏ bất kỳ sự cố nào xảy ra xung đột?Bạn không mất bất kỳ thứ gì bảo mật khi bạn vẫn yêu cầu khóa mà họ nhận được từ email, nhưng bạn sẽ ngăn họ có thể đặt lại mật khẩu của người dùng khác.

+1

Lý tưởng nhất là họ có thể chỉ cần nhấp vào liên kết trong email. Tôi không muốn điều này là khủng khiếp dài = P – Mala

Các vấn đề liên quan