Mã đăng nhập python
Python là một ngôn ngữ lập trình mạnh mẽ, dễ học. Nó có cấu trúc dữ liệu cấp cao hiệu quả và cách tiếp cận đơn giản nhưng hiệu quả đối với lập trình hướng đối tượng. Cú pháp tao nhã và kiểu gõ động của Python, cùng với bản chất diễn giải của nó, làm cho nó trở thành ngôn ngữ lý tưởng để viết kịch bản và phát triển ứng dụng nhanh chóng trong nhiều lĩnh vực trên hầu hết các nền tảng Trình thông dịch Python và thư viện chuẩn mở rộng có sẵn miễn phí ở dạng nguồn hoặc nhị phân cho tất cả các nền tảng chính từ trang web Python, https. //www. con trăn. org/, và có thể được phân phối tự do. Trang web tương tự cũng chứa các bản phân phối và con trỏ tới nhiều mô-đun, chương trình và công cụ Python miễn phí của bên thứ ba và tài liệu bổ sung Trình thông dịch Python dễ dàng mở rộng với các hàm và kiểu dữ liệu mới được triển khai trong C hoặc C++ (hoặc các ngôn ngữ khác có thể gọi được từ C). Python cũng phù hợp làm ngôn ngữ mở rộng cho các ứng dụng có thể tùy chỉnh Hướng dẫn này giới thiệu cho người đọc một cách không chính thức các khái niệm và tính năng cơ bản của ngôn ngữ và hệ thống Python. Sẽ rất hữu ích khi có một trình thông dịch Python tiện dụng cho trải nghiệm thực hành, nhưng tất cả các ví dụ đều độc lập, vì vậy hướng dẫn cũng có thể được đọc ngoại tuyến Để biết mô tả về các đối tượng và mô-đun tiêu chuẩn, hãy xem. đưa ra một định nghĩa chính thức hơn về ngôn ngữ. Để viết các phần mở rộng trong C hoặc C++, hãy đọc và. Ngoài ra còn có một số cuốn sách chuyên sâu về Python Hướng dẫn này không cố gắng toàn diện và bao gồm mọi tính năng đơn lẻ hoặc thậm chí mọi tính năng thường được sử dụng. Thay vào đó, nó giới thiệu nhiều tính năng đáng chú ý nhất của Python và sẽ cho bạn ý tưởng hay về hương vị và phong cách của ngôn ngữ. Sau khi đọc nó, bạn sẽ có thể đọc và viết các mô-đun và chương trình Python, đồng thời bạn sẽ sẵn sàng tìm hiểu thêm về các mô-đun thư viện Python khác nhau được mô tả trong Trong phần này, chúng ta sẽ tìm hiểu những cách làm nào để tạo ra một hệ thống đăng nhập người dùng cho ứng dụng Để giúp các bạn dễ theo dõi, sau đây là danh sách các bài viết trong chuỗi bài hướng dẫn này
Bạn có thể truy cập mã nguồn cho phần này tại GitHub Trước đây, chúng ta đã tạo ra một biểu mẫu đăng nhập trong Phần 3 và tìm hiểu cách sử dụng cơ sở dữ liệu trong Phần 4. Tiếp theo, chúng ta sẽ phân phối các kiến thức đã học trong hai phần trước để tạo ra một hệ thống đăng nhập thông tin người dùng đơn giản Mã băm cho mật khẩu của người dùng (Password hashing)Trong Phần 4, chúng ta đã định nghĩa trường Trong các thư viện của Flask, có một gói cung cấp các phương thức để làm việc với tên băm là Werkzeug. Nếu để ý quá trình cài đặt Flask, bạn có thể thấy tên của gói này ở đâu trong các thông báo mà Flask in ra trong suốt quá trình cài đặt bởi vì gói này là một trong những thành phần quan trọng nhất của Flask. Cũng vì lý do đó, Werkzeug đã được cài đặt sẵn trong môi trường ảo của bạn ngay từ đầu. Ví dụ sau sẽ minh họa cách tạo hàm băm cho mật mã bằng thư viện Werkzeug 1 2 3 4 >>> từ werkzeug. bảo mật nhập generate_password_hash >>> hash = generate_password_hash('foobar') >>> băm 'pbkdf2. sha256. 150000$3HUtwgW8$39ae9f2f4925661c5cf9cfa04842b04b874730f87739f65316eb6e85f4678c28' Trong ví dụ trên, chuỗi mật mã “foobar” ban đầu được chuyển đổi thành một chuỗi mã dài bằng các phương thức mã hóa không thể đảo ngược, có nghĩa là bạn sẽ không thể chuyển đổi chuỗi mã này thành mã ban đầu mật mã bằng . Too this call is hash (hash). Và hơn thế nữa, nếu bạn tiếp tục băm một mật mã nhiều lần, bạn sẽ nhận được nhiều kết quả khác nhau. Vì vậy, bạn sẽ không thể xác định được hai người dùng có cùng mã mật hay không nếu chỉ nhìn vào giá trị băm từ mật mã của họ Để xác thực mã mật khẩu (xác minh), chúng ta sử dụng hàm thứ hai từ thư viện Werkzeug như trong ví dụ sau 1 2 3 4 5 >>> từ werkzeug. bảo mật nhập check_password_hash >>> check_password_hash(băm, 'foobar') ĐÚNG VẬY >>> check_password_hash(băm, 'barfoo') Sai Quá trình xác thực sẽ nhận mã mật khẩu do người dùng nhập vào, chuyển đổi thành mã băm và so sánh với mã băm được sinh ra từ mã cấm đầu tiên và được lưu lại trong cơ sở dữ liệu. Nếu mã băm từ mật mã nhập vào giống với mã băm đã được lưu trữ, hàm sẽ trả về Quá trình tạo hàm băm và xác thực mã mật khẩu sẽ được thêm vào hai phương thức mới trong mô hình người dùng như sau ứng dụng/mô hình. py. Tạo mã băm và xác thực mã bảo mật 1 2 3 4 5 6 7 8 9 10 11 12 từ werkzeug. bảo mật nhập generate_password_hash, check_password_hash
.. .
lớp Người dùng(db. Mô hình). . . .
def set_password(self, password): bản thân. password_hash = generate_password_hash(password)
def check_password(self, password): return check_password_hash(self.password_hash, mật khẩu) Với hai phương thức này, một đối tượng người dùng có thể xác thực mã mật khẩu của mình. Sau đây là một ví dụ về cách sử dụng hai phương thức này 1 2 3 4 5 6 >>> u = Người dùng(username='thai', email='[email protected]') >>> u. set_password('mypassword') >>> u. check_password('anotherpassword') Sai >>> u. check_password('mypassword') ĐÚNG VẬY Giới thiệu về Flask-LoginTrong phần này, chúng ta cũng sẽ tìm hiểu thêm một Flask thư viện mở rộng rất phổ biến là Flask-Login Thư viện mở rộng này quản lý trạng thái đăng nhập của người dùng. Nhờ đó, hệ thống có thể ghi nhớ các thông tin về người dùng đã đăng nhập trong một phiên làm việc của viện và cho phép họ truy cập các trang Web yêu cầu người dùng phải đăng nhập. Nó cung cấp chức năng “Remember me” để người dùng vẫn giữ trạng thái đăng nhập ngay cả khi họ đã đóng trình duyệt. Để bắt đầu phần này, chúng ta hãy cài đặt Flask-Login trong môi trường ảo của bạn 1 (myenv) $ pip3 install flask-login Tương tự như các thư viện mở rộng khác, Flask-Login phải được khởi tạo ngay sau khi có thể ứng dụng trong tệp app/__init__. py as after ứng dụng/__init__. py. Khởi tạo Flask-Đăng nhập 1 2 3 4 5 6 7 8 .. . từ flask_login nhập Trình quản lý đăng nhập
app = Flask(__name__) .. . đăng nhập = Trình quản lý đăng nhập(ứng dụng)
.. . Điều chỉnh mô hình dữ liệu người dùng (User) cho Flask-LoginFlask-Login thư viện sẽ làm việc với người dùng mô hình dữ liệu với một số thuộc tính và phương thức định sẵn. Đây là một thiết kế hay bởi vì nếu các thuộc tính và phương thức này được cung cấp trong mô hình dữ liệu, Flask-Login sẽ thực hiện đúng theo yêu cầu bất chấp các điều kiện khác nhau. Ví dụ như nó có thể hoạt động với người dùng mô hình dữ liệu từ bất kỳ hệ thống cơ sở dữ liệu nào Sau đây là bốn yêu cầu của Flask-Login với người dùng mô hình dữ liệu
Chúng ta có thể viết mã cho yêu cầu này một cách dễ dàng. Nhưng bởi vì những yêu cầu này tương đối tổng quát, Flask-Login cung cấp một lớp mixin được gọi là ứng dụng/mô hình. py. mixin layer for user in Flask-Login 1 2 3 4 5 .. . từ flask_login nhập UserMixin
lớp Người dùng(UserMixin, db.Mô hình). . . . Hàm tải thông tin người dùngFlask-Login theo dõi trạng thái của những người dùng đã đăng nhập bằng cách lưu các ID tương ứng trong các phiên làm việc (phiên người dùng) – một vùng lưu trữ được xác định cho mỗi người dùng đang kết nối vào ứng dụng. Mỗi khi người dùng đăng nhập truy cập một trang mới trong ứng dụng, Flask-Login sẽ lấy ID của người dùng đó từ phiên làm việc và tải dữ liệu về người dùng đó vào bộ nhớ Bởi vì Flask-Login không trực tiếp làm việc với cơ sở dữ liệu, nó cần có sự trợ giúp của các thành phần khác nhau trong ứng dụng để tìm kiếm và tải dữ liệu về người dùng. Vì vậy, thư viện này cần có một chức năng hỗ trợ để tải thông tin người dùng. Hàm này sẽ tìm kiếm và tải các thông tin về người dùng từ cơ sở dữ liệu dựa trên Id của người dùng đó. Chúng ta sẽ thêm mã cho chức năng này vào mô-đun ứng dụng/mô hình. py as after ứng dụng/mô hình. py. Hàm tải dữ liệu người dùng cho Flask-Login 1 2 3 4 5 6 từ ứng dụng nhập đăng nhập .. .
@đăng nhập. user_loader def load_user(id): trả lại Người dùng. truy vấn. lấy(int(id)) Chúng ta sẽ đăng ký chức năng này với Flask-Login qua decorator Sau các bước chuẩn bị ở trên, chúng ta có thể quay lại với hàm hiển thị đăng nhập mà chúng ta đã tạo ra trong Phần 3. Lưu ý là tại thời điểm này, hàm này không có chức năng đăng nhập thực tế mà chỉ đưa ra một thông báo nhờ hàm ứng dụng/tuyến đường. py. Hàm hiển thị đăng nhập 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 .. . từ flask_login nhập current_user, login_user từ ứng dụng. mô hình nhập Người dùng
.. .
@ứng dụng. tuyến đường('/đăng nhập', methods=['GET', 'POST']) def đăng nhập(). if current_user. is_authenticated. trả lại chuyển hướng(url_for('index')) biểu mẫu = Biểu mẫu đăng nhập() nếu biểu mẫu. validate_on_submit(). người dùng = Người dùng. truy vấn. filter_by(tên người dùng=biểu mẫu . .tên người dùng. dữ liệu). đầu tiên() nếu người dùng là Không có or not user.check_password(biểu mẫu. mật khẩu. dữ liệu). flash('Tên người dùng hoặc mật khẩu không hợp lệ') return redirect(url_for('login')) login_user(user, remember=form.nhớ_tôi. dữ liệu) trả lại chuyển hướng(url_for('index')) return render_template('đăng nhập. html', tiêu đề='Đăng nhập', form=form) Trong hai dòng lệnh đầu tiên của hàm Trước đây, chúng tôi cũng sử dụng hàm Nếu chúng tôi tìm thấy một người dùng từ cơ sở dữ liệu có cùng tên người dùng như trong biểu mẫu đăng nhập, chúng tôi sẽ tiến hành các bước tiếp theo là kiểm tra mã mật khẩu. Quá trình này được thực hiện bằng cách sử dụng hàm Nếu tên người dùng và mật khẩu tương ứng đúng, chúng ta sẽ gọi một hàm trong thư viện Flask-Login là Sau khi người dùng đăng nhập thành công, chúng ta sẽ chuyển (chuyển hướng) người dùng đến trang chủ Đăng xuất (Log Out)Để hoàn tất quá trình xuất nhập, chúng ta cũng phải cung cấp chức năng đăng xuất (đăng xuất) ra khỏi ứng dụng. Chúng ta sẽ sử dụng một chức năng khác của thư viện Flask-Login được gọi là ứng dụng/tuyến đường. py. Hàm hiển thị Đăng xuất 1 2 3 4 5 6 7 8 9 .. . từ flask_login nhập đăng xuất_user
.. .
@ứng dụng. tuyến đường('/logout') def đăng xuất(). logout_user() return redirect(url_for('index')) Chúng ta cũng cần thay thế liên kết Đăng nhập trong thay đổi hướng bằng liên kết Đăng xuất sau khi người dùng đăng nhập thành công. Chúng ta sẽ làm điều này bằng cách cập nhật cơ sở tập tin. html ứng dụng/mẫu/cơ sở. html. Hiển thị liên kết đăng nhập và đăng xuất trên thanh định hướng 1 2 3 4 5 6 7 8 9 Blog của tôi {% nếu current_user. is_anonymous %} {% khác %} {% endif %} Như đã nói ở trên, thuộc tính Flask-Login có một chức năng rất hữu ích để yêu cầu người dùng đăng nhập nếu họ muốn truy cập vào một số trang định sẵn trong ứng dụng. Nếu người dùng không đăng nhập để tìm cách truy cập các trang này, Flask-Login sẽ tự động chuyển họ đến trang đăng nhập và quay lại trang được yêu cầu truy cập sau khi người dùng đã đăng nhập thành công Để sử dụng chức năng này, Flask-Login cần biết hàm hiển thị cho quá trình đăng nhập. Chúng ta sẽ thay đổi file app/__init__. py to make this thing 1 2 3 .. . đăng nhập = Trình quản lý đăng nhập(ứng dụng) đăng nhập. login_view = 'đăng nhập' Giá trị ‘ Chúng ta sẽ sử dụng decorator ứng dụng/tuyến đường. py. người trang trí 1 2 3 4 5 6 7 từ flask_login nhập đăng nhập_required
@ứng dụng. tuyến đường('/') @ứng dụng. tuyến đường('/index') @login_required def index(). . . . Chúng ta cần làm một việc nữa là thêm tính năng trở về trang mà người dùng yêu cầu truy cập sau khi đã đăng nhập thành công. Khi một người dùng chưa đăng nhập truy cập vào một trang được hiển thị bởi một hàm hiển thị đã được bảo vệ bởi trang trí Sau đây là đoạn mã để đọc và xử lý tham số ứng dụng/tuyến đường. py. Chuyển hướng đến trang tại “tiếp theo” 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 từ bình nhập yêu cầu từ werkzeug. url nhập url_ phân tích cú pháp
@ứng dụng. tuyến đường('/đăng nhập', methods=['GET', 'POST']) def đăng nhập(). . . . nếu biểu mẫu. validate_on_submit(). người dùng = Người dùng. truy vấn. filter_by(tên người dùng=biểu mẫu . .tên người dùng. dữ liệu). đầu tiên() nếu người dùng là Không có or not user.check_password(biểu mẫu. mật khẩu. dữ liệu). flash('Tên người dùng hoặc mật khẩu không hợp lệ') return redirect(url_for('login')) login_user(user, remember=form.nhớ_tôi. dữ liệu) trang_tiếp theo = yêu cầu. đối số. lấy('tiếp theo') nếu không trang_tiếp theo hoặc url_parse(next_page).netloc . = ''. trang_tiếp theo = url_for('index') trả lại chuyển hướng(trang tiếp theo) . . . Ngay sau khi hàm
Trường hợp đầu và trường hợp thứ hai đối tượng dễ hiểu. Trường hợp thứ ba Đảm bảo chắc chắn cho ứng dụng được bảo mật hơn. Một người có ý định có thể đặt một URL dẫn đến một trang Web nguy hiểm vào trong tham số tiếp theo, vì như vậy, ứng dụng chỉ chuyển hướng khi gặp đường dẫn tương đối, nhờ đó đảm bảo rằng mọi trang Web đều được chuyển đến đồng đều . Để phân biệt các URL tương đối và đầy đủ, chúng ta sử dụng hàm Bạn còn nhớ trong Phần 2 chúng ta đã tạo ra một người dùng giả để mô phỏng hệ thống đăng nhập người dùng khi thiết kế trang chủ khi chúng ta chưa có hệ thống này hay không? . Thay vì người dùng giả, chúng ta có thể sử dụng biến ứng dụng/mẫu/chỉ mục. html. Truyền thông tin về người dùng đang đăng nhập vào mẫu 1 2 3 4 5 6 7 8 {% mở rộng "cơ sở. html" %}
{% chặn nội dung %} Xin chào, {{ current_user. tên tài khoản }}. {% cho bài đăng trong bài viết %} {% endfor %} {% chặn kết thúc %} Chúng ta cũng có thể loại bỏ tham số ứng dụng/tuyến đường. py. Không truyền tham số 1 2 3 4 5 @ứng dụng. tuyến đường('/') @ứng dụng. tuyến đường('/index') def index(). . . . return render_template("index. html", tiêu đề='Trang chủ', posts=posts) Đây là lúc để kiểm tra chức năng đăng nhập và đăng xuất làm việc thế nào. Bởi vì chúng ta chưa có chức năng đăng ký người dùng, cách duy nhất để thêm người dùng vào cơ sở dữ liệu là sử dụng chế độ dòng lệnh của Python. Chúng ta hãy bắt đầu bằng cách gọi 1 2 3 4 >>> u = Người dùng(username='thai', email='[email protected]') >>> u. set_password('thaipham') >>> db. phiên. thêm(u) >>> db. phiên. cam kết() Bây giờ, nếu bạn chạy ứng dụng và truy cập địa chỉ http. //máy chủ cục bộ. 5000/ hoặc http. //máy chủ cục bộ. 5000/index, ứng dụng sẽ lập tức chuyển hướng bạn đến trang đăng nhập. Và sau khi đã nhập các thông tin về người dùng mà bạn đã thêm vào trong cơ sở dữ liệu, bạn sẽ được chuyển hướng đến trang mà bạn yêu cầu và một lời chào mừng sẽ được hiển thị Đăng ký người dùngChức năng cuối cùng mà chúng ta sẽ xây dựng trong bài viết hôm nay là biểu mẫu đăng ký để người dùng mới có thể đăng ký và đăng nhập vào ứng dụng. Chúng ta sẽ cần tạo ra một lớp biểu mẫu web mới trong ứng dụng/biểu mẫu. py ứng dụng/biểu mẫu. py. biểu mẫu đăng ký người dùng 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 từ flask_wtf nhập FlaskForm từ wtforms nhập StringField, PasswordField, BooleanField, SubmitField từ wtforms. trình xác thực nhập Lỗi xác thực, Bắt buộc dữ liệu, Email, EqualTo từ ứng dụng. mô hình nhập Người dùng
.. .
class Mẫu đăng ký(FlaskForm): tên người dùng = StringField('Username', validators=[DataRequired()]) email = StringField('Email', validators=[DataRequired(), Email()]) mật khẩu = Trường mật khẩu('Password', validators=[DataRequired()]) password2 = Trường mật khẩu( 'Lặp lại mật khẩu', trình xác thực=[DataRequired(), EqualTo('password')]) gửi = Trường gửi('Register')
def validate_username(self, username): người dùng = Người dùng. truy vấn. filter_by(tên người dùng=tên người dùng . .dữ liệu). đầu tiên() nếu người dùng có không None: nâng cao Lỗi xác thực('Vui lòng sử dụng tên người dùng khác. ')
def validate_email(self, email): người dùng = Người dùng. truy vấn. filter_by(email=email . .dữ liệu). đầu tiên() nếu người dùng có không None: tăng Lỗi xác thực('Vui lòng sử dụng một email khác . ') Có vài điểm đáng lưu ý liên quan đến việc kiểm tra dữ liệu đầu vào trong biểu mẫu mới này. Đầu tiên, chúng ta thêm một biến kiểm tra dữ liệu (validator) thứ hai bên ngoài Tiếp theo, chúng ta cũng sẽ lướt theo quy ước chung của các biểu mẫu đăng ký là yêu cầu người dùng nhập mật mã hai lần để tránh trạng thái nhập sai mật mã bên ngoài ý muốn. Vì vậy, chúng tôi sử dụng hai trường Và cuối cùng, chúng ta cũng có thêm hai hàm mới gọi là Để hiển thị biểu mẫu này, chúng ta cần xây dựng một mẫu HTML. Chúng ta sẽ đưa template này vào file app/templates/register. html. Chúng ta cũng viết mã cho mẫu này tương tự như cho mẫu đăng nhập ứng dụng/mẫu/đăng ký. html. Mẫu cho biểu mẫu đăng ký người dùng 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 {% mở rộng "cơ sở. html" %}
{% chặn nội dung %} Đăng ký
{{ hình thức. hidden_tag() }}
{{ biểu mẫu. tên tài khoản. nhãn }} {{ biểu mẫu. tên người dùng(size=32) }} {% cho lỗi trong biểu mẫu. tên tài khoản. lỗi %} kiểu="color. đỏ;">[{{ error }}] {% endfor %}
{{ biểu mẫu. e-mail. nhãn }} {{ biểu mẫu. email(size=64) }} {% cho lỗi trong biểu mẫu. e-mail. lỗi %} kiểu="color. đỏ;">[{{ error }}] {% endfor %}
{{ biểu mẫu. mật khẩu mở khóa. nhãn }} {{ biểu mẫu. mật khẩu(size=32) }} {% cho lỗi trong biểu mẫu. mật khẩu mở khóa. lỗi %} kiểu="color. đỏ;">[{{ error }}] {% endfor %}
{{ biểu mẫu. mật khẩu2. nhãn }} {{ biểu mẫu. mật khẩu2(size=32) }} {% cho lỗi trong biểu mẫu. mật khẩu2. lỗi %} kiểu="color. đỏ;">[{{ error }}] {% endfor %}
{{ biểu mẫu. gửi() }}
{% chặn kết thúc %} Chúng ta cũng cần thêm liên kết từ trang đăng nhập đến trang đăng ký để người dùng mới có thể đăng ký với hệ thống như sau ứng dụng/mẫu/đăng nhập. html. Liên kết đến trang đăng ký 1 Người dùng mới? . href="{{ url_for('register') }}">Click to Register! Và cuối cùng, chúng ta cần viết hàm hiển thị cho trang đăng ký trong app/routes. py ứng dụng/tuyến đường. py. Hàm hiển thị cho biểu mẫu đăng ký người dùng 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 từ ứng dụng nhập db từ ứng dụng. biểu mẫu nhập Biểu mẫu đăng ký
.. .
@ứng dụng. tuyến đường('/register', methods=['GET', 'POST']) def đăng ký(). if current_user. is_authenticated. trả lại chuyển hướng(url_for('index')) biểu mẫu = Đơn đăng ký() nếu biểu mẫu. validate_on_submit(). người dùng = Người dùng(username=form.tên người dùng. dữ liệu, email=biểu mẫu . .email. dữ liệu) người dùng. set_password(biểu mẫu. mật khẩu. dữ liệu) db. phiên. thêm(người dùng) db. phiên. cam kết() flash('Xin chúc mừng, bạn hiện là người dùng đã đăng ký. ') trả lại chuyển hướng(url_for('login')) return render_template('register. html', tiêu đề='Đăng ký', form=form) Trong hàm này, chúng ta làm một số công việc theo tuần tự như sau. đảm bảo rằng những người dùng đã đăng ký không thể truy cập trang này (cách xử lý tương tự như khi một người dùng đã đăng nhập tìm cách truy cập trang đã đăng nhập). Tiếp theo, chúng ta sẽ kiểm tra các dữ liệu đã đăng ký có hợp lệ hay không, nếu không có lỗi (được xác nhận thông qua điều kiện Với những thay đổi này, người dùng sẽ có thể tạo tài khoản người dùng, đăng nhập và đăng xuất. Hãy thử tất cả các vấn đề có lỗi để hiểu cách làm việc của mã kiểm tra lỗi mà chúng ta đã thêm vào chương trình. Chúng ta sẽ quay lại với hệ thống xác nhận người dùng và chức năng bổ sung để người dùng có thể đặt lại mật mã trong trường hợp họ đã quên trong một bài viết sau. Nhưng bây giờ, chúng ta hãy chuyển sang phần khác của ứng dụng |