我正在构建一个ASP.NET Web API,我目前正在实现非常基本的用户帐户。我有User
模型,其中只包含Email
和Password
字段,我有一个UserController
类,其操作如下:
// POST: api/Users
[ResponseType(typeof(User))]
public IHttpActionResult PostUser(User user)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
db.Users.Add(user);
db.SaveChanges();
return CreatedAtRoute("DefaultApi", new { id = user.Id }, user);
}
一切都很完美,除非我POST /api/Users
我在响应正文中发回了密码字段:
{
"Id":2,
"Email":"dummy@test.com",
"Password":"$2a$12$jTACgOlm2eO/OYcV5wrDnO2dmsnbWVnsCRzX1WfQKGsY4sYvh16gm"
}
如何确保敏感字段(如用户密码)永远不会在响应中输出?我更喜欢在模型级别上执行它的方法,这样我就不会忘记在控制器中实现它。
答案 0 :(得分:3)
一种选择是在客户端和服务器之间进行通信时始终使用Data Transfer Object (DTO)。来自Web Api团队的this article给出的示例与您的问题非常相似。
我会创建一个UserDTO
,它不会包含任何我想要在我的客户端和服务器之间传输的敏感数据。
这就是大多数API工作的方式,例如,Facebook通过this API call传递的用户不是来自其域的用户,而是用户的表示,只需要所需的信息。
使用DTO,您可以精确控制传输的内容,降低数据大小并防止安全信息泄露。
更新:如果你走这条路,你可能想要使用AutoMapper,它会减少你必须做的对象到对象的数量相当< /强>
答案 1 :(得分:1)
删除创建单独模型所需的一些值太多了,最好在返回之前清理数据,比如说
db.SaveChanges();
user.Password = String.Empty;
user.anyproperty = null;
return CreatedAtRoute("DefaultApi", new { id = user.Id }, user);
答案 2 :(得分:1)
约翰,
CreatedAtRoute方法用于返回新创建的资源的URI。例如,如果您要创建新产品,则可能会看到返回为api / products / 1234。该方法还将返回您提供的序列化对象作为第三个参数。该方法不知道您要返回的对象的性质,因此它不会将任何字段识别为敏感字段。
在您的情况下,您可以从用户对象中清除密码字段,或者返回不包含此字段的完全不同的对象。您不必被迫返回刚刚创建的同一对象。
最诚挚的问候, 丹尼尔