Web Services RESTfully设计/登录或/注册资源?

at0kjp5o  于 2022-11-15  发布在  其他
关注(0)|答案(7)|浏览(108)

我正在设计一个Web应用程序,然后停下来思考我的API应该如何设计成REST风格的Web服务。目前,我的大多数URI都是通用的,可能适用于各种Web应用程序:

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和谷歌。
/logout开始,也许因为我真的不知道GET的任何东西-它可能是更合适的POST一个请求到/logout,销毁会话,然后GET重定向。
那么/login/register呢?我可以将/register更改为/registration,但这不会改变我的服务的基本工作方式--如果它有更深层次的问题的话。
现在我注意到我从来没有公开过/user资源,也许这一点可以被利用,例如,以用户myUser为例:

foo.com/user/myUser

foo.com/user

最终用户不需要URI中的额外冗余。但是,哪一个在视觉上更吸引人呢?
我注意到这里还有一些关于REST业务的其他问题,但是如果可能的话,我真的很感激关于我在这里所做的事情的一些指导。
谢谢你!

更新日期:

我还想就以下问题提出一些意见:

/user/1

对比

/user/myUserName
8fsztsew

8fsztsew1#

RESTful可用作构建URL的指导原则,您可以将 * 会话 * 和 * 用户 * 资源:

  • GET /session/new获取包含登录表单的网页
  • POST /session根据数据库验证凭据
  • DELETE /session销毁会话并重定向到/
  • GET /users/new获取包含注册表单的网页
  • POST /users将输入的信息记录到数据库中,作为新的/用户/xxx
  • GET /users/xxx//获取并呈现配置文件视图中的当前用户数据
  • POST /users/xxx//更新有关用户的新信息

我通常使用/users作为用户索引页面(如预期的那样),使用/sessions查看谁登录了(如预期的那样)。
在URL中使用名称而不是数字(/users/43/users/joe)通常是出于对用户或搜索引擎更友好的愿望,而不是任何技术要求。两者都可以,但我建议你保持一致。
我认为,如果你使用注册/登录/注销或sign(in|up|out),它就不能很好地与其他术语一起工作。

wkyowqbh

wkyowqbh2#

有一件事特别突出,因为它不是REST式的:使用GET请求注销。
(from http://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol#Safe_methods)
一些方法(例如HEAD、GET、OPTIONS和TRACE)被定义为安全的,这意味着它们只用于信息检索,不应该改变服务器的状态。换句话说,它们不应该有副作用,除了相对无害的影响,如日志记录、缓存、提供横幅广告或增加Web计数器。[...]
[...服务器对GET请求的处理在技术上没有任何限制。因此,粗心或故意的编程可能会导致服务器上的不寻常的变化。这是不鼓励的,因为它可能会导致Web缓存、搜索引擎和其他自动代理的问题。
至于注销和重定向,您可以在您的注销URI上给予一个303响应,重定向到注销后的页面。
http://en.wikipedia.org/wiki/Post/Redirect/Get
http://en.wikipedia.org/wiki/HTTP_303
编辑以解决URL设计问题:
“我如何设计我的资源?”对我来说是一个重要的问题;“我如何设计我的URL?”是两个方面的考虑事项:
如果可能的话,用户将看到的URL不应该太难看和有意义;如果您希望在对某些资源的请求中发送Cookie,而不希望在对其他资源的请求中发送Cookie,则需要构建路径和Cookie路径。
如果JRandomUser想查看他自己的个人资料,而您希望URL比foo.com/user/JRandomUserfoo.com/user/(JRandom's numeric user id here)更漂亮,则可以为用户创建一个单独的URL,让用户查看自己的信息:

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.
                     */

在这个问题上,我会更容易地声称无知而不是智慧,但这里有一些资源设计考虑事项:
1.消费者:哪些资源应该直接在浏览器中查看,通过XHR加载,或者由其他类型的客户端访问?
1.访问/身份:响应依赖于cookie还是引用者?

brjng4g3

brjng4g33#

会话不是REST风格的

  • 是的,我知道。这已经在做了,通常是用OAuth,但实际上会话不是REST风格的。你不应该有/login /logout资源,主要是因为你不应该有会话。
  • 如果你要做的话,让它成为RESTful。资源是名词,/login和/logout不是名词。我会选择/session。这使得创建和删除成为一个更自然的操作。
  • POST和GET的会话比较简单。如果你把用户/密码作为变量发送,我会使用POST,因为我不想把密码作为URI的一部分发送。它会出现在日志中,并可能通过网络暴露。你也会冒着软件在GET参数限制上失败的风险。
  • 我通常在REST服务中使用基本身份验证或不使用身份验证。
    正在创建用户
  • 这是一个资源,所以你不需要/注册。
  • POST /user -如果请求者无法指定ID,则创建用户
  • PUT /user/xxx -创建或更新用户(假设您事先知道ID)
  • GET /user -列出x个用户ID
  • GET /user/xxx -获取ID为xxx的用户的详细信息
  • DELETE /user/xxx -删除ID为xxx的用户
  • 使用哪种ID是一个很难的问题。你必须考虑强制唯一性,考虑重用被删除的旧ID。例如,如果ID要被回收(如果可能的话),你不想在后端使用这些ID作为外键。你可以查找外部/内部ID转换,以减轻后端要求。
fbcarpbf

fbcarpbf4#

我将简单地谈谈我为我的客户集成各种REST Web服务的经验,无论它是用于移动的应用程序还是用于服务器到服务器的通信,以及为其他人构建REST API。以下是我从其他人的REST API以及我们自己构建的REST API中收集的一些观察结果:

  • 当我们说API时,它通常指的是一组编程接口,而不一定是表示层。REST也是以数据为中心的,而不是表示驱动的。也就是说,大多数REST以JSON或XML的形式返回数据,很少返回特定的表示层。这种特性这意味着相同的Web服务可以用HTML呈现,iOS、Android甚至用作服务器到服务器组合。
  • 将HTML和REST结合起来作为一个URL是非常罕见的。默认情况下,REST是作为服务的思想,没有表示层。使用Web服务的人的工作是根据他们的需要从他们调用的服务中呈现数据。在这一点上,下面的URL不符合我迄今为止遇到的大多数基于REST的设计(也不是那些来自Facebook或Twitter的标准)
GET  /register // gets the webpage that has the registration form
  • 继续上一点,基于REST的服务进行重定向也是不常见的(我也没有遇到过),如下所示:
GET  /logout   // destroys session and redirects to /
POST /login    // authenticates credentials against database and either redirects home with a new session or redirects back to /login

由于REST被设计为服务,登录和注销等功能通常会返回成功/失败结果(通常为JSON或XML数据格式),然后消费者将对这些结果进行解释。

  • 在REST中,URL表示所执行的操作。因此,我们应该尽可能地消除歧义。(例如/register),这样的设计会在所提供的服务中引入模糊性,并可能使服务的使用者感到困惑。例如,下面介绍的URL并不适合基于REST的服务
GET  /register // gets the webpage that has the registration form
POST /register // records the entered information into database as a new /user/xxx

以上是我所谈的一些观点,希望能给大家提供一些启示。
至于REST的实现,以下是我遇到的典型实现:

GET  /logout

在后台执行注销,返回JSON表示操作成功/失败

POST /login

将凭据提交到后端。返回成功/失败。如果成功,通常还将返回会话令牌以及配置文件信息。

POST /register

将注册提交到后端。返回成功/失败。如果成功,通常视为成功登录,或者您可以选择将注册作为一个单独的服务

GET  /user/xxx

获取用户配置文件并返回用户配置文件的JSON数据格式

POST /user/xxx 
// renamed to 
POST /updateUser/xxx

以JSON格式发布更新后的配置文件信息,并在后端更新信息。向调用方返回成功/失败

ldxq2e6h

ldxq2e6h5#

我相信这是一种RESTful的身份验证方法。对于LogIn,您使用HttpPut。当提供密钥时,可以使用此HTTP方法进行创建,并且重复调用是幂等的。对于LogOff,您在HttpDelete方法下指定相同的路径。不使用动词。正确的集合复数。HTTP方法支持此目的。

[HttpPut]
[Route("sessions/current")]
public IActionResult LogIn(LogInModel model) { ... }

[HttpDelete]
[Route("sessions/current")]
public IActionResult LogOff() { ... }

如果需要,您可以将current替换为active。

7fhtutme

7fhtutme6#

我建议使用类似于twitter的用户帐户URL,其中用户帐户URL类似于foo.com/myUserName,就像您可以通过URL https://twitter.com/joelbyler访问我的twitter帐户一样
我不同意注销需要POST。作为API的一部分,如果你要维护一个会话,那么UUID形式的会话ID可以用来跟踪用户,并确认所采取的操作是授权的。然后甚至GET也可以沿着会话ID传递给资源。
总之,我建议你保持简单,网址应该是短的一个难忘的。

x7rlezfr

x7rlezfr7#

ReST API本身代表Representational State Transfer,您可以在数据库之间来回传输资源的状态。
因此,每个动词都应该分配给一个资源,而在/user/login中,login似乎不是将login定义为资源的正确示例,其中user是实际的资源。
这是我所遵循的,这可能有点道理。

POST /user {userObject} -> To create user resource, i.e, Signup.
POST /user/:username {password: `${user_password}`} -> To identify the user by the username and authenticate using the password, i.e, Login.
GET /user -> To list all users from your table/collection
GET /user/:id -> To get details of a particular user (:id can be replaced with :username, or :email or the primary key you have setup for the user.)
PUT /user/:id -> To Update the user object.
DELETE /user/:id -> To delete the user object.

以上格式如下:[HTTP predicate ]/资源路径{正文(如果需要 *)}.
而对于注销,状态再次发挥作用,即在登录时不传输会话,而是JWT/AccessToken,这是一种客户端授权机制,您将其存储在前端作为本地存储,如果注销时未过期,则只需将其删除。
你不会有一个注销路径,这需要在你的API上请求,而是得到的到期时间处理或删除只在前端。

相关问题