使用令牌(Java)保护REST Web服务

这个问题在某种程度上与以下相关问题有关。 但是,我需要更清楚一些方面和一些其他信息。 请参阅: REST Web服务身份validation令牌实现

背景:

  • 我需要使用令牌为REST Web服务实现安全性
  • Web服务旨在与Java客户端一起使用。 因此,表单身份validation和凭据弹出窗口无用。
  • 我是REST安全和加密的新手

这是我到目前为止所理解的:

第一次请求:

  1. 用户建立https连接(或容器使用301确保https)
  2. 用户POST用户名和密码登录服务
  3. 如果凭证有效,我们:
    • 生成随机临时令牌
    • 将随机令牌存储在服务器上,将其映射到实际用户名
    • 使用仅为服务器所知的对称密钥加密令牌
    • 哈希加密的令牌
    • 将加密的令牌和哈希发送到客户端

对于后续请求:

  1. 客户端发送此加密令牌和哈希组合(使用基本的用户名字段?)
  2. 我们确保加密的令牌不会被哈希篡改,然后解密
  3. 我们检查session-tracking-table中的解密令牌是否有未过期的条目并获取实际的用户名(到期时间由代码管理?)
  4. 如果找到用户名,则根据允许的角色配置允许的操作

更多细节:

  1. 由于客户端是java客户端,因此第一个请求可以是包含凭据的POST。 但是,这似乎可能会在https建立之前公开凭据。 因此,是否应该对安全资源进行虚拟GET,以便首先建立https?
  2. 假设上面是必需的,第二个请求是带有凭据的LoginAction POST。 此请求是手动处理的(不使用容器的授权)。 这是正确的吗?
  3. 上面的LoginAction返回用户加密令牌+哈希的组合
  4. 用户将其设置为BASIC身份validation机制使用的标头(字段用户名)
  5. 我们实现了一个JAASRealm来解密和validation令牌,并找到允许的角色
  6. 其余的授权过程由具有web.xml中定义的WebResourceCollection的容器负责

这是正确的方法吗?

为什么不将它简化为以下内容?

第一次请求:

  1. 用户建立与服务器的HTTPS连接(服务不在任何其他端口上侦听)和POST登录服务的凭据。
  2. 服务器回复HSTS标头以确保所有进一步的通信都是HTTPS。
  3. 如果凭证有效,我们:
    • 生成使用CSPRNG安全生成的随机临时令牌。 使这个足够长,以确保安全(128位)。
    • 将随机令牌存储在服务器上,将其映射到实际用户名。
    • 将随机令牌发送到客户端

对于后续请求:

  1. 客户端通过HTTPS在自定义HTTP标头中发送令牌。
  2. 令牌位于数据库中并映射到用户名。 如果找到基于允许的角色和允许的操作的访问权限。
  3. 如果未找到,则认为用户未经身份validation,并且必须再次使用登录服务进行身份validation才能获得新令牌。

在服务器端,令牌将以失效日期存储。 在每次访问服务时,将更新此日期以创建滑动到期日期。 将会有一个每隔几分钟运行一次的作业来删除过期的令牌,并且检查令牌以查找有效会话的查询只会检查那些未被认为已过期的查询(如果计划的作业因任何原因失败,则会阻止永久会话)。

没有必要对数据库中的令牌进行散列加密 – 除了通过默默无闻的安全性之外,它不会增加真正的价值。 你可以哈哈哈哈。 这可以防止设法访问会话数据表的攻击者劫持现有用户会话。

方法看起来不错。 不太安全。 让我强调一下该请求可能带来的一些攻击。

  1. 在POST请求中的中间人攻击,用户可以篡改请求,服务器无法确保数据不被篡改。

  2. 重播攻击:在此,攻击者不会篡改请求。 攻击者轻敲请求并在短时间内多次将其发送给服务器,虽然这是一个有效的请求,服务器多次处理请求,这是不需要请阅读Nonce。

  3. 在第一步中,用户将他的凭证(即用户名和密码)发送到登录服务,如果您有基于Web的应用程序也使用相同的密码,则可能是危险的。 如果密码被泄露,API和Web上的所有内容都暴露出来,请使用不同的PIN进行API访问。 另外,确保您指定的解密令牌,在一定时间后过期。

  4. 确保服务(应用程序服务器)tomcat。 如果发生内部错误,jboss永远不会返回服务器页面,这会为攻击者提供部署应用程序的服务器的额外信息。

– 基于第二个post修改 –
是的,如果您使用相互SSL,则是正确的,但如果是单向访问,则您没有客户端证书。 如果你只是加倍确保请求中的所有内容,就像签名(签名)SOAP,强大的数据传输机制之一那样。 但重放攻击是HTTPS的一种可能性,只需处理即可。 rest使用令牌加密是好的。 为什么不让客户端用密码解密令牌并返回解密输出,你可以validation输出,如果它存在于你的数据库中? 这种方法即使是HTTPS,用户也不会通过网络发送密码?