Phân đoạn trong video: - 01:14 Settup dự án - 04:12 “Dính” CORS lần 1 - 06:06 Khái niệm “nguồn gốc” - 11:44 Tạo form và viết API đăng nhập (sử dụng session) - 28:11 “Dính” CORS lần 2 - 44:20 Sử dụng cookies khác domain - 58:38 Ứng dụng của cookies bên thứ 3 - 01:06:50 “Tháng 4 là lời hứa của anh”
Anh chia sẻ cụ thể hơn chút nhé. Khi bị chặn bởi CORS là chặn ở Response bên phía back-end. Trên thực tế Request đó vẫn được Server tiếp nhận xử lý, chỉ là không trả về được Tuy nhiên, khi có Request gửi lên Server mà có Header thì trình duyệt sẽ chặn luôn không cho Server nhận request đó Để làm được điều này, trình duyệt có 1 request có tên là Preflight với method là OPTIONS để thăm dò. Nếu Response header trả về không thỏa mãn thì sẽ không cho phép luôn. ==> Đó cũng là lý do tại sao ở phía back-end phải trả về Response Header CORS ngay sau khi có Request, nếu em để cái này trong 1 Route cụ thể sẽ không thể Pass được CORS với những Request có Header Header Access-Control-Allow-Origin hiểu đơn giản là cho phép Origin, chỉ cần khác Origin --> Block Cấu trúc 1 URL sẽ có 1 khái niệm là Origin bao gồm 3 phần: Scheme + Hostname + Port
Thank you anh đã góp ý, tiện đây em cũng làm rõ một số ý sau ạ: Khi gửi đi một "simple request", tức là với các methods GET, HEAD, POST (là post thì content-type là một trong số application/x-www-form-urlencoded, multipart/form-data, hoặc text/plain), không bao gồm option "credentials: include" hoặc "withCredentials: true" thì khi ấy request không bị chặn (nên không có preflight), server lúc này vẫn tiếp nhận, xử lý và phản hồi (chứ không phải là không trả về được), vì HTTP là "request-response protocol" - tức là luôn có request-response. Lúc này, nếu cross-origin và phản hồi về Access-Control-Allow-Origin khác Origin hiện tại hoặc khác * thì sẽ bị trình duyệt block response (tức là client nhận được response, trình duyệt không cho access thôi). Trường hợp khác, khi gửi các yêu cầu KHÔNG simple, trình duyệt không chặn request đó, mà nó sẽ "tạm dừng" để gửi preflight (request thăm dò với method OPTIONS) lên server trước, khi đó nếu server phản hồi các Headers phù hợp thì request chính mới được gửi đi, ngược lại trình duyệt sẽ block request chính luôn. Với trường hợp "credentials: include" hoặc "withCredentials: true" thì Access-Control-Allow-Origin không sử dụng được wildcard * mà bắt buộc phải là Origin cụ thể. Ngoài ra còn phải trả về thêm Access-Control-Allow-Credentials là "true" nữa, không là sau preflight request chính sẽ bị block. Thật ra việc "để cái này trong 1 Route cụ thể sẽ không thể Pass được CORS" là vì preflight nó là method OPTIONS, để trong route cụ thể mà route đó không khớp method OPTIONS thì preflight sẽ fail, vẫn tới request chính bị block sau đó. Còn nếu, mình viết trong route cụ thể với method OPTIONS và trả về đúng các Headers cần thiết thì vẫn pass được. Chẳng qua việc xử lý preflight trong từng route là không cần thiết, nên thực tế sẽ xử lý ở một nơi là middleware, vừa dễ maintain, vừa xử lý sớm luôn ngay sau khi nhận được request.
@@F8VNOfficial Ok em ơi Đúng như những gì em chia sẻ, trường hợp simple request thì trình duyệt sẽ block response. Cái anh muốn nhắc tới cũng là ở phía trình duyệt thôi, vì mình đang bàn về CORS mà. Bản thân Request đó vẫn được Server thực thi và trả về Response và bị trình duyệt Block (Cái này do câu từ của anh chưa rõ lắm) Ý cuối của em về việc Pass Preflight em nói chính xác, chính vì thế nên chúng ta mới cần xử lý ngay từ lúc nhận được Request. Ngày trước, anh cũng bị case liên quan đến việc Pass Preflight, cũng viết riêng Middleware rồi nhưng gọi nhầm chỗ.
@@hoanganunicode Dạ vâng anh ạ. Cái CORS này cũng khá lằng nhằng, ngày đầu em mới gặp case cũng chỉ biết xử lý simple request. Tới khi làm SSO gặp case set-cookie khác Origin và khác cả Domain luôn em mới hiểu thêm về CORS. Mà nay anh cũng thức khuya rồi ạ 🤣
phải nói dạo gần đây anh Sơn ra list video chất lượng thật sự, mỗi video dài hơn 1h nhưng trong đó cả 1 bầu trời kiến thức, ai hấp thụ được phải nói là nội lực tăng đáng kể kkk. Vẫn hóng khóa JS Pro của anh, nghe bảo trong tháng sau đã r rồi, hèn gì anh Sơn mới có time record video dài dằn dẳn ntn =)))
Hi anh Sơn ! Em đang học khoá HTML Pro, làm dự án 3 thì em học lại vì thấy kiến thức nền chưa vững. Em học tới bài image thì có nghe qua khái niệm CORS, đại loại thẻ img có các thuộc tính cho phép hoặc không sử dụng tài nguyên của mình. Em nghiên cứu về CORS thì lại thấy video này của anh, mặc dù chưa hiểu hết những gì anh truyền tải nhưng cũng giúp em có thêm góc nhìn. Chúc Anh và Team F8 thật nhiều sức khoẻ ạ !
Hi em, sao học tới dự án 3 lại phải học lại vậy em. Trước đó em phải học qua các kiến thức lý thuyết rồi chứ em nhỉ. Còn về thẻ img nó có thuộc tính crossOrigin, mặc định là "anonymous" - tức là khi tải ảnh từ nguồn gốc chéo sẽ không mang theo thông tin xác thực (cụ thể là cookie), còn với giá trị "use-credentials" nó sẽ mang theo cookie sang máy chủ bên thứ 3 em nhé. Thuộc tính này của thẻ img, nhưng anh nghĩ nó nằm ngoài phạm vi khóa học HTML đó em ạ. Nên nếu chưa học JS và chưa tới kiến thức xác thực thì em chưa cần học về nó đâu em nha.
@@F8VNOfficial dạ em sinh viên tốt nghiệp cũng 2 năm rồi nhưng cảm thấy kiến thức nền tảng quá yếu. Em đã biết tới FE và BE nên em nghĩ tìm hiểu về CORS cũng giúp BE tiến bộ hơn. Lần đầu em học về thẻ img thì em chỉ biết mỗi 2 thuộc tính là alt và src. Sau khi nghiên cứu kỹ hơn thì em lại biết thêm 2 thằng như anh đã chia sẻ là "anonymous" và "use-credentials". Càng nghiên cứu sâu thì em càng thấy kiến thức cơ bản của mình cần bồi dưỡng thêm. Dạ có khoảng thời gian em phải tạm dừng việc học để tập trung kiếm tiền. Em chỉ mới học lại khoá HTML Pro mới đây thôi, lần trước em dừng tại dự án 3. Mỗi lần học lại có thêm kiến thức mới anh ạ
@@phucngo7638 À lâu không học nên bị quên cần ôn lại cho chắc phải không em? Đúng rồi, nếu em đã có kiến thức cả Frontend và Backend thì cần hiểu về CORS để có thể xử lý trong tình huống cross-origin. Như tình huống thẻ img nó mặc định là "anonymous" rồi, hiếm khi mình cần dùng "use-credentials" lắm em ạ. Vì dùng như vậy khi load ảnh nó sẽ đính kèm cookie. Trường hợp dùng là khi trang của em dùng session để authentication và em bảo vệ cả link ảnh luôn, tức là cần có session mới cho load ảnh nha. Chúc em học tốt nhé.
@@F8VNOfficial dạ em học về js nhưng em thấy đi phỏng vấn có nhiều người hỏi thêm về kiến thức về oop anh ạ. Em có đọc thêm tài liệu nhưng cứ cảm thấy mông lung. Em cũng ko rõ em đang không hiểu cụ thể ở điểm gì anh ạ.
chao a va moi nguoi . cho e hoi: ví dụ nếu res.render('home',{userData}) co cach nao de header o partials cung nhan duoc userData khong a . e muon kiem tra neu nguoi dung dang nhap thi se hien thi logout
F8 cho mình hỏi phần bạn dùng session không biết có phải session hồi xưa như những app cũ (server-side app) họ làm không nhỉ? Session cũ là "stateful authentication", tức là server duy trì kết nối với client để thiết lập một phiên hoạt động và để server biết client là ai. Còn session của bạn đơn thuần chỉ là một object "stateless", phi trạng thái, request sau không hề biết gì về request trước thì cái này có dc gọi là session thực sự ko ạ?
Vẫn là khái niệm session stateful authentication đó bạn. Cái object "sessions" (const sessions = {}) mình để trong code backend đó chính là data được lưu phía backend khi chương trình chạy và các request sau vẫn truy cập được vào object đó (stateful), không cần phải lưu xuống ổ cứng mới là statful đâu bạn. Đoạn đó mình ví dụ vậy cho đơn giản, thực tế nó cũng được lưu vào disk để duy trì được dữ liệu (persisten).
@@F8VNOfficial Thanks bạn mình hiểu rồi. Mình có hai câu hỏi nhỏ hơi ngớ ngẩn xíu nhưng mong dc bạn trả lời: - Session ID hoàn toàn có thể lưu theo kiểu: server trả về session ID qua json -> FE lấy và lưu vô "local storage" hoặc "request header" rồi sau đó gửi lên theo mỗi request. Vậy thì sao phải lưu vô cookie? (Mình đang tư duy phản biện để "kiểm chứng tính đứng đắn của việc lưu session ID vô cookie"). - Như mình thấy thì JWT hơn session ID ở chỗ nó stateless (ko phải lưu trên server). Nhưng đích đến cuối cùng vẫn là check trong database: + JWT decode ra -> lấy dc userid trong payload ra check vô db -> get thông tin user + Session ID lấy từ cookie ra -> lấy sessionid ra check vô db -> get thông tin user ==> Khác nhau về cơ chế không nhiều, vậy tại sao "token-based authentication" hiện tại lại tỏ ra vượt trội và ưu thế hơn so vơi "session" trong các ứng dụng hiện đại ngày nay? Thanks!
@@F8VNOfficial Tuyệt vời, bạn trả lời đúng những gì mình muốn nghe, kiến thức của bạn rất chắc. Thank you very much. Mong được chia sẻ thêm về các "advanced auth hiện đại" dùng token-based như O-auth, OIDC, Single-Sign-On trong các clip tiếp theo.
@evileyes9317 Hi bạn, ❓"Vậy thì sao phải lưu vô cookie?" - Vì cookie khi được lưu ở trình duyệt sẽ được tự đính kèm request HTTP giúp server nhận được sessionId dễ dàng, nên việc authentication cho các routes khá tiện, kể cả bạn load hình ảnh, load URL tới các resource khác cookie cũng được mang theo (nếu cùng một trang). Ngoài ra, trình duyệt cho phép lưu theo Domain, Path, Expires, HttpOnly, v.v nên việc sử dụng rất thuật tiện; việc tự nhận sessionId qua body rồi tự lưu trữ ở nơi khác sẽ phức tạp và kém bảo mật hơn. - Thực tế, nếu client không sử dụng trình duyệt (ví dụ bạn code mobile App) thì phía App sẽ không tự set-cookie (điều này có trên trình duyệt thôi), khi đó App muốn lấy được sessionId qua tiêu đề HTTP sẽ không được vì HttpOnly. Để App lấy được, server phải bỏ HttpOnly (giảm bảo mật), khi đó phía App lấy sessionId qua tiêu đề phản hồi và tự lưu trữ => câu chuyện trở nên phức tạp vì phải tự xử lý hết, cũng không tự động như cookie ở trình duyệt (không còn mang ý nghĩa tạo phiên nữa, vì server tạo phiên mà client lại phải xử lý thủ công hết mới duy trì được phiên). Khi ấy, người ta xoay sang sử dụng token (đơn giản thay đổi cách gọi, vì nó không còn phải là cookie nữa), và có thể nguyên lý hoạt động có thể tương tự như session (server tạo token và trả về client, mỗi request lại mang theo token...). ✅Tóm váy lại: Tại sao lưu vào cookie? 👉 Tự động gửi đi, bảo mật, dễ dàng triển khai. ❓"Vậy tại sao "token-based authentication" hiện tại lại tỏ ra vượt trội và ưu thế hơn so vơi "session" trong các ứng dụng hiện đại ngày nay" - Đúng là cơ chế thì vẫn là luồng đó. Server tạo ra JWT trả về client, client lưu trữ và gửi lên cùng các request... Tuy nhiên, mấu chốt nó nằm ở việc nó là stateless authentication. Như bạn có nói, đích đến vẫn là check DB, chắc chắn rồi. Nhưng nó là stateless về về mặt kiến trúc hệ thống trông như sau: [Client] -> [Web service] -> [Database] Khi dùng JWT thì [Web service] không lưu dữ liệu nữa (sessions thì được lưu ở đây), nên JWT nó là stateless authentication. Khi đó dữ liệu được lưu trong chính payload của JWT, thường lưu userID để định danh (JWT gọi là "sub" - subject). Vậy stateless ở khúc [Web service] có lợi gì? Hãy tưởng tượng hệ thống của bạn không phải chỉ có 1 máy chủ, mà có từ 2 máy chủ trở lên, phía trước là Load balancer (cân bằng tải), nhiệm vụ chia tải cho các máy chủ phía sau (Web service). Khi đó, mỗi request của bạn có thể vào các máy chủ khác nhau. Giả sử login request vào máy chủ A và tạo session trên đó, request sau lại vào máy chủ B thì sẽ không có session nên sẽ lỗi Unauthorized. Giải pháp khi đó là cần sync sessions giữa các [Web service], hoặc lưu session ra DB, hoặc máy chủ riêng để các [Web service] cùng trỏ chung vào => phức tạp hơn, khó khăn khi scale hơn. Nếu dùng stateless authentication như JWT thì không gặp phải vấn đề trên nữa. Các request có thể mang JWT tới bất cứ [Web service] nào, chỉ cần có secret key là có thể xác thực được token. Ngoài ra, JWT không lo đụng chính sách CORS của trình duyệt. Nó cũng bảo mật hơn vì xác thực bằng secret key, phải có secret key mới có thể xác thực. ✅Tóm váy lại: Tại sao "token-based authentication", cụ thể là JWT lại tỏ ra vượt trội hơn? 👉 Stateless, dễ dàng mở rộng; phù hợp với kiến trúc phân tán (không cần sync session); bảo mật; cross-domain/origin (không dính CORS); tùy biến cao (payload mang data).
A có thể giải thích về cách hoạt động của AbortController phía browser và cách nó tương tác với BE server không anh. Theo em phỏng đoán thì khi request được tạo và đang trong quá trình chờ response data mà huỷ request bằng AbortController thì dưới BE không biết được điều đó và tiếp tục chạy sau đó thực hiện thao tác trên DB, dẫn tới việc cancel từ client chỉ có ý nghĩa khi BE chưa thực hiện chỉnh sửa DB. Tiện thể em có thấy từ khoá cancellationToken phía BE dotnet, không biết về mặt ý nghĩa và cách hoạt động có liên quan không ạ Em cảm ơn anh
Em hình dung là HTTP nó là giao thức request-response, một khi request đã gửi đi thì server sẽ nhận được (không tính trường hợp server đang bị lỗi hoặc lỗi mạng), việc cancel ở client chỉ là client không xử lý response nữa thôi. Em lưu ý là khi cancel mà request chưa gửi đi thành công thì server không nhận được, cancel khi đã gửi đi thành công thì server vẫn có thể nhận được và xử lý, nhưng client sẽ không xử lý response từ server về nữa. Còn cancellationToken nó là khái niệm huỷ bỏ một hoạt động công việc nào đó. Ví dụ em có một tác vụ bất đồng bộ chưa hoàn thành, em có thể dùng cancellationToken để huỷ bỏ tác vụ đang chạy. Về cách hoạt động thì chúng tương tự nhau em nhé.
a Sơn ơi, vậy người ta thường hay dùng cookie-session hay jwt token vậy ạ? Mà hình như còn có trường hợp cho jwt token vào cookie luôn thì phải. Em thấy nó không sai nhưng có trường hợp phổ biến hơn là nếu dùng cookie-session rồi thì thôi jwt và ngược lại vì jwt thì ta hay dùng bearer token và gán nó vào authorization header. Anh hỗ trợ em câu hỏi này với ạ?
Tùy từng bài toán em ơi. Ví dụ dự án dùng SSR truyền thống thì vẫn dùng Session thôi (sessionId vẫn lưu vào cookie nha). Còn với các dự án mà viết API (SPA) thì hay dùng token. Nó gọi là "session based authentication" và "token based authentication" em nhé. Nghĩa là xác thực người dùng bằng cái gì, bằng session hay bằng token. Còn việc có token rồi lưu vào cookie vẫn là bình thường nhé. Để an toàn họ sẽ lưu JWT vào cookie với HttpOnly đó em. Khi đó API cần hỗ trợ nhận token qua nhiều cách, cả Header Authorization và cả cookie token em nhé. Còn lưu token vào localStorage hoặc cookie không HttpOnly sẽ kém bảo mật hơn, vì script ở trình duyệt sẽ lấy được, nếu dính XSS thì dễ bị leak token em nhé. Trường hợp Cross-Domain (khác tên miền giữa Frontend và Backend, hoặc giữa Mobile App và API) thì mới dùng JWT lưu ở localStorage với cookie mà không HttpOnly thôi em. Nếu Same-Site thì dùng HttpOnly cho an toàn em ạ.
A sơn ơi mong a trả lời giúp em ReactJs intern với fresher ở hcm giờ ko tìm được việc luôn anh à em thất nghiệp 7 tháng rồi anh 😢😢 em ko biết phải nên làm gì nữa a em bị stress quá mong anh trả lời ạ
Giờ họ vẫn tuyển, em tham gia nhiều nhóm tuyển dụng trên FB, có thể chủ động đăng tin tìm việc, tham gia TOPCV và bật chế độ tìm việc. Còn về kỹ năng cá nhân, em xây dựng dự án có đầy đủ các tính năng cơ bản mà hầu hết các trang đều đó, ngoài ra em nâng cao độ khó lên ví dụ: xác thực email sau khi đăng ký, xác minh 2 bước khi đăng nhập, chat hay comment realtime, v.v.
Mn cho em hỏi, sao máy em vào localhost thì được mà lúc vào 127.0.0.1 hay domain tự tạo trong file hosts lại không được (trừ lúc chạy xampp, nhưng cũng chỉ vào đc port của mysql admin thôi)
Em vào 127.0.0.1 không được trong trường hợp cụ thể như nào em nhỉ, em có sử dụng đúng port không em? Còn trường hợp em tự tạo trong file hosts thì em đúng ở terminal em chạy "ping host-name-của-em" xem có ping ra IP được không em nhé. Nếu ping được và đảm bảo dịch vụ đã chạy + truy cập đúng IP/host:cổng thì có thể dịch vụ đang chạy ở duy nhất host "localhost", khi đó tùy vào từng dự án mình sẽ có cách cấu hình khác nhau để cho host ở 0.0.0.0 là sẽ truy cập được qua cả localhost/127.0.0.1/và các hosts tự cấu hình nha em.
cái cors nó ảo vc ra, lần nào tự làm theo 3 4 project trên mạng thử cũng phải đặt tận 2 con cors() ,có khi phải đặt thêm con thứ 3 ngay trong cái phương thức get post... nó mới chịu chạy chả hiểu
Bạn đọc cái message CORS màu đỏ nó bắn ra ý, xem cụ thể trường hợp đó nó cần gì, và để ý coi lần đó gọi API khác Origin không, hay POST với application/json không, hay credentials include không? Vì những trường hợp đó nó đòi hỏi preflight request hoặc đòi thêm Header từ response bạn nhé. Nếu có message lỗi cụ thể, mình có thể gợi ý cho bạn lý do của lỗi đó cụ thể hơn.
Căng thế em, mấy bài như này thì anh còn làm concept được, chứ Identity Server làm mất nhiều thời gian lắm, mà sợ nhiều anh em không quan tâm, cái này đi làm thi thoảng mới gặp. Em đang quan tâm cụ thể chỗ nào em ơi?
@@nguyenmanhthoi2642 Okie em, anh sẽ làm video về lý thuyết và luồng hoạt động nha. Còn việc sử dụng thư viện hay framework anh em tự tìm hiểu nha, nhờ việc hiểu kiến trúc, lý thuyết và luồng hoạt động sẽ giúp anh em hiểu được thư viện nó làm gì ở trong.
@@hienvinhle1797 trường nào chứ trường mình bộ môn CNTT không có mấy cái này nhé, cái này thuộc dạng kiến thức chuyên sâu hơn về web, còn trường chỉ dạy cơ bản nhất thôi, để còn dạy thêm nhiều concept khác, phần nhiều là xoáy sâu vào các thuật toán, các bài toán, vẽ các thể loại sơ đồ hơn là các nội dung liên quan nhiều tới dev như thế này
Phân đoạn trong video:
- 01:14 Settup dự án
- 04:12 “Dính” CORS lần 1
- 06:06 Khái niệm “nguồn gốc”
- 11:44 Tạo form và viết API đăng nhập (sử dụng session)
- 28:11 “Dính” CORS lần 2
- 44:20 Sử dụng cookies khác domain
- 58:38 Ứng dụng của cookies bên thứ 3
- 01:06:50 “Tháng 4 là lời hứa của anh”
Anh chia sẻ cụ thể hơn chút nhé.
Khi bị chặn bởi CORS là chặn ở Response bên phía back-end. Trên thực tế Request đó vẫn được Server tiếp nhận xử lý, chỉ là không trả về được
Tuy nhiên, khi có Request gửi lên Server mà có Header thì trình duyệt sẽ chặn luôn không cho Server nhận request đó
Để làm được điều này, trình duyệt có 1 request có tên là Preflight với method là OPTIONS để thăm dò. Nếu Response header trả về không thỏa mãn thì sẽ không cho phép luôn.
==> Đó cũng là lý do tại sao ở phía back-end phải trả về Response Header CORS ngay sau khi có Request, nếu em để cái này trong 1 Route cụ thể sẽ không thể Pass được CORS với những Request có Header
Header Access-Control-Allow-Origin hiểu đơn giản là cho phép Origin, chỉ cần khác Origin --> Block
Cấu trúc 1 URL sẽ có 1 khái niệm là Origin bao gồm 3 phần: Scheme + Hostname + Port
Thank you anh đã góp ý, tiện đây em cũng làm rõ một số ý sau ạ:
Khi gửi đi một "simple request", tức là với các methods GET, HEAD, POST (là post thì content-type là một trong số application/x-www-form-urlencoded, multipart/form-data, hoặc text/plain), không bao gồm option "credentials: include" hoặc "withCredentials: true" thì khi ấy request không bị chặn (nên không có preflight), server lúc này vẫn tiếp nhận, xử lý và phản hồi (chứ không phải là không trả về được), vì HTTP là "request-response protocol" - tức là luôn có request-response. Lúc này, nếu cross-origin và phản hồi về Access-Control-Allow-Origin khác Origin hiện tại hoặc khác * thì sẽ bị trình duyệt block response (tức là client nhận được response, trình duyệt không cho access thôi).
Trường hợp khác, khi gửi các yêu cầu KHÔNG simple, trình duyệt không chặn request đó, mà nó sẽ "tạm dừng" để gửi preflight (request thăm dò với method OPTIONS) lên server trước, khi đó nếu server phản hồi các Headers phù hợp thì request chính mới được gửi đi, ngược lại trình duyệt sẽ block request chính luôn.
Với trường hợp "credentials: include" hoặc "withCredentials: true" thì Access-Control-Allow-Origin không sử dụng được wildcard * mà bắt buộc phải là Origin cụ thể. Ngoài ra còn phải trả về thêm Access-Control-Allow-Credentials là "true" nữa, không là sau preflight request chính sẽ bị block.
Thật ra việc "để cái này trong 1 Route cụ thể sẽ không thể Pass được CORS" là vì preflight nó là method OPTIONS, để trong route cụ thể mà route đó không khớp method OPTIONS thì preflight sẽ fail, vẫn tới request chính bị block sau đó. Còn nếu, mình viết trong route cụ thể với method OPTIONS và trả về đúng các Headers cần thiết thì vẫn pass được. Chẳng qua việc xử lý preflight trong từng route là không cần thiết, nên thực tế sẽ xử lý ở một nơi là middleware, vừa dễ maintain, vừa xử lý sớm luôn ngay sau khi nhận được request.
@@F8VNOfficial Ok em ơi
Đúng như những gì em chia sẻ, trường hợp simple request thì trình duyệt sẽ block response. Cái anh muốn nhắc tới cũng là ở phía trình duyệt thôi, vì mình đang bàn về CORS mà.
Bản thân Request đó vẫn được Server thực thi và trả về Response và bị trình duyệt Block (Cái này do câu từ của anh chưa rõ lắm)
Ý cuối của em về việc Pass Preflight em nói chính xác, chính vì thế nên chúng ta mới cần xử lý ngay từ lúc nhận được Request.
Ngày trước, anh cũng bị case liên quan đến việc Pass Preflight, cũng viết riêng Middleware rồi nhưng gọi nhầm chỗ.
@@hoanganunicode Dạ vâng anh ạ. Cái CORS này cũng khá lằng nhằng, ngày đầu em mới gặp case cũng chỉ biết xử lý simple request. Tới khi làm SSO gặp case set-cookie khác Origin và khác cả Domain luôn em mới hiểu thêm về CORS.
Mà nay anh cũng thức khuya rồi ạ 🤣
@@F8VNOfficial À đúng rồi. Quên mất. Em nay lại cú đêm à?
@@hoanganunicode Vâng anh ơi, em lại cú đêm tới 4h sáng rồi :v
anh dạy chuyên sâu quá, em phải tua lại 3 4 lần nghe từng chữ mới hiểu haha
vừa nói hôm trước hôm sau có liền luôn, quá là ưng luôn ad ơi.
Cảm ơn bạn nha.
hóng jwt + access token và refresh token từ a : D
+1 luôn
+1 lên top
Lên tốp
+1 sao a Sơn ko tương tác comment này ta
lên top
mấy bài kiểu này anh đăng hay vãi. mong a ra video kiểu này thường xuyên hơn ạ !!!
Video cả tiếng có dài quá không em? Tại anh đi từ bài toán theo flow tới khi gặp vấn đề thì giải quyết ấy.
@@F8VNOfficialkhông a ơi , e lại thích kiểu này hơn vì nó xuyên suốt, k bị ngắt nhịp như các video ngắn😂
@@vinhphucu Cảm ơn em nhiều nha, để anh làm thêm nội dung kiểu này
@@F8VNOfficial dài nhưng xem vẫn cuốn ạ
Kiến thức anh Sơn rộng quá. Xem video a xong thấy mình còn nhiều thứ phải học quá. Cảm ơn anh ạ
Cố lên em. Mỗi ngày học thêm một tí xíu thôi. Nó tích luỹ nhiều dần theo năm tháng em nhé.
Fan cứng lâu năm, công nhận video nào của anh cũng thực sự chất lượng
P/s: Hóng khóa JS Pro 🎉🎉
Bài học chất lượng dễ hiểu quá a mong a ra thêm bài SSO nx ạ
Mong anh Sơn ra thật nhiều video như thế này nữa. Chúc anh và gia đình thật nhiều sức khoẻ ạ
Cảm ơn em nhiều nha, chúc em thành công hơn nha
Chúng ta nên cám bạn Thiếu Cơ đó vì nhờ bạn mà có thêm video hay ho nữa 🤣
Kkkk
Vừa thấy thông báo là xem liền. Hóng video SSO a ơi
Okie em ơi
phải nói dạo gần đây anh Sơn ra list video chất lượng thật sự, mỗi video dài hơn 1h nhưng trong đó cả 1 bầu trời kiến thức, ai hấp thụ được phải nói là nội lực tăng đáng kể kkk. Vẫn hóng khóa JS Pro của anh, nghe bảo trong tháng sau đã r rồi, hèn gì anh Sơn mới có time record video dài dằn dẳn ntn =)))
Kk thật ra là quay khoá học nhiều anh stress quá. Quay video chia sẻ free xong anh em comment tiếp thêm động lực nên anh quay thêm á.
Hay quá anh ơi. Hóng JWT và các bài giảng sắp tới của anh. Vô cùng thiết thực và bổ X.
Cảm ơn em nha
những video dài như này rất hữu ích
Hi anh Sơn !
Em đang học khoá HTML Pro, làm dự án 3 thì em học lại vì thấy kiến thức nền chưa vững.
Em học tới bài image thì có nghe qua khái niệm CORS, đại loại thẻ img có các thuộc tính cho phép hoặc không sử dụng tài nguyên của mình.
Em nghiên cứu về CORS thì lại thấy video này của anh, mặc dù chưa hiểu hết những gì anh truyền tải nhưng cũng giúp em có thêm góc nhìn.
Chúc Anh và Team F8 thật nhiều sức khoẻ ạ !
Hi em, sao học tới dự án 3 lại phải học lại vậy em. Trước đó em phải học qua các kiến thức lý thuyết rồi chứ em nhỉ.
Còn về thẻ img nó có thuộc tính crossOrigin, mặc định là "anonymous" - tức là khi tải ảnh từ nguồn gốc chéo sẽ không mang theo thông tin xác thực (cụ thể là cookie), còn với giá trị "use-credentials" nó sẽ mang theo cookie sang máy chủ bên thứ 3 em nhé.
Thuộc tính này của thẻ img, nhưng anh nghĩ nó nằm ngoài phạm vi khóa học HTML đó em ạ. Nên nếu chưa học JS và chưa tới kiến thức xác thực thì em chưa cần học về nó đâu em nha.
@@F8VNOfficial dạ em sinh viên tốt nghiệp cũng 2 năm rồi nhưng cảm thấy kiến thức nền tảng quá yếu. Em đã biết tới FE và BE nên em nghĩ tìm hiểu về CORS cũng giúp BE tiến bộ hơn.
Lần đầu em học về thẻ img thì em chỉ biết mỗi 2 thuộc tính là alt và src. Sau khi nghiên cứu kỹ hơn thì em lại biết thêm 2 thằng như anh đã chia sẻ là "anonymous" và "use-credentials". Càng nghiên cứu sâu thì em càng thấy kiến thức cơ bản của mình cần bồi dưỡng thêm.
Dạ có khoảng thời gian em phải tạm dừng việc học để tập trung kiếm tiền. Em chỉ mới học lại khoá HTML Pro mới đây thôi, lần trước em dừng tại dự án 3.
Mỗi lần học lại có thêm kiến thức mới anh ạ
@@phucngo7638 À lâu không học nên bị quên cần ôn lại cho chắc phải không em? Đúng rồi, nếu em đã có kiến thức cả Frontend và Backend thì cần hiểu về CORS để có thể xử lý trong tình huống cross-origin. Như tình huống thẻ img nó mặc định là "anonymous" rồi, hiếm khi mình cần dùng "use-credentials" lắm em ạ. Vì dùng như vậy khi load ảnh nó sẽ đính kèm cookie. Trường hợp dùng là khi trang của em dùng session để authentication và em bảo vệ cả link ảnh luôn, tức là cần có session mới cho load ảnh nha.
Chúc em học tốt nhé.
hay quá a ơi, thích xem dạng video như này quá ạ!!!
Cảm ơn em nhiều nha, đóng góp thêm chủ đề để rảnh anh làm nha.
Hay quá a ơi, video cả tiếng mà xem cứ sợ hết kkk
KK cảm ơn em nha
Quá là chất lượng và chi tiết luôn anh
Hay quá, đúng cái mình đang tìm hiểu. Cám ơn bạn!
🥰🥰
Bài này rất hay
đấy là người khác nói thế, với mình thì rất đơn giản bấm vào mua khoá học 💪💪
kkk
Video rất nhiều chất xám của a, cảm ơn a nhìu❤
Cảm ơn em nha
wow anh sơn của chúng ta phải đeo kính rồi ư 😀😀😀😀
Kkkk
Hóng thầy chia sẻ những thủ thuật tăng SEO cho website
SEO thì tập trung làm nội dung tốt. Thủ thuật ko bền em nhé.
em đang học thêm nestjs và đang thấy khó hiểu về decorator trong typescript. Mong anh ra video giải thích ạ
mong anh ra nhiều video về kĩ thuật lập trình như này
Okie em ơi
thực ra đây không phải kỹ thuật lập trình đâu b, này là kiến thức cơ sở cốt lõi của web rồi
Làm khóa học dạy cơ chế SSL đi anh
Hóng SSO luôn ạ
Hóng SSO a ạ
lâu lắm anh mới ra thêm video
Anh tập trung quay khóa học JS Pro em ơi
Quá đỉnh a ơi
a làm thêm nhiều video về backend và hệ thống đi a
a Sơn có thể giải thích Event Loop trong JS cụ thể làm gì ko ạ, e đọc mà thấy phần này khó hiểu quá!
Hóng SSO quá anh ơi =)))
Cho e hỏi khúc 13:57 có ai biết a Sơn dùng extension gì nó gợi ý từ cái viết tắt kia ra đầy đủ dòng code đó không ạ?
Cái đấy mặc định vscode có mà bạn k b cài intellicode
Hay quá anh ơi. Anh có thể làm thêm video về oop được không anh? Phần oop này em thấy khó hiểu quá.
Cụ thể em thấy nó khó hiểu ở phần nào em ơi. À mà em đang học ngôn ngữ gì nhỉ?
@@F8VNOfficial dạ em học về js nhưng em thấy đi phỏng vấn có nhiều người hỏi thêm về kiến thức về oop anh ạ. Em có đọc thêm tài liệu nhưng cứ cảm thấy mông lung. Em cũng ko rõ em đang không hiểu cụ thể ở điểm gì anh ạ.
chao a va moi nguoi . cho e hoi: ví dụ nếu res.render('home',{userData}) co cach nao de header o partials cung nhan duoc userData khong a . e muon kiem tra neu nguoi dung dang nhap thi se hien thi logout
F8 cho mình hỏi phần bạn dùng session không biết có phải session hồi xưa như những app cũ (server-side app) họ làm không nhỉ?
Session cũ là "stateful authentication", tức là server duy trì kết nối với client để thiết lập một phiên hoạt động và để server biết client là ai.
Còn session của bạn đơn thuần chỉ là một object "stateless", phi trạng thái, request sau không hề biết gì về request trước thì cái này có dc gọi là session thực sự ko ạ?
Vẫn là khái niệm session stateful authentication đó bạn. Cái object "sessions" (const sessions = {}) mình để trong code backend đó chính là data được lưu phía backend khi chương trình chạy và các request sau vẫn truy cập được vào object đó (stateful), không cần phải lưu xuống ổ cứng mới là statful đâu bạn. Đoạn đó mình ví dụ vậy cho đơn giản, thực tế nó cũng được lưu vào disk để duy trì được dữ liệu (persisten).
@@F8VNOfficial Thanks bạn mình hiểu rồi. Mình có hai câu hỏi nhỏ hơi ngớ ngẩn xíu nhưng mong dc bạn trả lời:
- Session ID hoàn toàn có thể lưu theo kiểu: server trả về session ID qua json -> FE lấy và lưu vô "local storage" hoặc "request header" rồi sau đó gửi lên theo mỗi request.
Vậy thì sao phải lưu vô cookie? (Mình đang tư duy phản biện để "kiểm chứng tính đứng đắn của việc lưu session ID vô cookie").
- Như mình thấy thì JWT hơn session ID ở chỗ nó stateless (ko phải lưu trên server). Nhưng đích đến cuối cùng vẫn là check trong database:
+ JWT decode ra -> lấy dc userid trong payload ra check vô db -> get thông tin user
+ Session ID lấy từ cookie ra -> lấy sessionid ra check vô db -> get thông tin user
==> Khác nhau về cơ chế không nhiều, vậy tại sao "token-based authentication" hiện tại lại tỏ ra vượt trội và ưu thế hơn so vơi "session" trong các ứng dụng hiện đại ngày nay?
Thanks!
@@F8VNOfficial Tuyệt vời, bạn trả lời đúng những gì mình muốn nghe, kiến thức của bạn rất chắc. Thank you very much.
Mong được chia sẻ thêm về các "advanced auth hiện đại" dùng token-based như O-auth, OIDC, Single-Sign-On trong các clip tiếp theo.
@evileyes9317 Hi bạn,
❓"Vậy thì sao phải lưu vô cookie?"
- Vì cookie khi được lưu ở trình duyệt sẽ được tự đính kèm request HTTP giúp server nhận được sessionId dễ dàng, nên việc authentication cho các routes khá tiện, kể cả bạn load hình ảnh, load URL tới các resource
khác cookie cũng được mang theo (nếu cùng một trang). Ngoài ra, trình duyệt cho phép lưu theo Domain, Path, Expires, HttpOnly, v.v nên việc sử dụng rất thuật tiện; việc tự nhận sessionId qua body rồi tự lưu trữ ở nơi khác sẽ phức tạp và kém bảo mật hơn.
- Thực tế, nếu client không sử dụng trình duyệt (ví dụ bạn code mobile App) thì phía App sẽ không tự set-cookie (điều này có trên trình duyệt thôi), khi đó App muốn lấy được sessionId qua tiêu đề HTTP sẽ không được vì HttpOnly. Để App lấy được, server phải bỏ HttpOnly (giảm bảo mật), khi đó phía App lấy sessionId qua tiêu đề phản hồi và tự lưu trữ => câu chuyện trở nên phức tạp vì phải tự xử lý hết, cũng không tự động như cookie ở trình duyệt (không còn mang ý nghĩa tạo phiên nữa, vì server tạo phiên mà client lại phải xử lý thủ công hết mới duy trì được phiên). Khi ấy, người ta xoay sang sử dụng token (đơn giản thay đổi cách gọi, vì nó không còn phải là cookie nữa), và có thể nguyên lý hoạt động có thể tương tự như session (server tạo token và trả về client, mỗi request lại mang theo token...).
✅Tóm váy lại: Tại sao lưu vào cookie?
👉 Tự động gửi đi, bảo mật, dễ dàng triển khai.
❓"Vậy tại sao "token-based authentication" hiện tại lại tỏ ra vượt trội và ưu thế hơn so vơi "session" trong các ứng dụng hiện đại ngày nay"
- Đúng là cơ chế thì vẫn là luồng đó. Server tạo ra JWT trả về client, client lưu trữ và gửi lên cùng các request... Tuy nhiên, mấu chốt nó nằm ở việc nó là stateless authentication.
Như bạn có nói, đích đến vẫn là check DB, chắc chắn rồi. Nhưng nó là stateless về về mặt kiến trúc hệ thống trông như sau:
[Client] -> [Web service] -> [Database]
Khi dùng JWT thì [Web service] không lưu dữ liệu nữa (sessions thì được lưu ở đây), nên JWT nó là stateless authentication. Khi đó dữ liệu được lưu trong chính payload của JWT, thường lưu userID để định danh (JWT gọi là "sub" - subject).
Vậy stateless ở khúc [Web service] có lợi gì? Hãy tưởng tượng hệ thống của bạn không phải chỉ có 1 máy chủ, mà có từ 2 máy chủ trở lên, phía trước là Load balancer (cân bằng tải), nhiệm vụ chia tải cho các máy chủ phía sau (Web service).
Khi đó, mỗi request của bạn có thể vào các máy chủ khác nhau. Giả sử login request vào máy chủ A và tạo session trên đó, request sau lại vào máy chủ B thì sẽ không có session nên sẽ lỗi Unauthorized. Giải pháp khi đó là cần sync sessions giữa các [Web service], hoặc lưu session ra DB, hoặc máy chủ riêng để các [Web service] cùng trỏ chung vào => phức tạp hơn, khó khăn khi scale hơn.
Nếu dùng stateless authentication như JWT thì không gặp phải vấn đề trên nữa. Các request có thể mang JWT tới bất cứ [Web service] nào, chỉ cần có secret key là có thể xác thực được token.
Ngoài ra, JWT không lo đụng chính sách CORS của trình duyệt. Nó cũng bảo mật hơn vì xác thực bằng secret key, phải có secret key mới có thể xác thực.
✅Tóm váy lại: Tại sao "token-based authentication", cụ thể là JWT lại tỏ ra vượt trội hơn?
👉 Stateless, dễ dàng mở rộng; phù hợp với kiến trúc phân tán (không cần sync session); bảo mật; cross-domain/origin (không dính CORS); tùy biến cao (payload mang data).
Oai anh Sơn dạo này tròn thế nhờ hihi
Ngồi code nhiều tích mỡ đó :(
Anh làm 1 video nói về caching data được không ạ. 1 số thằng như Redis hoặc tương tự thế ạ.
Em quan tâm điều gì trong caching em nhỉ?
anh trai nghijch fastify chưa
A có thể giải thích về cách hoạt động của AbortController phía browser và cách nó tương tác với BE server không anh. Theo em phỏng đoán thì khi request được tạo và đang trong quá trình chờ response data mà huỷ request bằng AbortController thì dưới BE không biết được điều đó và tiếp tục chạy sau đó thực hiện thao tác trên DB, dẫn tới việc cancel từ client chỉ có ý nghĩa khi BE chưa thực hiện chỉnh sửa DB.
Tiện thể em có thấy từ khoá cancellationToken phía BE dotnet, không biết về mặt ý nghĩa và cách hoạt động có liên quan không ạ
Em cảm ơn anh
Em hình dung là HTTP nó là giao thức request-response, một khi request đã gửi đi thì server sẽ nhận được (không tính trường hợp server đang bị lỗi hoặc lỗi mạng), việc cancel ở client chỉ là client không xử lý response nữa thôi.
Em lưu ý là khi cancel mà request chưa gửi đi thành công thì server không nhận được, cancel khi đã gửi đi thành công thì server vẫn có thể nhận được và xử lý, nhưng client sẽ không xử lý response từ server về nữa.
Còn cancellationToken nó là khái niệm huỷ bỏ một hoạt động công việc nào đó. Ví dụ em có một tác vụ bất đồng bộ chưa hoàn thành, em có thể dùng cancellationToken để huỷ bỏ tác vụ đang chạy.
Về cách hoạt động thì chúng tương tự nhau em nhé.
@@F8VNOfficial em cảm ơn a. Sắp tới a ra khoá JS pro em nhất định sẽ mua
Anh có tài liệu nào chuyên sâu về cái header không a
Nó là kiến thức về HTTP protocol em nhé.
a làm thêm video động đực, định hướng các kiểu đi
Em theo mảng web hay mobile hay mảng nào em ơi
@@F8VNOfficial web frontend ạ, nghe nói đã bảo hòa nên em đang cố gắn rất nhiều nhưng thiếu động lực
a Sơn ơi, vậy người ta thường hay dùng cookie-session hay jwt token vậy ạ? Mà hình như còn có trường hợp cho jwt token vào cookie luôn thì phải. Em thấy nó không sai nhưng có trường hợp phổ biến hơn là nếu dùng cookie-session rồi thì thôi jwt và ngược lại vì jwt thì ta hay dùng bearer token và gán nó vào authorization header. Anh hỗ trợ em câu hỏi này với ạ?
Tùy từng bài toán em ơi. Ví dụ dự án dùng SSR truyền thống thì vẫn dùng Session thôi (sessionId vẫn lưu vào cookie nha). Còn với các dự án mà viết API (SPA) thì hay dùng token.
Nó gọi là "session based authentication" và "token based authentication" em nhé. Nghĩa là xác thực người dùng bằng cái gì, bằng session hay bằng token.
Còn việc có token rồi lưu vào cookie vẫn là bình thường nhé. Để an toàn họ sẽ lưu JWT vào cookie với HttpOnly đó em. Khi đó API cần hỗ trợ nhận token qua nhiều cách, cả Header Authorization và cả cookie token em nhé.
Còn lưu token vào localStorage hoặc cookie không HttpOnly sẽ kém bảo mật hơn, vì script ở trình duyệt sẽ lấy được, nếu dính XSS thì dễ bị leak token em nhé. Trường hợp Cross-Domain (khác tên miền giữa Frontend và Backend, hoặc giữa Mobile App và API) thì mới dùng JWT lưu ở localStorage với cookie mà không HttpOnly thôi em. Nếu Same-Site thì dùng HttpOnly cho an toàn em ạ.
@@F8VNOfficial same site là ví dụ như em làm frontend ở localhost:5173, backend ở localhost:3000 phải không anh?
Nginx, docker, k8s anh ui
a Sơn ơi, trong postman, ở tab form-data, làm thế nào để gửi xuống backend 1 empty array vậy ạ?
Em đặt tên khóa (key) thêm cặp ngoặc vuông vào nó hiểu là mảng nhé. Ví dụ: items[], mảng rỗng thì em không gửi value nữa.
Bao giờ có khóa học Javascript Pro thế Mr Sơn ?
Dự kiến tháng sau mình open đó, nhiều anh em mong lắm rồi
nghe phát biết nettruyen luôn a =))
Anh ví dụ bừa thôi ấy kk =)))
quá xịn
Xịn thì phải học và code ra dự án xịn xò nha
@@F8VNOfficial tks ad, mở mang được nhiều kiến thức hay. Hóng ad làm video khác tên miền 1 domain giống google và youtube.
hay
JS Pro gần ra chưa anh ơi 😂
Sắp rồi em ơi 💪💪
A sơn ơi mong a trả lời giúp em ReactJs intern với fresher ở hcm giờ ko tìm được việc luôn anh à em thất nghiệp 7 tháng rồi anh 😢😢 em ko biết phải nên làm gì nữa a em bị stress quá mong anh trả lời ạ
Giờ họ vẫn tuyển, em tham gia nhiều nhóm tuyển dụng trên FB, có thể chủ động đăng tin tìm việc, tham gia TOPCV và bật chế độ tìm việc. Còn về kỹ năng cá nhân, em xây dựng dự án có đầy đủ các tính năng cơ bản mà hầu hết các trang đều đó, ngoài ra em nâng cao độ khó lên ví dụ: xác thực email sau khi đăng ký, xác minh 2 bước khi đăng nhập, chat hay comment realtime, v.v.
Mn cho em hỏi, sao máy em vào localhost thì được mà lúc vào 127.0.0.1 hay domain tự tạo trong file hosts lại không được (trừ lúc chạy xampp, nhưng cũng chỉ vào đc port của mysql admin thôi)
Em vào 127.0.0.1 không được trong trường hợp cụ thể như nào em nhỉ, em có sử dụng đúng port không em? Còn trường hợp em tự tạo trong file hosts thì em đúng ở terminal em chạy "ping host-name-của-em" xem có ping ra IP được không em nhé. Nếu ping được và đảm bảo dịch vụ đã chạy + truy cập đúng IP/host:cổng thì có thể dịch vụ đang chạy ở duy nhất host "localhost", khi đó tùy vào từng dự án mình sẽ có cách cấu hình khác nhau để cho host ở 0.0.0.0 là sẽ truy cập được qua cả localhost/127.0.0.1/và các hosts tự cấu hình nha em.
cái cors nó ảo vc ra, lần nào tự làm theo 3 4 project trên mạng thử cũng phải đặt tận 2 con cors() ,có khi phải đặt thêm con thứ 3 ngay trong cái phương thức get post... nó mới chịu chạy chả hiểu
Bạn đọc cái message CORS màu đỏ nó bắn ra ý, xem cụ thể trường hợp đó nó cần gì, và để ý coi lần đó gọi API khác Origin không, hay POST với application/json không, hay credentials include không? Vì những trường hợp đó nó đòi hỏi preflight request hoặc đòi thêm Header từ response bạn nhé. Nếu có message lỗi cụ thể, mình có thể gợi ý cho bạn lý do của lỗi đó cụ thể hơn.
Sao mình login qua sdt f8 không nhận được mã xác nhận vậy ad?
Bạn inbox fanpage F8 - Học Lập Trình Để Đi Làm để được hỗ trợ bạn nhé, phần này đang có trục trặc chút mong bạn thông cảm nha.
Mong a làm về Identity Server & kết nối oidc lấy access token & refresh token :v
Căng thế em, mấy bài như này thì anh còn làm concept được, chứ Identity Server làm mất nhiều thời gian lắm, mà sợ nhiều anh em không quan tâm, cái này đi làm thi thoảng mới gặp. Em đang quan tâm cụ thể chỗ nào em ơi?
@@F8VNOfficial Dạ access token, refresh token và SSO anh ạ 😅
bạn tìm hiểu về keycloak ấy, nó sẽ có đủ chức năng để bạn tích hợp mà cái này bên ngoài doanh nghiệp giờ cx dùng nhiều chứ không cần tự code nữa
@@nguyenmanhthoi2642 Okie em, anh sẽ làm video về lý thuyết và luồng hoạt động nha. Còn việc sử dụng thư viện hay framework anh em tự tìm hiểu nha, nhờ việc hiểu kiến trúc, lý thuyết và luồng hoạt động sẽ giúp anh em hiểu được thư viện nó làm gì ở trong.
Refresh token a ơi
hóng nginx
🥰
Hóng SEO
Kk SEO thì mình chia sẻ ở góc độ dev được thôi, chứ chuyên SEO phải tìm chuyên gia SEO
đại học ko có mấy kiến thức này
Có thể họ sẽ đề cập "nhẹ nhàng" thôi, còn cái anh nói là nó sâu hơn, cả 1 tiếng đồng hồ cơ mà
Sao lại k chưa học tới thôi :)) không có này sao làm web api được
@@hienvinhle1797 trường nào chứ trường mình bộ môn CNTT không có mấy cái này nhé, cái này thuộc dạng kiến thức chuyên sâu hơn về web, còn trường chỉ dạy cơ bản nhất thôi, để còn dạy thêm nhiều concept khác, phần nhiều là xoáy sâu vào các thuật toán, các bài toán, vẽ các thể loại sơ đồ hơn là các nội dung liên quan nhiều tới dev như thế này