我正在设计一个Web应用程序,然后停下来思考如何将我的api设计为RESTful Web服务。目前,我的大部分URI都是通用的,可能适用于各种网络应用程序:
GET /logout // destroys session and redirects to /
GET /login // gets the webpage that has the login form
POST /login // authenticates credentials against database and either redirects home with a new session or redirects back to /login
GET /register // gets the webpage that has the registration form
POST /register // records the entered information into database as a new /user/xxx
GET /user/xxx // gets and renders current user data in a profile view
POST /user/xxx // updates new information about user
我有一种感觉,在搜索SO和google后,我在这里做了很多错误。
从/logout
开始,也许是因为我没有GET
任何事情 - POST
对/logout
的请求可能更合适,摧毁会话,以及然后GET
重定向。 /logout
一词应该留下吗?
/login
和/register
怎么样?我可以将/register
更改为/registration
,但这不会改变我的服务从根本上如何运作 - 如果它有更深层次的问题。
我现在注意到我从未公开/user
资源。也许这可以以某种方式利用。例如,请使用用户myUser
:
foo.com/user/myUser
或
foo.com/user
最终用户不需要URI中的额外详细程度。但是,哪一个在视觉上更吸引人?
我在这里注意到关于这个REST业务的一些其他问题,但如果可能的话,我真的很感谢我在这里提出的一些指导。
谢谢!
更新
我还想提出一些意见:
/user/1
VS
/user/myUserName
答案 0 :(得分:105)
RESTful可用作构建网址的指南,您可以创建会话和用户资源:
GET /session/new
获取具有登录表单的网页POST /session
验证针对数据库的凭据DELETE /session
销毁会话并重定向到/ GET /users/new
获取具有注册表单的网页POST /users
将输入的信息作为新的/ user / xxx GET /users/xxx
//在个人资料视图中获取并呈现当前用户数据POST /users/xxx
//更新有关用户的新信息这些可以是复数或单数(我不确定哪一个是正确的)。我通常使用/users
作为用户索引页面(如预期的那样),并使用/sessions
查看谁登录(如预期的那样)。
使用网址中的名称而不是数字(/users/43
与/users/joe
)通常是希望对用户或搜索引擎更友好,而不是任何技术要求。要么很好,但我建议你保持一致。
我认为如果你选择注册/登录/注销或sign(in|up|out)
,它就不能与其他术语一起使用。
答案 1 :(得分:55)
有一件事特别突出,因为没有REST-ful:使用GET请求注销。
(来自http://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol#Safe_methods)
某些方法(例如,HEAD,GET,OPTIONS和TRACE)被定义为安全,这意味着它们仅用于信息检索,不应更改服务器的状态。换句话说,它们不应该具有副作用,除了相对无害的效果,例如日志记录,缓存,横幅广告的提供或递增网络计数器。 [...]
服务器的[... H]和[GET请求]在技术上没有任何限制。因此,粗心或有意的编程可能会导致服务器上的重大变化。这是不鼓励的,因为它可能导致Web缓存,搜索引擎和其他自动代理[...] 的问题
对于注销和重定向,您可以在注销URI上发布一条帖子,将303响应重定向到注销后页面。
http://en.wikipedia.org/wiki/Post/Redirect/Get
http://en.wikipedia.org/wiki/HTTP_303
编辑以解决网址设计问题:
“我如何设计我的资源?”对我来说是一个重要的问题; “我该如何设计我的网址?”是两个方面的考虑因素:
如果可能,用户将看到的网址不应该太丑陋和有意义; 如果您希望将cookie发送到某些资源而不是其他资源,您需要构建路径和cookie路径。
如果JRandomUser
想要查看自己的个人资料,并且您希望网址比foo.com/user/JRandomUser
或foo.com/user/(JRandom's numeric user id here)
更漂亮,那么您可以创建一个单独的网址,供用户查看他们自己的信息:
GET foo.com/profile /*examines cookies to figure out who
* is logged in (SomeUser) and then
* displays the same response as a
* GET to foo.com/users/SomeUser.
*/
在这个问题上我会比智慧更容易宣称无知,但这里有一些资源设计考虑因素:
答案 2 :(得分:48)
会话不是RESTful
是的,我知道。它正在完成,通常使用OAuth,但实际上会话不是RESTful。您不应该主要拥有/ login / logout资源,因为您不应该有会话。
如果您要这样做,请将其设为RESTful。资源是名词,/ login和/ logout不是名词。我会和/ session一起去。这使得创建和删除成为更自然的行为。
POST与GET的会话很容易。如果您将用户/密码作为变量发送,我会使用POST,因为我不希望将密码作为URI的一部分发送。它将显示在日志中,并可能通过电线暴露。您还冒着让GET args限制软件失败的风险。
我通常使用Basic Auth或没有使用REST服务的Auth。
创建用户
这是一个资源,所以你不需要/注册。
使用哪种ID是一个难题。你必须考虑强制执行唯一性,关于重复使用DELETEd的旧ID。例如,如果要回收id(如果可能的话),则不希望在后端使用这些id作为外键。您可以查找外部/内部ID转换,以减轻后端要求。
答案 3 :(得分:20)
答案 4 :(得分:3)
我相信这是一种RESTful身份验证方法。对于LogIn,您使用HttpPut
。当提供密钥时,此HTTP方法可用于创建,并且重复调用是幂等的。对于LogOff,您在HttpDelete
方法下指定相同的路径。没有使用动词。适当的收集多元化。 HTTP方法支持此目的。
[HttpPut]
[Route("sessions/current")]
public IActionResult LogIn(LogInModel model) { ... }
[HttpDelete]
[Route("sessions/current")]
public IActionResult LogOff() { ... }
如果需要,您可以将当前电流替换为活动状态。
答案 5 :(得分:2)
我建议使用类似于Twitter的用户帐户网址,其中用户的帐户网址类似于foo.com/myUserName
,就像您可以使用网址https://twitter.com/joelbyler
我不同意退出需要POST。作为API的一部分,如果您要维护会话,那么UUID形式的会话ID可能会用于跟踪用户并确认正在采取的操作是否已获得授权。然后即使是GET也可以将会话ID传递给资源。
简而言之,我建议您保持简单,URL应该简短而难忘。