Đăng nhập vào trang bằng mật khẩu php. Mật khẩu bảo vệ. Đặt mật khẩu trên trang

Đặt mật khẩu trên trang

Bài viết này không hề có vẻ là tiết lộ gì cả, tất cả những điều này đều khá hiển nhiên và được biết đến rộng rãi. Nhưng gần đây khi nhận được một số câu hỏi về việc hạn chế quyền truy cập vào các trang web, tôi quyết định gộp các câu trả lời lại với nhau.

Vì vậy, nhiệm vụ của chúng ta là đặt mật khẩu để truy cập vào một trang nhất định. Hãy bắt đầu với phương pháp bảo vệ nguyên thủy nhất - có thể nói là một vài dòng JavaScript. Mã này giống như

Var pass = nhắc("Nhập mật khẩu:", ""); if (pass == null) window.location = "bad.html"; khác nếu (pass.toLowerCase() == "password") window.location = "ok.html"; else window.location = "bad..js"> về cơ bản không thay đổi bất cứ điều gì.

Ở cấp độ cao hơn, có một hệ thống tương tự được triển khai bằng Java.

Dưới đây là mã nguồn đơn giản hóa.

Nhập java.applet.*; nhập java.awt.*; nhập java.net.*; public class Mật khẩu mở rộng Applet ( TextField đăng nhập, mật khẩu; Đăng nhập chuỗi = "đăng nhập"; Mật khẩu chuỗi = "Mật khẩu"; mật khẩu công khai() ( ) public void init() ( Panel panel = new Panel(); panel.setLayout(new GridLayout(2,2)); login = new TextField(20); mật khẩu = new TextField(20); panel.add(new Label("Đăng nhập:")); panel.add(đăng nhập); panel.add(new Label("Mật khẩu:")); panel.add(password); add(panel); add(new Button("Ok")); ) public boolean action(Event evt, Object obj) ( if(evt.target instanceof Nút) ( Chuỗi s; if(login.getText().equals(Login) && pass.getText().equals(Password)) ( s = "http://www.webclub.ru/materials/ pagepsw/ok. html"; ) khác ( s = "http://www.webclub.ru/materials/pagepsw/bad.html"; ) thử ( getAppletContext().showDocument ((các) URL mới); ) Catch(Ngoại lệ e) ( pass.setText(e.toString()); ) trả về true; ) trả về false; ) )

Bằng cách đưa applet này vào một trang, bạn có thể nhận được kết quả như thế này:

Kiểm tra mật khẩu

Nó có thể được làm thông minh hơn, tạo một trang riêng cho mỗi người dùng, buộc nó đọc dữ liệu từ một tệp, v.v. Hạn chế cơ bản là một khi một người đã đến trang mà anh ta đang tìm kiếm, không ai có thể ngăn anh ta ghi nhớ URL này, vì vậy đây là công cụ sử dụng một lần. Tất nhiên, bạn có thể ẩn trang bên trong khung để URL không xuất hiện trên thanh địa chỉ, nhưng bạn hiểu sự bảo vệ này là của ai. Một lần nữa, applet hoàn toàn được chuyển đến khách hàng và về nguyên tắc, hoàn toàn có sẵn để nghiên cứu.

Giải pháp dựa trên việc sử dụng CGI không có nhược điểm cuối cùng. Một tập lệnh Perl đơn giản trông giống như thế này:

#!/usr/bin/Perl sử dụng CGI qw(:standard); $query = CGI mới; $ok = "ok.html"; $address = "bad.html"; $đăng nhập = "đăng nhập"; $password = "mật khẩu"; $l = $query->param("đăng nhập"); $p = $query->param("mật khẩu"); if(($p eq $password) && ($l eq $login)) ( $address = $ok; ) print $query->redirect($address);

Ví dụ sử dụng:

Kiểm tra mật khẩu

Để giải quyết nhược điểm đầu tiên, bạn có thể tự động tạo một trang mới dựa trên trang ẩn ở đâu đó bên trong mà không cần cung cấp URL.

Mã đã sửa đổi:

#!/usr/bin/Perl sử dụng CGI qw(:standard); $query = CGI mới; $ok = "ok.html"; $address = "bad.html"; $docroot = $ENV("DOCUMENT_ROOT"); $localpath = "/materials/pagepsw/"; $đăng nhập = "đăng nhập"; $password = "mật khẩu"; $l = $query->param("đăng nhập"); $p = $query->param("mật khẩu"); if(($p eq $password) && ($l eq $login)) ( $address = $ok; ) print $query->header(); open(FL, $docroot.$localpath.$address); while() ( # Ở đây bạn cũng có thể sửa đổi mã html một cách nhanh chóng # Tại sao? Chà, bạn không bao giờ biết... :) print $_; )đóng(FL);

Ví dụ sử dụng:

Kiểm tra mật khẩu

Như bạn có thể thấy, URL tệp không còn được hiển thị, mặc dù phải trả giá bằng SSI, nếu có thứ gì đó tương tự (tuy nhiên, điều này có thể bị phát hiện trong quá trình xuất và được xử lý theo cách thủ công). Nhưng ngay cả ở đây vẫn có khả năng đoán URL về mặt lý thuyết và chúng ta không được quên rằng tất cả các loại hình ảnh có trong các trang đều có thể gây hại - tất nhiên là khi sử dụng các đường dẫn tương đối.

Cuối cùng, cách đáng tin cậy nhất để đặt mật khẩu truy cập là sử dụng các công cụ máy chủ - xét cho cùng, mọi người đã làm như vậy không phải là vô ích. Tôi sẽ tập trung vào hai - Apache là phổ biến nhất và IIS cũng phổ biến :)

Với IIS, mọi thứ khá đơn giản - việc bảo vệ được thực hiện bằng NTFS, tất nhiên, điều này phần nào hạn chế khả năng của những quản trị viên không phải máy chủ. Ý tưởng như sau: người dùng IUSR_xxxx, với tài khoản của họ, tất cả khách truy cập trang web đều hoạt động theo mặc định, bị từ chối quyền truy cập vào tệp/thư mục mong muốn. Sau đó, chỉ những người dùng được chỉ định rõ ràng trong Thuộc tính->Bảo mật mới có quyền truy cập vào các tệp này. Rõ ràng là sẽ thuận tiện hơn nhiều khi kết hợp chúng thành nhóm. Có một vài sự tinh tế ở đây. Đầu tiên, những người dùng được chỉ định phải được cấp quyền Đăng nhập cục bộ (Chính sách->Quyền người dùng trong Trình quản lý người dùng). Thứ hai, nếu bạn không chọn dịch vụ WWW Xác thực cơ bản (Clear Text) trong cài đặt WWW, chỉ người dùng Internet Explorer mới được được phép trong "A.

Trong Apache, mọi thứ được thực hiện hơi khác một chút. Bảo vệ được đặt ở cấp thư mục. Các lệnh tương ứng có thể được đặt cả trong tệp cấu hình chung (trong phần) và trong tệp .htaccess. Bộ chỉ thị trong cả hai trường hợp đều giống nhau và đối với hầu hết mọi người thuê không gian cho một trang web/trang trên máy chủ của người khác, phương pháp thứ hai phù hợp hơn nhiều. Vì vậy, bạn tạo một tệp .htaccess trong thư mục mà bạn định hạn chế quyền truy cập, sau đó chèn các lệnh sau vào đó (Tôi sẽ liệt kê các lệnh chính):

Loại xác thực loại điều khiển- Cơ bản thường được sử dụng.

Tên xác thực Tên- chỉ định tên của khu vực mà tên người dùng và mật khẩu hợp lệ. Đây là tên mà trình duyệt hiển thị trong hộp thoại mật khẩu. Bằng cách đặt một tên như vậy cho các thư mục khác nhau, bạn có thể tiết kiệm thời gian cho người dùng nhập mật khẩu bổ sung.

Tệp nhóm xác thực Tên- chỉ định tên của tệp trong đó tên của các nhóm và thành viên của họ được lưu trữ. Định dạng của nó:
nhóm1: thành viên1 thành viên2 ...
nhóm2: thành viên3 thành viên4 ...

Tệp người dùng xác thực Tên- chỉ định tên của tập tin bằng mật khẩu. Nhìn chung, để tạo nó, bạn cần sử dụng tiện ích htpasswd từ bản phân phối Apache. Nhưng ít nhất đối với một số phiên bản của máy chủ, định dạng này giống như sau:
người dùng1: mật khẩuhash1
người dùng2: mật khẩuhash2

Có thể dễ dàng lấy được mật khẩu bằng cách sử dụng hàm Perl tiêu chuẩn:
$hash=crypt($pass,$salt);
trong đó $pass là mật khẩu, $salt là chuỗi hai ký tự liên quan đến việc tạo hàm băm.

Vì vậy, hoàn toàn có thể tự động hóa quá trình thêm người dùng mới, thay đổi mật khẩu thông qua biểu mẫu html, v.v.

yêu cầu người dùng người dùng1 người dùng2 và yêu cầu nhóm người dùng1 người dùng2 cho phép bạn chỉ định người dùng và nhóm nào sẽ có quyền truy cập vào một thư mục nhất định.

yêu cầu người dùng hợp lệ cho phép truy cập vào tất cả người dùng được chỉ định trong tệp mật khẩu hệ thống.

... , phương thức ở đâu Tôiđịnh nghĩa một phương thức HTTP. Ví dụ, nó giới hạn việc sử dụng các lệnh lồng nhau trong các trường hợp sử dụng phương thức GET và POST (thường thì điều này là quá đủ). Các chỉ thị có thể được lồng vào nhau: yêu cầu, ra lệnh, cho phép và từ chối.

Một vài chỉ thị hữu ích khác lần lượt là từ chối và cho phép - từ chối và cho phép truy cập. Áp dụng một cái gì đó như thế này:
tư chôi tât cả
cho phép từ 192.168

Theo mặc định, tất cả từ chối được thực thi trước, sau đó tất cả đều cho phép, do đó, cho phép từ tất cả sẽ cho phép truy cập vào tất cả người dùng, bất kể bất kỳ từ chối nào. Lệnh có thể được thay đổi bằng lệnh: lệnh cho phép, từ chối.

từ chối tất cả diễn ra tốt đẹp với phương pháp bảo vệ trang thứ hai thông qua CGI; chỉ thị này là tốt nhất để che tất cả các loại mật khẩu cho sổ khách, v.v.

Nhân tiện, ở đây, việc xử lý lỗi độc lập được thể hiện ở đây: trong trường hợp này là mã 403, Bị cấm. Lỗi 404, Not Found và 401, Unauthorized được xử lý tương tự. Để thực hiện việc này, chỉ cần thêm lệnh ErrorDocument vào .htaccess mã địa chỉ:
Tài liệu lỗi 404 /cgi-bin/bad.pl
Tài liệu Lỗi 403 /cgi-bin/badaccess.pl
Tài liệu Lỗi 401 /cgi-bin/badaccess.pl

Tất cả những gì tập lệnh thực hiện là tạo ra một thông báo lỗi bằng cách sử dụng biến môi trường REQUEST_URI, do đó bạn chỉ cần trỏ đến một số trang phù hợp.

Đối với ví dụ cuối cùng, chúng tôi sử dụng tệp .htaccess có nội dung sau:

Kiểm tra tên xác thực cơ bản AuthType AuthGroupFile /.../pagepsw/deny/tgroup AuthUserFile /.../pagepsw/deny/tuser yêu cầu kiểm tra nhóm

Chỉ có một dòng trong tệp tgroup - kiểm tra: kiểm tra đăng nhập, trong tệp tuser - mật khẩu được mã hóa để đăng nhập (mật khẩu) và kiểm tra (kiểm tra). Xin lưu ý rằng khi bạn truy cập lại trang này, trình duyệt hiểu rằng nó vừa truy cập vào khu vực này và không làm phiền người dùng bằng yêu cầu mật khẩu không cần thiết.

Tóm lại, đây là tập hợp thông tin tối thiểu cần thiết để bảo vệ các trang web. Như thực tế cho thấy, ít nhiều bạn chỉ nên tin tưởng các giải pháp dựa trên các công cụ do máy chủ cung cấp (và sau đó cho đến khi phát hiện ra một lỗ hổng khác trên máy chủ), vì vậy nếu có thể, tốt hơn hết bạn nên chọn chúng.


Một trong những tiên đề chính về bảo mật thông tin nêu rõ rằng “sự thoải mái của một hệ thống tỷ lệ nghịch với tính bảo mật của nó”. Điều này có nghĩa là khi lựa chọn một hệ thống bảo mật cần phải tìm ra sự cân bằng tối ưu giữa độ phức tạp của bảo mật và sự tiện lợi trong trải nghiệm của người dùng.


Mặt khác, việc phát triển và thực hiện bảo vệ đòi hỏi một lượng công sức và tiền bạc nhất định. Vì vậy, cần phải có cách tiếp cận hợp lý trong việc thiết kế bảo vệ. Nói một cách đơn giản, không cần phải tạo ra một hệ thống bảo mật phức tạp và tốn kém nếu không có gì có giá trị được lưu trữ trên trang web. Không một kẻ tấn công nào cố gắng phá vỡ trang chủ của bạn, trang web danh thiếp của một công ty nhỏ hoặc trang web của một trường mẫu giáo.


Trong bài học trước, chúng ta đã xem xét việc ủy ​​quyền bằng máy chủ Web (Ủy quyền cơ bản). Đây có lẽ là cách dễ nhất và an toàn nhất để hạn chế quyền truy cập vào tài nguyên. Tuy nhiên, việc duy trì cơ chế như vậy khá tốn công, đặc biệt với số lượng lớn người dùng với các quyền khác nhau. Ngoài ra, không phải máy chủ nào cũng cho phép xác thực HTTP.


Một giải pháp thay thế phổ biến hơn là bảo vệ bằng mật khẩu. Ý nghĩa của nó là máy chủ lưu trữ danh sách người dùng và thông tin đăng nhập, mật khẩu và quyền truy cập tương ứng của họ. Khi truy cập trang web lần đầu tiên, người dùng nhập thông tin đăng nhập/mật khẩu và có quyền truy cập vào tài nguyên. Máy chủ “ghi nhớ” người dùng và không yêu cầu mật khẩu cho đến khi mở phiên tiếp theo (khởi động lại trình duyệt).

Việc tổ chức bảo vệ bằng mật khẩu hoàn toàn thuộc về người lập trình. Nhà phát triển phải đảm bảo tính bảo mật trong việc lưu trữ danh sách người dùng, kiểm tra thông tin đăng nhập/mật khẩu, lưu bối cảnh bảo mật và sử dụng lại chúng. Bối cảnh bảo mật ở đây được hiểu là một tập hợp các tham số nhận dạng duy nhất người dùng (tối thiểu đây là thông tin đăng nhập, mật khẩu và mã định danh phiên).

Hãy xem xét một ví dụ về việc thực hiện bảo vệ bằng mật khẩu đơn giản nhất. Hãy tạo một tập tin logon.php

Khi bạn nhấp vào nút “đăng nhập”, dữ liệu biểu mẫu sẽ được gửi đến máy chủ, nơi tập lệnh sẽ kiểm tra thông tin đăng nhập và mật khẩu đã nhập và nếu chúng tương ứng bằng “admin” và “megaPass”, nó sẽ hiển thị một thông báo cho phép đăng nhập. Nếu thông tin đăng nhập hoặc mật khẩu không chính xác, người dùng sẽ thấy thông báo cảnh báo.

Hạn chế đầu tiên của tập lệnh này: truyền dữ liệu bằng phương thức GET. Khi sử dụng phương pháp này, dữ liệu được truyền trực tiếp đến địa chỉ và do đó có thể nhìn thấy ngay cả bằng mắt thường. Ví dụ: nếu bạn nhập đúng tên người dùng và mật khẩu, bạn sẽ thấy trên thanh địa chỉ

Http://localhost/logon.php?login=admin&passwd=megaPass

Hạn chế thứ hai: tên người dùng và mật khẩu được mã hóa cứng trực tiếp vào mã. Điều này có nghĩa là để thêm người dùng mới, bạn sẽ cần phải liên tục thay đổi mã tệp. Chỉ cần tưởng tượng tệp sẽ lớn như thế nào nếu bạn có ít nhất một nghìn người dùng đã đăng ký trên trang web của mình... Danh sách người dùng tốt nhất nên được lưu trữ trong một tệp riêng biệt hoặc tốt hơn là trong cơ sở dữ liệu, bởi vì... Kẻ tấn công đánh cắp một tập tin dễ dàng hơn nhiều so với việc trích xuất nội dung nào đó từ cơ sở dữ liệu.

Hạn chế thứ ba: kết quả đăng nhập của người dùng không được ghi nhớ, tức là. Chỉ cần làm mới trang và bạn sẽ được yêu cầu nhập lại mật khẩu của mình.

Vì vậy, chúng ta hãy xem xét các cách để loại bỏ những thiếu sót này.

Cách dễ nhất để ẩn dữ liệu được truyền là sử dụng phương thức truyền POST. Trong trường hợp này, chính trình duyệt (ẩn với người dùng) sẽ chuyển tất cả dữ liệu cần thiết đến máy chủ và nó chỉ có thể bị chặn bởi các chương trình đặc biệt từ kho vũ khí của các chuyên gia CNTT, lập trình viên hoặc tin tặc.

Như đã đề cập ở trên, danh sách người dùng phải được lưu trữ riêng biệt. Hãy tạo một bảng trong cơ sở dữ liệu thử nghiệm:

TẠO BẢNG `smplusers` (
`user_id` int(11) NOT NULL auto_increment,
`user_name` varchar(50) KHÔNG NULL,
`user_login` varchar(50) KHÔNG NULL,
`user_password` varchar(50) KHÔNG NULL,
`reg_date` ngày giờ KHÔNG NULL,
KHÓA CHÍNH (`user_id`)
)

và thêm một số hồ sơ người dùng vào đó:

CHÈN VÀO smplUsers
(tên người dùng, người dùng_login, người dùng_password, reg_date)
giá trị
("Ivanov I.I.", "ivanov-i-i", "pass1", NOW()),
("Petrov P.P.", "petrovich", "pass2", NOW()),
("Sidorov S.S.", "sidorov", "pass3", NOW())

Xin lưu ý rằng toán tử INSERT cho phép thêm nhiều bản ghi vào bảng cùng một lúc và dữ liệu được liệt kê theo các khối được phân tách bằng dấu phẩy.

Bây giờ hãy thay đổi logon.php để tên người dùng và mật khẩu được kiểm tra chính xác trực tiếp trong cơ sở dữ liệu:







Bây giờ thông tin đăng nhập và mật khẩu được truyền đi một cách bí mật và rất dễ dàng thay đổi thông tin đăng nhập bằng cách chỉnh sửa bảng trong cơ sở dữ liệu. Bước cuối cùng vẫn là - hướng dẫn máy chủ ghi nhớ thực tế đăng ký. Cách dễ nhất để làm điều này là sử dụng cơ chế phiên. Hãy thực hiện những thay đổi cần thiết:



...

Máy chủ bây giờ sẽ ghi nhớ từng người dùng đã đăng nhập thành công và sẽ hiển thị thông báo chào mừng vào lần làm mới trang tiếp theo.

Tập lệnh này chỉ là một ví dụ về tổ chức bảo vệ bằng mật khẩu, mặc dù là một tập lệnh có đầy đủ chức năng. Bạn có thể biến nó thành một mẫu có giá trị thực tế bằng cách thêm xác minh dữ liệu đầu vào, chức năng mã hóa, khôi phục mật khẩu, kết thúc phiên, v.v.

Tôi quyết định mô tả các cách để bảo vệ một phần trang web bằng mật khẩu. Chủ đề này thực sự khá lớn nên lần đầu tiên tôi sẽ giới hạn ở việc ủy ​​quyền php+mysql.

Câu hỏi đầu tiên thường được đặt ra là làm thế nào để đóng thư mục chứa các tập lệnh quản trị bằng mật khẩu. Trong trường hợp này, không cần rườm rà - một hoặc nhiều quản trị viên có các quyền như nhau và tính cách hiếm khi thay đổi. Cách dễ nhất trong tình huống này là sử dụng ủy quyền máy chủ tiêu chuẩn - đặt các tệp .htaccess và .htpasswd và ghi các tham số cần thiết vào chúng. Rất nhiều điều đã được viết về điều này, vì vậy tôi sẽ không nói bất cứ điều gì đặc biệt mới.

Tôi sẽ thêm hai điều. Đầu tiên là nơi đặt tệp .htpasswd. Bằng thực nghiệm, tôi phát hiện ra rằng, ví dụ: nếu đường dẫn đến tài liệu có thông báo lỗi (ErrorDocument) được ghi liên quan đến biến hệ thống DocumentRoot. Nhưng đường dẫn đến tệp mật khẩu (UserFile) được ghi tương ứng với ServerRoot. Theo như tôi hiểu, bạn không thể đặt .htpasswd phía trên ServerRoot - không nhận được "../". Tất cả điều này được thực hiện để bạn có thể đặt một tệp có mật khẩu, chẳng hạn như một cấp trên thư mục gốc của trang web, để không có quyền truy cập vào tệp từ mạng.

Thứ hai là tập lệnh có thể tìm ra ai đang mở nó và mật khẩu: các biến $PHP_AUTH_USER và $PHP_AUTH_PW.

Nhược điểm chính của phương pháp này là máy chủ không thể chặn việc đoán mật khẩu (sau nhiều lần đăng nhập không thành công, người dùng được yêu cầu đợi một hoặc hai giờ và trong thời gian này, các cuộc gọi từ địa chỉ IP của anh ta sẽ bị bỏ qua). Điều này được viết trong tài liệu chính thức của Apache.

Một nhược điểm khác là cần phải ghi lại các tệp có mật khẩu khi xóa người dùng hoặc giới thiệu mật khẩu mới. Nhưng nếu điều này xảy ra không thường xuyên thì phương pháp này là khá đủ và bạn sẽ không phải lo lắng về việc viết cơ chế ủy quyền.

Tự động hóa ủy quyền

Điều này là cần thiết không chỉ để đơn giản hóa công việc với số lượng lớn người dùng và doanh thu cao của họ. Nếu bạn cần lưu giữ thông tin bổ sung về người dùng hoặc bạn cần phân biệt quyền linh hoạt, tốt hơn hết bạn nên chuyển quyền vào cơ sở dữ liệu.

Mỗi trang của một lãnh thổ khép kín bao gồm một tệp có mã sau:

$result = mysql_query(" SELECT * FROM user WHERE login="". preg_replace("/[^w_-]/","",$PHP_AUTH_USER). "" AND pass="". md5($PHP_AUTH_PW) " ""); if (@mysql_num_rows($result)!=1) ( header("WWW-Authenticate: Basic Realm="User Area""); header("HTTP/1.0 401 Unauthorized"); print("Để đăng nhập vào khu vực người dùng ​​của trang web, bạn phải nhập tên người dùng và mật khẩu của mình."); exit(); ); $user_row = mysql_fetch_array($result);

Ở dòng đầu tiên, tất cả các ký tự ngoại trừ chữ cái, số, dấu gạch ngang và dấu gạch dưới đều bị xóa khỏi thông tin đăng nhập. Sau đó, số lượng hàng nhận được sẽ được kiểm tra và chỉ khi đó là một hàng thì quyền truy cập mới được cấp. Trong các trường hợp khác, người dùng sẽ thấy một cửa sổ trong trình duyệt nhắc bạn nhập thông tin đăng nhập và mật khẩu. Nếu người dùng đăng nhập thành công, chúng tôi có tất cả thông tin về anh ta trong mảng $user_row.

Tất nhiên, ví dụ tôi đưa ra có một số thiếu sót đáng kể. Đừng viết lại từng cái một để không trở thành nạn nhân của những nỗ lực đoán mật khẩu, bởi vì
1. ở đây không có biện pháp bảo vệ chống lại sự lựa chọn
2. Nếu bảng người dùng lớn, khi đoán mật khẩu, kẻ tấn công rất có thể sẽ áp đảo cơ sở dữ liệu

Và phương pháp cuối cùng hôm nay là lưu trữ dữ liệu được mã hóa trong cookie.

Có một tập lệnh để đăng nhập, phần còn lại bao gồm mã chỉ cho phép bạn tiếp tục các hành động trong một khu vực kín - nếu cookie hết hạn hoặc anh ta đăng xuất khỏi đó, bạn sẽ phải quay lại trang đăng nhập.

Tập lệnh đầu vào sẽ kiểm tra thông tin đăng nhập và mật khẩu và cấp hai cookie. Trong trường hợp đầu tiên - thông tin đăng nhập, để xác định ngay người dùng (trong cơ sở dữ liệu, trường đăng nhập tất nhiên là khóa duy nhất hoặc thậm chí). Cookie thứ hai chứa hàm băm về thời gian đăng nhập và mật khẩu (để đảm bảo bí mật hoàn toàn, tôi thêm chữ cái “Y” vào những dòng này - khi đó gần như không thể tìm thấy hàm băm :).

Tất cả các chương trình khác đều có mã thực hiện những việc sau. Đưa ra yêu cầu tới cơ sở dữ liệu - chọn dòng có thông tin đăng nhập nhận được. Từ dòng này, nó lấy trường “log_time” và mật khẩu rồi tạo hàm băm từ chúng, như được mô tả ở trên. So sánh nó với những gì nó nhận được và nếu chúng khớp, sẽ tạo ra một cookie băm mới, một lần nữa, từ mật khẩu, thời gian và chữ cái "Y" và thực hiện truy vấn tới cơ sở dữ liệu "CẬP NHẬT người dùng SET log_time='...' WHERE đăng nhập ='$ cookie_login'".

if (isset($HTTP_COOKIE_VARS[$cookie_login]) && isset($HTTP_COOKIE_VARS[$cookie_code])) ( $login = $HTTP_COOKIE_VARS[$cookie_login]; $code = $HTTP_COOKIE_VARS[$cookie_code]; $result = mysql_query("SELECT date_format(log_date,"%Y%m%d%H%i%s") dưới dạng log_date1,pass,uid TỪ người dùng WHERE email="$login" AND log_date>"DATE_SUB(NOW(),INTERVAL 15 PHÚT)"" ); if (!mysql_error() && @mysql_num_rows($result)==1) ( $log_time0 = time(); $log_time1 = date("YmdHis", $log_time0); $log_time2 = date("Y-m-d H:i :s", $log_time0); $current_user = mysql_fetch_array($result); if (md5($current_user["pass".$current_user["log_date1".$md5letter) == $code) ( mysql_query("UPDATE người dùng SET log_date="$log_time2" WHERE uid=".$current_user["uid"]); setcookie($cookie_code, md5($current_user["pass"].$log_time1.$md5letter), time()+900, $site_path); $auth = true; ) else unset($current_user); ); );

Một lần nữa, ở đây không có biện pháp bảo vệ nào khỏi việc lựa chọn và tấn công vào máy chủ (nhân tiện, ở đây bạn có thể viết địa chỉ IP của người dùng thay vì chữ cái “Y” - vì vậy, chẳng hạn như hàng xóm văn phòng không thể lấy một tệp có tên cookie và đăng nhập từ máy tính của anh ấy).

Mật khẩu cho trang. Phần 2. Chặn tuyển dụng

Lần trước khi tôi đăng vấn đề này, họ đã đá tôi ngay tại chỗ, nói rằng việc chặn như vậy có thể làm hỏng máy chủ.

Nhưng trước tiên, về việc chặn hồi phục. Những điều tầm thường, nhưng vẫn vậy. Mật khẩu gồm mười ký tự bao gồm các chữ cái và số Latinh có nghĩa là có rất nhiều tùy chọn. Nếu bạn đoán mật khẩu 1.000.000 lần mỗi giây thì sẽ mất vài nghìn năm. Nhưng vì gobbledygook như vậy rất khó nhớ nên chúng ta thường tạo mật khẩu bằng những từ có ý nghĩa. Một vài năm trước, hóa ra hầu hết mật khẩu đều có thể đoán được bằng cách sử dụng từ điển 10.000 từ. Có một thời điểm, một loại sâu (một loại virus tương tự) xuất hiện trên mạng, chúng leo lên các máy chủ Unix, lợi dụng các lỗ hổng bảo mật của chúng và lấy trộm mật khẩu của những người dùng đặc quyền bằng cách sử dụng... từ điển chính tả hệ thống Unix. Không cần phải mang theo bất cứ thứ gì!

Mỗi người dùng, cho đến khi nhập đúng thông tin đăng nhập và mật khẩu, đều bị coi là một hacker độc ác. Chúng tôi phải giải quyết vấn đề gì khi người dùng nhập nội dung không chính xác?
hay quên (đối với điều này, các trang web tử tế có biểu mẫu “quên mật khẩu” để gửi cùng mật khẩu này đến email đã nhập trong cài đặt hệ thống)
chiều chuộng (“vì tôi không quan tâm”)
chọn mật khẩu bằng từ điển (khả năng lựa chọn thành công rất cao, vì vậy bạn cần phải đóng nó, đặc biệt nếu trang web có tính chất thương mại)
Tấn công DoS (để không làm quá tải máy chủ, bạn cần hạn chế tối đa các hành động mà script sẽ thực hiện trong trường hợp này)

Tôi đã suy nghĩ rất lâu về việc làm thế nào tôi có thể gây ra tình trạng quá tải trên máy chủ nếu cơ chế bảo vệ dựa trên các tệp. Hóa ra nó lại dễ dàng (một câu hỏi khác là nó sẽ tốn bao nhiêu tiền). Vì vậy, giả sử máy chủ sẽ không thể xử lý nó nếu tập lệnh cố mở tệp để ghi 1000 lần một giây và ghi dữ liệu vào chúng. Vì sau 5 lần đăng nhập không thành công, người dùng sẽ ngay lập tức bị từ chối truy cập (không có dữ liệu nào được ghi vào tệp), cần phải tìm 200 IP duy nhất để liên hệ năm lần. Điều đó là có thể. Chúng tôi treo một biểu ngữ html với năm thẻ trong thanh cuộn biểu ngữ:

Người dùng ngay lập tức thực hiện năm yêu cầu, máy chủ ghi vào tệp năm lần (nhân tiện, trong một số trình duyệt, một cửa sổ để nhập thông tin đăng nhập và mật khẩu của bạn có thể bật lên). Bạn có thể tạo một trang HTML với năm hình ảnh như vậy và chèn chính trang đó qua iframe vào trang web bạn đang truy cập (thông qua iframe - để không tìm thấy trường người giới thiệu. Không chắc là dịch vụ hỗ trợ miễn phí hosting sẽ xử lý những việc như tìm kiếm các tệp nhật ký để tìm kiếm người giới thiệu). Tất nhiên, những ví dụ mà tôi đưa ra là rất xa vời, nhưng thực tế là người ta có thể lợi dụng lỗ hổng như vậy trong hệ thống đã được chứng minh. Nhân tiện, điều gì đó tương tự đã xảy ra rồi.

Nhưng tôi vẫn sẽ cung cấp cho bạn phương pháp này - tôi đã viết nó một cách vô ích, hay sao? Nhân tiện, nó có thể được sử dụng mà không cần lo ngại nhiều về số lượng địa chỉ hạn chế (ví dụ: đối với mạng cục bộ của công ty) bằng cách đặt tệp .htaccess trong thư mục có nội dung sau:

lệnh từ chối, cho phép
tư chôi tât cả
cho phép từ xxx.xxx.xxx

Và đây là mã chương trình:

lỗi $ = 0; $fn = "bỏ qua/". preg_replace("[^d.]", "", $REMOTE_ADDR. ".". $HTTP_FORWARDED_FOR); if (is_file($fn)) ( if (filectime($fn)< time()-3600) unlink($fn); else $errors = fread(fopen($fn, "r"), 2); }; if ($errors>5) ( print ("Truy cập đã bị đóng. Vui lòng quay lại sau một giờ."); exit(); ); // ở đây kết nối với máy chủ cơ sở dữ liệu được thiết lập. để không đụng chạm vô ích nếu người dùng ngay lập tức bị “đánh”. $result = mysql_query("SELECT * FROM user WHERE login="". preg_replace("/[^w_-]/", "", $PHP_AUTH_USER). "" AND pass="". md5($PHP_AUTH_PW) " ""); if (@mysql_num_rows($result)!=1) ( header("WWW-Authenticate: Basic Realm="Secret Area""); header("HTTP/1.0 401 Unauthorized"); print ("Cần có sự cho phép"); fwrite (fopen($fn, "w"), ++$errors); exit(); ); $current_user = mysql_fetch_array($result); mysql_free_result($result); Tuy nhiên, thật tội lỗi khi làm việc với các tập tin nếu có cơ sở dữ liệu. Câu nói đùa. Đối với các ủy quyền không thành công, chúng tôi tạo một bảng: CREATE TABLE unauth (username VARCHAR(64) NOT NULL, pass VARCHAR(64) NOT NULL, ip VARCHAR(255), logintime TIMESTAMP) Và thay vì truy cập các tệp, chúng tôi làm việc với cơ sở dữ liệu. $errors = @mysql_result(mysql_query("SELECT count(username) as false FROM unauth WHERE logintime>DATE_SUB(NOW(),INTERVAL 1 GIỜ) VÀ ip="$REMOTE_ADDR""),0); nếu (mysql_error()) die(mysql_error()); if ($errors>5) ( print ("Quyền truy cập đã bị đóng. Vui lòng quay lại sau một giờ."); exit(); ); $result = mysql_query("SELECT * FROM user WHERE login="". preg_replace("/[^w_-]/", "", $PHP_AUTH_USER). "" AND pass="". md5($PHP_AUTH_PW) " ""); if (@mysql_num_rows($result)!=1) ( header("WWW-Authenticate: Basic Realm="Secret Area""); header("HTTP/1.0 401 Unauthorized"); print ("Cần có sự cho phép"); mysql_query ("XÁC NHẬN VÀO unauth (tên người dùng, pass, ip) GIÁ TRỊ ("$PHP_AUTH_USER", "$PHP_AUTH_PW", "$REMOTE_ADDR $HTTP_X_FORWARDED_FOR")"); exit(); ); $current_user = mysql_fetch_array($result); mysql_free_result($result);

Việc có lưu trữ hồ sơ cũ để thống kê hay không là quyết định kinh doanh. Nếu có bất cứ điều gì, chúng có thể bị xóa bằng cách thực hiện yêu cầu sau trước khi ủy quyền:

XÓA TỪ unauth WHERE thời gian đăng nhập