0

我正在为非关键数据开发一个小型 REST 网络服务,主要由智能手机应用程序访问。为了限制用户对其个人数据的访问(授权不需要组或角色),我需要实现某种基本身份验证。

由于服务将通过 HTTP 访问,因此使用 HTTP-Authentification 似乎不是一个好主意,因为用户名和密码将在每个请求中以明文形式发送,并且需要存储在客户端设备上。

因此,我的想法是通过以下方式实现身份验证:

  1. 用户使用我的网络服务的登录方法通过他们的用户名/密码登录
  2. 此方法检查用户名/密码组合的有效性(基于包含加盐和散列密码的数据库)
  3. 如果登录成功,则将用户的id(数据库表的主键)作为属性存储在会话中
  4. 在以下请求中,此属性用于对用户进行身份验证

在代码中,我的登录方法如下所示:

User user = this.authentificate(username, password);
HttpSession session = request.getSession(true);
if (user != null)
   session.setAttribute("UserId", user.getId());
else
   session.invalidate();

之后,我将能够根据会话对用户进行身份验证:

int userId = (int) request.getSession().getAttribute("UserId");
User currentUser = getUserById(userId);

这种方法是否可以被视为“安全”(不可能进行简单的会话劫持 - 据我了解https://stackoverflow.com/a/5838191/232175,属性值不会离开服务器)?
有什么缺点或替代方案吗?

4

1 回答 1

2

关于在会话中存储用户标识,我认为可以,但是您还有另一个问题。

首先,我假设登录方法将通过 HTTPS,否则用户名和密码将以明文形式发送到登录方法,而您又回到了之前遇到的相同问题。

其次,如果登录方法是通过 HTTPS,那么会话 cookie 将是一个 HTTPS cookie,并且所有其他 API 调用也需要通过 HTTPS。如果后续调用是通过 HTTP 进行的,他们将获得一个新的会话 cookie,并且用户 ID 在该会话中将不可用。

如果您真的想要没有 HTTPS 的安全身份验证,则需要使用共享秘密签名方案(例如 HMAC)或 RSA 等非对称签名系统来让客户端签署请求,然后在服务器端验证这些签名请求。

于 2012-10-18T15:30:20.383 回答