Câu trả lời dưới đây liên quan chủ yếu đến Cookies đã ký , một triển khai khái niệm về phiên (như được sử dụng trong các ứng dụng web). Flask cung cấp cả cookie thông thường (không dấu) (thông qua request.cookies
và response.set_cookie()
) và cookie đã ký (thông qua flask.session
). Câu trả lời có hai phần, phần đầu mô tả cách tạo Cookie đã ký và phần thứ hai được trình bày dưới dạng QA giải quyết các khía cạnh khác nhau của sơ đồ. Cú pháp được sử dụng cho các ví dụ là Python3, nhưng các khái niệm cũng áp dụng cho các phiên bản trước.
Là gì SECRET_KEY
(hoặc làm thế nào để tạo ra một Cookie Đã ký)?
Ký cookie là một biện pháp phòng ngừa chống giả mạo cookie. Trong quá trình ký một cookie, SECRET_KEY
nó được sử dụng theo cách tương tự như cách "muối" sẽ được sử dụng để trộn mật khẩu trước khi băm nó. Đây là một mô tả đơn giản (cực kỳ) của khái niệm này. Mã trong các ví dụ có nghĩa là minh họa. Nhiều bước đã bị bỏ qua và không phải tất cả các chức năng thực sự tồn tại. Mục tiêu ở đây là cung cấp một sự hiểu biết về ý tưởng chung, việc triển khai thực tế sẽ được tham gia nhiều hơn một chút. Ngoài ra, hãy nhớ rằng Flask thực hiện hầu hết điều này cho bạn trong nền. Vì vậy, bên cạnh việc đặt các giá trị cho cookie của bạn (thông qua API phiên) và cung cấp một SECRET_KEY
, bạn không chỉ nên tự mình thực hiện lại điều này mà còn không cần phải làm như vậy:
Chữ ký cookie của một người nghèo
Trước khi gửi Phản hồi tới trình duyệt:
(1) Đầu tiên a SECRET_KEY
được thành lập. Ứng dụng chỉ nên được biết đến và nên được giữ tương đối ổn định trong suốt vòng đời của ứng dụng, bao gồm cả thông qua khởi động lại ứng dụng.
# choose a salt, a secret string of bytes
>>> SECRET_KEY = 'my super secret key'.encode('utf8')
(2) tạo cookie
>>> cookie = make_cookie(
... name='_profile',
... content='uid=382|membership=regular',
... ...
... expires='July 1 2030...'
... )
>>> print(cookie)
name: _profile
content: uid=382|membership=regular...
...
...
expires: July 1 2030, 1:20:40 AM UTC
(3) để tạo chữ ký, nối thêm (hoặc thêm vào) SECRET_KEY
chuỗi byte cookie, sau đó tạo hàm băm từ kết hợp đó.
# encode and salt the cookie, then hash the result
>>> cookie_bytes = str(cookie).encode('utf8')
>>> signature = sha1(cookie_bytes+SECRET_KEY).hexdigest()
>>> print(signature)
7ae0e9e033b5fa53aa....
(4) Bây giờ gắn chữ ký ở một đầu của content
trường của cookie gốc.
# include signature as part of the cookie
>>> cookie.content = cookie.content + '|' + signature
>>> print(cookie)
name: _profile
content: uid=382|membership=regular|7ae0e9... <--- signature
domain: .example.com
path: /
send for: Encrypted connections only
expires: July 1 2030, 1:20:40 AM UTC
và đó là những gì được gửi cho khách hàng.
# add cookie to response
>>> response.set_cookie(cookie)
# send to browser -->
Khi nhận được cookie từ trình duyệt:
(5) Khi trình duyệt trả lại cookie này cho máy chủ, hãy xóa chữ ký khỏi trường của cookie content
để lấy lại cookie ban đầu.
# Upon receiving the cookie from browser
>>> cookie = request.get_cookie()
# pop the signature out of the cookie
>>> (cookie.content, popped_signature) = cookie.content.rsplit('|', 1)
(6) Sử dụng cookie ban đầu với ứng dụng SECRET_KEY
để tính toán lại chữ ký bằng phương pháp tương tự như trong bước 3.
# recalculate signature using SECRET_KEY and original cookie
>>> cookie_bytes = str(cookie).encode('utf8')
>>> calculated_signature = sha1(cookie_bytes+SECRET_KEY).hexdigest()
(7) So sánh kết quả tính toán với chữ ký được bật ra khỏi cookie vừa nhận được. Nếu chúng khớp, chúng tôi biết rằng cookie đã không bị rối. Nhưng nếu thậm chí chỉ cần thêm một khoảng trắng vào cookie, chữ ký sẽ không khớp.
# if both signatures match, your cookie has not been modified
>>> good_cookie = popped_signature==calculated_signature
(8) Nếu chúng không khớp thì bạn có thể phản hồi với bất kỳ số lượng hành động nào, đăng nhập sự kiện, loại bỏ cookie, phát hành mới, chuyển hướng đến trang đăng nhập, v.v.
>>> if not good_cookie:
... security_log(cookie)
Mã xác thực thư dựa trên băm (HMAC)
Loại chữ ký được tạo ở trên yêu cầu khóa bí mật để đảm bảo tính toàn vẹn của một số nội dung được gọi trong mật mã là Mã xác thực thư hoặc MAC .
Tôi đã xác định trước đó rằng ví dụ trên là sự đơn giản hóa khái niệm đó và đó không phải là một ý tưởng tốt để thực hiện việc ký kết của riêng bạn. Đó là bởi vì thuật toán được sử dụng để ký cookie trong Flask được gọi là HMAC và có liên quan nhiều hơn một chút so với từng bước đơn giản ở trên. Ý tưởng chung là như nhau, nhưng do những lý do nằm ngoài phạm vi của cuộc thảo luận này, loạt tính toán phức tạp hơn một chút. Nếu bạn vẫn quan tâm đến việc tạo một DIY, như thường lệ, Python có một số mô-đun để giúp bạn bắt đầu :) đây là một khối bắt đầu:
import hmac
import hashlib
def create_signature(secret_key, msg, digestmod=None):
if digestmod is None:
digestmod = hashlib.sha1
mac = hmac.new(secret_key, msg=msg, digestmod=digestmod)
return mac.digest()
Các tài liệu cho hmac và hashlib .
"Làm sáng tỏ" của SECRET_KEY
:)
"Chữ ký" trong bối cảnh này là gì?
Đó là một phương pháp để đảm bảo rằng một số nội dung chưa được sửa đổi bởi bất kỳ ai khác ngoài một người hoặc một thực thể được ủy quyền để làm như vậy.
Một trong những hình thức chữ ký đơn giản nhất là " tổng kiểm tra ", đơn giản chỉ cần xác minh rằng hai phần dữ liệu giống nhau. Ví dụ: khi cài đặt phần mềm từ nguồn, trước tiên, điều quan trọng là phải xác nhận rằng bản sao mã nguồn của bạn giống hệt với tác giả. Một cách tiếp cận phổ biến để làm điều này là chạy nguồn thông qua hàm băm mật mã và so sánh đầu ra với tổng kiểm tra được công bố trên trang chủ của dự án.
Ví dụ, giả sử bạn sắp tải xuống nguồn của dự án trong một tệp được nén từ máy nhân bản web. Tổng kiểm tra SHA1 được công bố trên trang web của dự án là 'eb84e8da7ca23e9f83 ....'
# so you get the code from the mirror
download https://mirror.example-codedump.com/source_code.tar.gz
# you calculate the hash as instructed
sha1(source_code.tar.gz)
> eb84e8da7c....
Cả hai giá trị băm đều giống nhau, bạn biết rằng bạn có một bản sao giống hệt nhau.
Cookie là gì?
Một cuộc thảo luận rộng rãi về cookie sẽ vượt ra ngoài phạm vi của câu hỏi này. Tôi cung cấp một cái nhìn tổng quan ở đây vì một sự hiểu biết tối thiểu có thể hữu ích để hiểu rõ hơn về cách thức và lý do SECRET_KEY
hữu ích. Tôi rất khuyến khích bạn theo dõi một số bài đọc cá nhân về HTTP Cookies.
Một thực tế phổ biến trong các ứng dụng web là sử dụng máy khách (trình duyệt web) làm bộ đệm nhẹ. Cookies là một trong những thực hiện của thực hành này. Một cookie thường là một số dữ liệu được máy chủ thêm vào phản hồi HTTP bằng các tiêu đề của nó. Nó được giữ bởi trình duyệt mà sau đó sẽ gửi lại cho máy chủ khi đưa ra yêu cầu, cũng bằng cách sử dụng các tiêu đề HTTP. Dữ liệu chứa trong cookie có thể được sử dụng để mô phỏng những gì được gọi là trạng thái, ảo tưởng rằng máy chủ đang duy trì kết nối liên tục với máy khách. Chỉ trong trường hợp này, thay vì dây để giữ kết nối "sống", bạn chỉ cần có ảnh chụp nhanh về trạng thái của ứng dụng sau khi ứng dụng đã xử lý yêu cầu của khách hàng. Các ảnh chụp nhanh này được thực hiện qua lại giữa máy khách và máy chủ. Khi nhận được yêu cầu, trước tiên, máy chủ sẽ đọc nội dung của cookie để thiết lập lại bối cảnh của cuộc trò chuyện với khách hàng. Sau đó, nó xử lý yêu cầu trong bối cảnh đó và trước khi trả lời phản hồi cho khách hàng, cập nhật cookie. Ảo tưởng của một phiên liên tục được duy trì.
Cookie trông như thế nào?
Một cookie thông thường sẽ trông như thế này:
name: _profile
content: uid=382|status=genie
domain: .example.com
path: /
send for: Encrypted connections only
expires: July 1 2030, 1:20:40 AM UTC
Cookies là tầm thường để xem xét từ bất kỳ trình duyệt hiện đại. Ví dụ, trên Firefox, hãy vào Tùy chọn> Quyền riêng tư> Lịch sử> xóa từng cookie .
Các content
lĩnh vực là phù hợp nhất cho các ứng dụng. Các lĩnh vực khác thực hiện hầu hết các hướng dẫn meta để chỉ định phạm vi ảnh hưởng khác nhau.
Tại sao lại sử dụng cookie?
Câu trả lời ngắn gọn là hiệu suất. Sử dụng cookie, giảm thiểu nhu cầu tìm kiếm mọi thứ trong các kho dữ liệu khác nhau (bộ nhớ đệm, tệp, cơ sở dữ liệu, v.v.), do đó tăng tốc mọi thứ về phía ứng dụng máy chủ. Hãy nhớ rằng cookie càng lớn thì tải trọng qua mạng càng nặng, do đó, những gì bạn lưu trong tra cứu cơ sở dữ liệu trên máy chủ bạn có thể mất qua mạng. Xem xét cẩn thận những gì cần bao gồm trong cookie của bạn.
Tại sao cookie cần phải được ký?
Cookies được sử dụng để giữ tất cả các loại thông tin, một số trong đó có thể rất nhạy cảm. Về bản chất, chúng cũng không an toàn và yêu cầu một số biện pháp phòng ngừa phụ trợ phải được coi là an toàn theo bất kỳ cách nào cho cả hai bên, khách hàng và máy chủ. Việc ký cookie đặc biệt giải quyết vấn đề mà họ có thể khắc phục trong các nỗ lực để đánh lừa các ứng dụng máy chủ. Có các biện pháp khác để giảm thiểu các loại lỗ hổng khác, tôi khuyến khích bạn đọc thêm về cookie.
Làm thế nào một cookie có thể bị giả mạo?
Cookies nằm trên máy khách ở dạng văn bản và có thể được chỉnh sửa mà không cần nỗ lực. Một cookie được nhận bởi ứng dụng máy chủ của bạn có thể đã được sửa đổi vì một số lý do, một số trong đó có thể không phải là vô tội. Hãy tưởng tượng một ứng dụng web giữ thông tin cấp phép về người dùng của nó trên cookie và cấp các đặc quyền dựa trên thông tin đó. Nếu cookie không phải là tinker, bất kỳ ai cũng có thể sửa đổi trạng thái của họ để nâng cao trạng thái của họ từ "vai trò = khách truy cập" thành "vai trò = quản trị viên" và ứng dụng sẽ không khôn ngoan hơn.
Tại sao SECRET_KEY
cần thiết để ký cookie?
Xác minh cookie khác một chút so với xác minh mã nguồn theo cách nó được mô tả trước đó. Trong trường hợp mã nguồn, tác giả ban đầu là người ủy thác và chủ sở hữu của dấu vân tay tham chiếu (tổng kiểm tra), sẽ được giữ công khai. Những gì bạn không tin tưởng là mã nguồn, nhưng bạn tin tưởng chữ ký công khai. Vì vậy, để xác minh bản sao của nguồn bạn chỉ muốn băm tính toán của bạn khớp với băm công khai.
Tuy nhiên, trong trường hợp cookie, ứng dụng không theo dõi chữ ký, nó sẽ theo dõi chữ ký của nó SECRET_KEY
. Đây SECRET_KEY
là dấu vân tay tham khảo. Cookies đi du lịch với một chữ ký mà họ tuyên bố là hợp pháp. Tính hợp pháp ở đây có nghĩa là chữ ký được cấp bởi chủ sở hữu của cookie, đó là ứng dụng và trong trường hợp này, đó là tuyên bố rằng bạn không tin tưởng và bạn cần kiểm tra chữ ký để xác thực. Để làm điều đó, bạn cần bao gồm một yếu tố trong chữ ký mà chỉ bạn biết, đó là SECRET_KEY
. Ai đó có thể thay đổi cookie, nhưng vì họ không có thành phần bí mật để tính đúng chữ ký hợp lệ nên họ không thể giả mạo nó. Như đã nêu trước đó một chút về loại dấu vân tay này, trong đó trên cùng của tổng kiểm tra cũng cung cấp một khóa bí mật,
Phiên thì sao?
Các phiên trong triển khai cổ điển của họ là các cookie chỉ mang một ID trong content
trường , session_id
. Mục đích của các phiên hoàn toàn giống như các cookie đã ký, nghĩa là để ngăn chặn việc giả mạo cookie. Phiên cổ điển có một cách tiếp cận khác nhau mặc dù. Khi nhận được cookie phiên, máy chủ sử dụng ID để tra cứu dữ liệu phiên trong bộ nhớ cục bộ của chính nó, có thể là cơ sở dữ liệu, tệp hoặc đôi khi là bộ đệm trong bộ nhớ. Cookie phiên thường được đặt hết hạn khi đóng trình duyệt. Do bước tra cứu lưu trữ cục bộ, việc triển khai các phiên này thường phát sinh một cú đánh hiệu suất. Cookie đã ký đang trở thành một lựa chọn thay thế ưa thích và đó là cách các phiên của Flask được triển khai. Nói cách khác, phiên Flask làcookie đã ký và để sử dụng cookie đã ký trong Flask, chỉ cần sử dụng Session
API của nó .
Tại sao không mã hóa cookie?
Đôi khi nội dung của cookie có thể được mã hóa trước khi được ký . Điều này được thực hiện nếu chúng được coi là quá nhạy cảm để có thể nhìn thấy từ trình duyệt (mã hóa ẩn nội dung). Tuy nhiên, chỉ cần ký cookie, giải quyết một nhu cầu khác nhau, một nhu cầu duy trì mức độ hiển thị và khả năng sử dụng cookie trên trình duyệt, đồng thời ngăn chặn việc chúng bị can thiệp.
Điều gì xảy ra nếu tôi thay đổi SECRET_KEY
?
Bằng cách thay đổi SECRET_KEY
bạn đang làm mất hiệu lực tất cả các cookie đã ký với khóa trước đó. Khi ứng dụng nhận được yêu cầu với cookie đã được ký trước đó SECRET_KEY
, nó sẽ cố gắng tính chữ ký với cái mới SECRET_KEY
và cả hai chữ ký sẽ không khớp, cookie này và tất cả dữ liệu của nó sẽ bị từ chối, nó sẽ như thể trình duyệt đang kết nối với máy chủ lần đầu tiên. Người dùng sẽ được đăng xuất và cookie cũ của họ sẽ bị lãng quên, cùng với mọi thứ được lưu trữ bên trong. Lưu ý rằng điều này khác với cách xử lý cookie hết hạn. Một cookie hết hạn có thể được gia hạn hợp đồng thuê nếu chữ ký của nó bị mất. Một chữ ký không hợp lệ chỉ ngụ ý một cookie không hợp lệ đơn giản.
Vì vậy, trừ khi bạn muốn làm mất hiệu lực tất cả các cookie đã ký, hãy cố gắng giữ SECRET_KEY
nguyên như vậy trong thời gian dài.
Có gì tốt SECRET_KEY
?
Một chìa khóa bí mật nên khó đoán. Tài liệu về Phiên có một công thức tốt để tạo khóa ngẫu nhiên:
>>> import os
>>> os.urandom(24)
'\xfd{H\xe5<\x95\xf9\xe3\x96.5\xd1\x01O<!\xd5\xa2\xa0\x9fR"\xa1\xa8'
Bạn sao chép khóa và dán nó vào tệp cấu hình của bạn làm giá trị của SECRET_KEY
.
Không sử dụng khóa được tạo ngẫu nhiên, bạn có thể sử dụng một loại từ, số và ký hiệu phức tạp, có lẽ được sắp xếp trong một câu chỉ bạn biết, được mã hóa dưới dạng byte.
Đừng không thiết lập SECRET_KEY
trực tiếp với một chức năng mà tạo ra một chìa khóa khác nhau mỗi lần nó được gọi. Ví dụ: không làm điều này:
# this is not good
SECRET_KEY = random_key_generator()
Mỗi lần ứng dụng của bạn được khởi động lại, nó sẽ được cấp một khóa mới, do đó làm mất hiệu lực của lần trước.
Thay vào đó, hãy mở một vỏ python tương tác và gọi hàm để tạo khóa, sau đó sao chép và dán nó vào cấu hình.