RESTful登录失败:返回401或自定义响应

时间:2012-07-30 01:36:51

标签: http rest login http-response-codes

这是一个概念性问题。

我有一个客户端(移动)应用程序,需要支持针对RESTful Web服务的登录操作。由于Web服务是RESTful,这相当于客户端接受用户的用户名/密码,验证服务的用户名/密码,然后只记得发送该用户名/密码以及所有后续请求。

此Web服务中的所有其他响应均以JSON格式提供。

问题是,当我查询Web服务只是为了找出给定的用户名/密码是否有效时,Web服务是否总是以JSON数据响应告诉我它成功或不成功,或者它应该返回HTTP 200就好了凭据和凭据错误凭据上的HTTP 401。

我问的原因是,即使您只是询问凭据是否有效,其他一些RESTful服务也会使用401作为错误的凭据。但是,我对401响应的理解是,它们代表了一个没有有效凭据就无法访问的资源。但是登录资源应该对任何人都可以访问,因为登录资源的全部目的是告诉你你的凭据是否有效。

换句话说,在我看来,请求如下:

myservice.com/this/is/a/user/action 
如果提供了错误的凭据,

应返回401。但是请求如下:

myservice.com/are/these/credentials/valid

永远不应该返回401,因为该特定URL(请求)在有或没有有效凭据的情况下被授权。

我想在这方面听到一些合理的意见。处理此问题的标准方法是什么,是处理逻辑上合适的标准方法吗?

4 个答案:

答案 0 :(得分:102)

首先关闭。 401是发生失败登录时发送的正确响应代码。

  

401未经授权       与403 Forbidden类似,但专门用于需要身份验证且失败或尚未提供的情况。响应必须包含WWW-Authenticate头字段,其中包含适用于所请求资源的质询。

你的混淆,myservice.com/are/these/credentials/valid在你做一次检查时发回401,我认为这是基于这样一个事实,即在REST中做布尔请求经常是RESTful约束错误的。每个请求都应该返回一个资源。在RESTful服务中做布尔问题是一个滑落到RPC的单点。

现在我不知道你所看到的服务是如何表现的。但解决这个问题的一个好方法是使用类似于Account对象的东西来尝试获取。如果您的凭据是正确的,您将获得Account对象,如果您不想浪费带宽只是为了“检查”,您可以在同一资源上执行HEAD。

帐户对象也是存储所有那些讨厌的布尔值的好地方,否则创建单独的资源会很棘手。

答案 1 :(得分:14)

401仅在请求需要授权头字段且授权失败时才发送。由于Login API不需要授权,因此我认为401是错误的错误代码

根据此处的https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html

标准

* 10.4.2 401未经授权

请求需要用户身份验证。响应必须包含WWW-Authenticate标头字段(第14.47节),其中包含适用于所请求资源的质询。客户可以用合适的授权头域(第14.8节)重复请求。如果请求已包含授权凭证,则401响应指示已拒绝这些凭证的授权。如果401响应包含与先前响应相同的质询,并且用户代理已经尝试了至少一次身份验证,则应该向用户提供响应中给定的实体,因为该实体可能包括相关的诊断信息。 HTTP访问身份验证在“ HTTP身份验证:基本和摘要访问身份验证” [43]中进行了说明。*

答案 2 :(得分:0)

返回409,并显示正确的错误消息。

答案 3 :(得分:0)

如果 401 响应代码误导用户身份验证,API 可以为成功和失败的身份验证发送 HTTP 状态代码 200 OK,但在身份验证成功响应上设置自定义标头,并在登录失败时省略该标头。

客户端可以检查头部是否存在并决定动作。

示例:SpringBoot API 响应

登录成功时调用 OK 将标题“gotyouin”设置为一个值(任何东西)。调用 failed 不会添加标头,客户端可以将此视为失败的登录尝试。

public class LoginResponseEntityHelper {
   public static ResponseEntity<?> ok(String token) {
       return ResponseEntity.status(HttpStatus.OK).header("gotyouin", token).body(null);
    }

    public static ResponseEntity<?> failed() {
        return ResponseEntity.status(HttpStatus.OK).body(null);
    }}
相关问题