在REST中对对象执行操作(订阅/标记为已读/等)

时间:2015-02-04 15:32:28

标签: rest

我正在阅读Creating an efficient REST API,我理解并同意该文件的大部分内容。

我目前正在实施Twitter克隆,数据库中的每个推文对象都有一个读者列表(用户ID)。

根据该文件,似乎对此的要求类似于:

PATCH /tweet
{read: true}

但是read不是推文的实际属性。相反,这实际上会使用当前经过身份验证的用户更新推文上的readers列表。这是对的吗?

这也意味着用户可以使用相同的API路径潜在地对推文执行其他操作,但用户实际上不能以任何方式更新/ PATCH推文而不是标记它们或不读。

此外,只有经过身份验证的用户才能执行此操作,并且只应更新他们的读者列表。该文档说您不应该在API中处理状态,这意味着没有会话 - 但是显然需要进行身份验证。似乎每次都应该发送身份验证/授权令牌,但我不知道在某些情况下这与会话cookie有何实质性的差异。请求实际应该是这样的暗示:

PATCH /tweet
<Authentication-Header>
{userId: userId, read: true}

即。 API本身是否应该尝试使用会话中的信息并强制请求提供登录的用户信息?有没有更好的方法来构建它?

2 个答案:

答案 0 :(得分:0)

使用cookie的问题在于您将状态移到URI之外并进入cookie。

RESTful API应具有URI中所需的所有状态。信不信由你,但这确实让事情变得更容易,因为如果你要创建一个新的客户端库,你就不必处理cookie。

不使用cookie也可以很好地与其他设备集成。假设我在浏览器上查看RESTful网页,然后我想在我的帐户上显示某人。我可以通过电子邮件向他们发送URI / some-uri?authToken = 1234,他们将能够查看我的帐户,而无需我提供密码!

令牌过期后,他们将无法再访问该帐户。

修改

如果您将令牌放在POST正文中,则用户无法通过在地址栏中输入来访问页面。他们会被告知他们没有被授权。所以,是的,你需要在URI中。如果你真的想要,你可以使用cookie,但除了它是一种解决方法。

您可以通过公开登录资源来获取登录令牌。要登录,您需要将您的用户名和密码发送到:

POST /login

这会创建一个/login/{token}资源。您可以使用此令牌(如果需要,甚至可以使用完整的URI)来对服务器进行身份验证。

当您想要退出时,请致电

`DELETE /login/{token}` 

如果您现在尝试使用该令牌,则API应返回“未经过身份验证的”#39;因为令牌不再存在。

答案 1 :(得分:0)

取决于需要什么级别的身份验证。

保持简单。无需复杂化。

你真的需要“国家”吗?您有一个数据库,您必须检查用户身份验证。为什么不使用数据库记录?

如果客户端在其Web服务器上使用API​​,则只需检查请求的IP地址。

IP地址不能被欺骗,因此是一个非常好的身份验证因素。添加用户名,您就可以进行多重身份验证

使用PHP的客户端说明

$user = 'joe';
$param = 1;

file_get_contents("http://apisite.com/api/function/?id=$user&param=$param");

HTML表单,也许您必须限制访问权限,但如果他们将页面命名为页面并不容易猜到,那么您就拥有它。:

<form action="http://apisite.com/api/function/">
<input type="textarea" name="tweet"/>
<input type="hidden" name="user" value="joe" />
<input type="hidden" name="param" value="1" />
</form>

如果要在PHP中完成API:

PHP

<?php
header('Content-Type: text/plain; charset=utf-8');
header('Cache-Control: max-age=0');
$ip =  $_SERVER['REMOTE_ADDR'];
$results = mysqli_query("SELECT COUNT(*),`user`,`state` FROM `Profile` WHERE `ip` LIKE '$ip' ");
$row = mysql_fetch_array($results, MYSQL_NUM);
if ($row[0] == 1 && $row[1]==$_GET['user']) && $row[2]==1){
  $tweet = trim($_GET['tweet']);
  $param = $_GET['param'];
  include('tweet.php');
  echo "Sent\n";
}
else{
  echo "Not Sent\n";
}
?>