Bạn có thể giúp tôi hiểu điều này? Những sai lầm phổ biến của REST: Các phiên là không liên quan


159

Tuyên bố miễn trừ trách nhiệm: Tôi mới tham gia vào trường tư tưởng REST và tôi đang cố gắng để bao bọc tâm trí của mình xung quanh nó.

Vì vậy, tôi đang đọc trang này, những lỗi REST phổ biến và tôi thấy tôi hoàn toàn bị bối rối bởi phần về các phiên không liên quan. Đây là những gì trang nói:

Không cần khách hàng "đăng nhập" hoặc "bắt đầu kết nối". Xác thực HTTP được thực hiện tự động trên mỗi tin nhắn. Ứng dụng khách hàng là người tiêu dùng tài nguyên, không phải dịch vụ. Vì vậy, không có gì để đăng nhập! Giả sử bạn đang đặt chuyến bay trên dịch vụ web REST. Bạn không tạo kết nối "phiên" mới cho dịch vụ. Thay vào đó, bạn yêu cầu "đối tượng người tạo hành trình" tạo cho bạn một hành trình mới. Bạn có thể bắt đầu điền vào chỗ trống nhưng sau đó lấy một số thành phần hoàn toàn khác ở nơi khác trên web để điền vào một số khoảng trống khác. Không có phiên nên không có vấn đề di chuyển trạng thái phiên giữa các khách hàng. Cũng không có vấn đề về "mối quan hệ phiên"

Được rồi, tôi nhận được rằng xác thực HTTP được thực hiện tự động trên mỗi tin nhắn - nhưng bằng cách nào? Là tên người dùng / mật khẩu được gửi với mỗi yêu cầu? Không phải điều đó chỉ làm tăng diện tích bề mặt tấn công sao? Tôi cảm thấy như mình đang thiếu một phần của câu đố.

Sẽ rất tệ nếu có một dịch vụ REST, giả sử, /sessionchấp nhận yêu cầu GET, trong đó bạn chuyển tên người dùng / mật khẩu như một phần của yêu cầu và trả lại mã thông báo phiên nếu xác thực thành công, có thể sau đó thông qua cùng với các yêu cầu tiếp theo? Điều đó có ý nghĩa từ quan điểm REST hay là thiếu điểm đó?


mọi yêu cầu luôn được xác thực, chiếm quyền điều khiển phiên là một điều. yên tĩnh làm cho điều này rõ ràng hơn nhưng không tiếp xúc nhiều hơn.
Jasen

Câu trả lời:


79

Để là RESTful, mỗi yêu cầu HTTP phải tự mang đủ thông tin cho người nhận để xử lý nó hoàn toàn hài hòa với tính chất không trạng thái của HTTP.

Được rồi, tôi nhận được rằng xác thực HTTP được thực hiện tự động trên mỗi tin nhắn - nhưng bằng cách nào?

Có, tên người dùng và mật khẩu được gửi với mọi yêu cầu. Các phương pháp phổ biến để làm như vậy là xác thực truy cập cơ bảnxác thực truy cập tiêu hóa . Và vâng, một kẻ nghe trộm có thể nắm bắt thông tin đăng nhập của người dùng. Do đó, người ta sẽ mã hóa tất cả dữ liệu được gửi và nhận bằng cách sử dụng TLS) .

Sẽ rất tệ nếu có một dịch vụ REST, giả sử, / phiên, chấp nhận yêu cầu GET, trong đó bạn chuyển tên người dùng / mật khẩu như một phần của yêu cầu và trả lại mã thông báo phiên nếu xác thực thành công, có thể sau đó được thông qua cùng với các yêu cầu tiếp theo? Điều đó có ý nghĩa từ quan điểm REST hay là thiếu điểm đó?

Điều này sẽ không phải là RESTful vì nó mang trạng thái nhưng nó khá phổ biến vì nó thuận tiện cho người dùng; một người dùng không phải đăng nhập mỗi lần.

Những gì bạn mô tả trong "mã thông báo phiên" thường được gọi là cookie đăng nhập . Chẳng hạn, nếu bạn cố gắng đăng nhập vào Yahoo! tài khoản có một hộp kiểm cho biết "giữ cho tôi đăng nhập trong 2 tuần". Điều này về cơ bản là nói (theo lời của bạn) "giữ mã thông báo phiên của tôi tồn tại trong 2 tuần nếu tôi đăng nhập thành công." Các trình duyệt web sẽ gửi các cookie đăng nhập như vậy (và có thể là các cookie khác) với mỗi yêu cầu HTTP mà bạn yêu cầu để thực hiện cho bạn.


5
Câu trả lời này không có ý nghĩa với tôi. Đầu tiên, nó nói rằng bạn có thể vượt qua đăng nhập và mật khẩu mỗi lần và do đó cũng một lần, điều này có ý nghĩa. Sau đó, ý tưởng quay lại máy khách trạng thái đăng nhập thành công dưới dạng mã thông báo được đề xuất. Nếu cần, mã thông báo có thể mã hóa thời gian tạo. Chúng tôi chắc chắn được phép trả lại thông tin cho khách hàng. Vì vậy, đề nghị này có vẻ tốt với tôi. Câu trả lời nói rằng nó không ổn vì "nó mang trạng thái", nhưng không phải ý tưởng về "ST" trong "REST" trạng thái đó có thể được chuyển giữa máy khách và máy chủ không?

33

Không có gì lạ khi dịch vụ REST yêu cầu xác thực cho mọi yêu cầu HTTP. Ví dụ: Amazon S3 yêu cầu mọi yêu cầu đều có chữ ký được lấy từ thông tin đăng nhập của người dùng, yêu cầu chính xác để thực hiện và thời gian hiện tại. Chữ ký này dễ tính toán ở phía máy khách, có thể được máy chủ xác minh nhanh chóng và được sử dụng hạn chế cho kẻ tấn công chặn nó (vì nó dựa trên thời gian hiện tại).


3
+1 bạn có thể giải thích rõ hơn: có hạn sử dụng cho kẻ tấn công chặn nó không (vì nó dựa trên thời gian hiện tại) ? Bạn không nói về một cookie có chứa tên người dùng và mật khẩu được mã hóa? như SO không? (IMHO)
Royi Namir

2
@RoyiNamir: Tôi không nói về cookie. Chữ ký được S3 sử dụng là một tham số cho yêu cầu HTTP, nhưng không phải là cookie, nó được tính toán lại cho mọi yêu cầu.
Greg Hewgill

Vì vậy, nếu tôi cần lưu một số thông tin về người dùng, tôi sẽ lưu nó ở đâu? trong db? Tôi không muốn chuyển từng yêu cầu tới db .... và tôi vẫn muốn sử dụng phần còn lại .... bạn có thể vui lòng giúp đỡ không?
Royi Namir

@RoyiNamir: Nếu bạn có câu hỏi cụ thể về cách hoàn thành một số mục tiêu, vui lòng đặt câu hỏi mới . Tôi không thể trả lời các câu hỏi bổ sung ở đây trong các ý kiến.
Greg Hewgill

10

Nhiều người không hiểu rõ các nguyên tắc REST, sử dụng mã thông báo phiên không có nghĩa là bạn luôn ở trạng thái, lý do để gửi tên người dùng / mật khẩu với mỗi yêu cầu chỉ để xác thực và tương tự để gửi mã thông báo (được tạo bởi đăng nhập xử lý) chỉ để quyết định xem khách hàng có quyền yêu cầu dữ liệu hay không, bạn chỉ vi phạm các tham vọng REST khi bạn sử dụng tên người dùng / mật khẩu hoặc mã thông báo phiên để quyết định dữ liệu nào sẽ hiển thị! thay vào đó, bạn phải sử dụng chúng chỉ cho mục đích (để hiển thị dữ liệu hoặc không hiển thị dữ liệu)

trong trường hợp của bạn, tôi nói CÓ, đây là RESTy, nhưng hãy thử tránh sử dụng các phiên php gốc trong API REST của bạn và bắt đầu tạo các mã thông báo băm của riêng bạn hết hạn theo thời gian xác định!


1
cảm ơn bạn. tại sao nên tránh phiên php gốc và sử dụng mã thông báo băm riêng thay thế?
Matthew

không phải bất kỳ lý do tuyệt vời nào tôi nói, chỉ để bảo mật hơn và kiểm soát nhiều hơn.
EvilThinker

Điều này là tốt hơn so với câu trả lời được chấp nhận. Ít nhất, nó chấp nhận đề xuất là RESTy, điều này có ý nghĩa. Tuy nhiên, tôi không thấy lý do tại sao thông tin được truyền có thể được sử dụng để ủy quyền người dùng phụ thuộc. Một số người dùng có thể có quyền truy cập vào một số dữ liệu và những người khác thì không. Điều đó không làm cho giao thức không RESTful.

8

Không, nó không bỏ lỡ vấn đề. ClientLogin của Google hoạt động chính xác theo cách này với ngoại lệ đáng chú ý là khách hàng được hướng dẫn đi đến "/ session" bằng phản hồi HTTP 401. Nhưng điều này không tạo ra một phiên, nó chỉ tạo ra một cách để khách hàng (tạm thời) tự xác thực mà không cần thông tin xác thực rõ ràng và để máy chủ kiểm soát tính hợp lệ của các thông tin tạm thời này khi thấy phù hợp.


11
@ unlorgiven3 Miễn là mã thông báo được trả về chỉ được sử dụng để xác thực người dùng và không được máy chủ sử dụng để liên kết người dùng với trạng thái khác được lưu trữ trên máy chủ, thì tôi thấy không có ràng buộc REST nào bị vi phạm.
Darrel Miller

4
@ unlorgiven3 Mã thông báo được máy chủ trả về thực chất là bằng chứng cho thấy người dùng nói họ là ai. Vì vậy, thay vì mỗi yêu cầu bao gồm tên người dùng và mật khẩu, mỗi yêu cầu bao gồm mã thông báo được xây dựng theo cách mà máy chủ có thể tự tin về tính chính xác của nó.
Darrel Miller

1
@ unsorgiven3, Darrel nói đúng. Mã thông báo được lặp lại sẽ phải được gửi bởi khách hàng trên mỗi yêu cầu HTTP, giống như trong xác thực cơ bản, tiêu hóa, cho đến khi mã thông báo hết hạn. Khi điều đó xảy ra, khách hàng có thể lặp lại đăng nhập, tùy ý yêu cầu người dùng xác thực hoặc bất cứ điều gì. Tôi có thể giải thích câu trả lời, nếu bạn muốn. chỉnh sửa: (Và cảm ơn vì đã theo kịp câu trả lời cho các câu hỏi cũ!)
mogsie

1
Không có vấn đề gì, mogsie, luôn luôn thú vị để thảo luận về những điều này :-) Tôi nghĩ tôi thấy các bạn đang đi đâu với điều này, tiếc là tôi không hiểu đủ về xác thực tiêu hóa để thực sự nắm bắt điều này (chủ yếu là tôi không biết hiểu cách mã thông báo được gửi lại mỗi yêu cầu HTTP, nhưng đó dường như là một chi tiết triển khai). Tuy nhiên, bây giờ tôi thấy tại sao phương thức này không vi phạm các nguyên tắc REST. Cảm ơn các câu trả lời!
Cướp

6
@ unlorgiven3, Điều này có thể giúp: mã thông báo là một phần thông tin đã ký. Vì vậy, nó là khép kín. Máy chủ có thể xác thực mã thông báo mà không cần kiểm tra trạng thái được lưu trữ trước đó. Vì vậy, nó chỉ là một trạng thái được lưu trữ trên máy khách và chuyển qua lại.
Iravanchi

5

Được rồi, tôi nhận được rằng xác thực HTTP được thực hiện tự động trên mỗi tin nhắn - nhưng bằng cách nào?

"Ủy quyền:" Tiêu đề HTTP được gửi bởi khách hàng. Hoặc cơ bản (văn bản thuần túy) hoặc tiêu hóa.

Sẽ rất tệ nếu có một dịch vụ REST, giả sử, / phiên, chấp nhận yêu cầu GET, trong đó bạn chuyển tên người dùng / mật khẩu như một phần của yêu cầu và trả lại mã thông báo phiên nếu xác thực thành công, có thể sau đó được thông qua cùng với các yêu cầu tiếp theo? Điều đó có ý nghĩa từ quan điểm REST hay là thiếu điểm đó?

Toàn bộ ý tưởng của phiên là tạo ra các ứng dụng trạng thái bằng giao thức không trạng thái (HTTP) và máy khách câm (trình duyệt web), bằng cách duy trì trạng thái ở phía máy chủ. Một trong những nguyên tắc REST là "Mọi tài nguyên đều có địa chỉ duy nhất bằng cách sử dụng cú pháp chung để sử dụng trong các liên kết hypermedia" . Biến phiên là thứ không thể truy cập thông qua URI. Ứng dụng RESTful thực sự sẽ duy trì trạng thái về phía khách hàng, gửi tất cả các biến cần thiết qua HTTP, tốt nhất là trong URI.

Ví dụ: tìm kiếm với phân trang. Bạn muốn có URL ở dạng

http://server/search/urlencoded-search-terms/page_num

Nó có nhiều điểm chung với các URL có thể đánh dấu


4
Tuy nhiên, thông tin xác thực cũng không thể truy cập được thông qua URI - mọi người đang nói về việc gửi thông tin xác thực như một phần của tiêu đề yêu cầu. Làm thế nào khác với việc bao gồm một mã thông báo phiên với yêu cầu? Tôi không nói sử dụng mã thông báo phiên trong URI, nhưng trong dữ liệu được truyền trong yêu cầu.
Cướp

Xác thực thiết lập nếu bạn được phép thực hiện hành động đó và trong ứng dụng RESTful sẽ không ảnh hưởng đến kết quả của nó.
vartec

4
Mã thông báo phiên cũng sẽ thiết lập nếu bạn được ủy quyền thực hiện hành động đó. Bạn có nghĩa là nó sẽ không ảnh hưởng đến kết quả của nó? Nếu người gọi không được ủy quyền, họ sẽ gặp lỗi Không được ủy quyền. Điều tương tự với mã thông báo phiên. Tôi thực sự không thấy sự khác biệt?
Cướp

3
Không, mã thông báo phiên là một điều khiển để trạng thái được lưu trên máy chủ. Đó không phải là RESTful. Đối với Không được ủy quyền, tôi không thấy đó là kết quả. Tôi muốn xem xét rằng đó là một ngoại lệ (như trong thử / bắt).
vartec

Đủ công bằng, vartec - điều đó có ý nghĩa. Cảm ơn đã theo lên!
Cướp

3

Tôi nghĩ đề xuất của bạn là ổn, nếu bạn muốn kiểm soát thời gian sống của phiên khách. Tôi nghĩ rằng kiến ​​trúc RESTful khuyến khích bạn phát triển các ứng dụng phi trạng thái. Vì @ 2pence đã viết "mỗi yêu cầu HTTP phải tự mang đủ thông tin cho người nhận để xử lý nó hoàn toàn hài hòa với bản chất không trạng thái của HTTP" .

Tuy nhiên, không phải lúc nào cũng như vậy, đôi khi ứng dụng cần thông báo khi khách hàng đăng nhập hoặc đăng xuất và để duy trì các tài nguyên như khóa hoặc giấy phép dựa trên thông tin này. Xem câu hỏi tiếp theo của tôi cho một ví dụ về trường hợp như vậy.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.