Django Rest框架 - 为什么尝试使用不正确的凭据登录用户时返回200状态代码? [英] Django Rest Framework - Why is a 200 status code returned when trying to login a user using incorrect credentials?

查看:206
本文介绍了Django Rest框架 - 为什么尝试使用不正确的凭据登录用户时返回200状态代码?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是我的URLs.py:

  url(r'^ api-auth /',include('rest_framework urls',
namespace ='rest_framework')),

我有一个表单在我的用户可以键入用户名和密码的主页。当单击提交按钮时,AngularJS会向用户对象(用户名和密码)发送一个POST请求到api-auth / login /:

 code> $ http.post(/ api-auth / login /,self.loginuser)
.error(function(data,status,headers,config){
console.log数据);
});

当用户提交不正确的用户名和密码(不存在或不存在的用户名和密码)匹配),Django Rest Framework返回200 OK而不是204 No Content,404 or 401 Unauthorized(在这篇文章中,它表示401是正确的状态代码返回:如果用户尝试登录,返回的相应HTTP状态代码是什么不正确的用户名/密码,但格式正确?)。



根据这里: http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html 在9.5节POST中,它说在这种情况下,200(OK)或204(无内容)是适当的响应状态,取决于响应是否包括描述结果的实体。



如果数据存在,我处理错误并记录数据(我做了console.log (数据)在JS),但没有数据记录,这意味着(从我的理解)没有数据发送/响应不包括描述结果的实体。



那么DjangoRestFramework如何返回200而不是204 No Content(或404或401,这是什么应该根据我链接的其他SO帖子返回)?

解决方案

有些事情在你的问题上混淆了。首先,您使用的技术视图,第二个解释答案的方式。



1)视图



这是一个很快的。您可以通过将数据发送到 / api-auth / login / 将DRF的登录视图用于可浏览的API 。这个视图实际上是与Django的 auth 应用程序( django.contrib.auth.views.login )假设它正在处理一个用户,手动浏览API。



那就是用 GET调用它一个空的html表单,用 POST 发回表单将触发表单验证,这可能会以重新显示的形式(200是否包含文档)或重定向被发回(302找到空的内容)。



这就是为什么你的数据是空的:服务器发送一个HTML文档,而你的角度可能试图解析一些JSON对象。



您使用的表单视图绝对不是从脚本中调用的。这可以完成,但是您需要相应地处理结果,这意味着分析返回的html页面以查找错误消息。如果你想从脚本中轻松访问,你应该建立你自己的登录视图。



strong> 2)文档vs请求



您正在处理两种单独的语义级别。


  1. 请求的含义

  2. 请求中包含的文档的含义。

HTTP错误代码在请求的上下文中是有意义的。他们发生在较低的水平。例如,返回401代码意味着执行此请求之前需要有效的认证凭证。



所以这里,这基本上意味着>您必须在之前具有有效的身份验证凭据,才能处理您的登录请求。



这可能是有道理的,但只有在您有两层身份验证的上下文。在第一层允许您的第二层登录请求之前,您需要具有对第一层有效的身份验证凭据。在这种情况下,如果您尝试使用第二层登录,但无法识别第一层,则可以获得401。



那么REST如何适应?



的概念REST 应用于HTTP时,是尝试匹配请求级语义和文档级语义。它非常适合,因为每个REST概念都具有匹配的HTTP动词,HTTP可缓存,客户端服务器,...和... 无状态



无状态意味着HTTP和REST都不具有登录的概念。登录是一种抽象,通常意味着我们使用如下工作流:


  1. 我们验证一些端点(登录/密码,挑战,oauth,无论如何)。

  2. 端点返回一些授权令

  3. 我们向服务器发送每个下一个请求的授权令牌。

但事实是,每一个请求都必须由服务器。也就是说,服务器将始终从授权请求开始,然后再查看内部的内容。如果此步骤失败,401是足够的响应。



除了步骤#1。此请求没有授权步骤。必须进行处理,必须检索和检查登录/密码,根据结果,服务器可能会决定发回授权令牌。



那么,什么错误代码如果选择不适用的话呢?嗯,有几个你可以选择:




  • 200好的。登录请求被成功处理并产生一个错误消息,这里是一个结果的文档。您的脚本会读取该文档(可能是一个JSON对象),以查看它是否有错误或授权令牌。

  • 204没有内容。登录请求已成功处理,但没有任何内容,肯定没有授权令牌。奇怪的选择,但正确。

  • 400不好的请求。登录请求未成功处理。



只有确定的事情,401不是一个选项。 401意味着您不允许尝试登录。不是登录失败。


This is my URLs.py:

url(r'^api-auth/', include('rest_framework.urls',
                               namespace='rest_framework')),

I have a form on my homepage where users can type a username and password. When the submit button is clicked, AngularJS sends a POST request to "api-auth/login/" with the user object (username and password):

$http.post("/api-auth/login/", self.loginuser)
    .error(function(data, status, headers, config) {
        console.log(data);
     });

When a user submits an incorrect username and password (username and password which either do not exist or do not match), Django Rest Framework returns a 200 OK rather than a 204 No Content, 404 or 401 Unauthorized (on this post, it says 401 is the correct status code to return: What's the appropriate HTTP status code to return if a user tries logging in with an incorrect username / password, but correct format?).

According to here: http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html in section 9.5 POST, it says "In this case, either 200 (OK) or 204 (No Content) is the appropriate response status, depending on whether or not the response includes an entity that describes the result."

I handle errors and log the data if data exists (I did console.log(data) in JS), but no data is logged, which means (from my understanding) no data is sent / the response does not include an entity that describes the result.

So how come DjangoRestFramework returns a 200 rather than a 204 No Content (or a 404 or 401, which is what should be returned according to the other SO post I linked to)?

解决方案

Several things are mixed up in your question. First, the technical views you use and second the way you interpret answers.

1) The views

That's a quick one. The view you use by sending data to /api-auth/login/ it DRF's Login view for the browsable API. This view, which is actually the one that ships with Django's auth app (django.contrib.auth.views.login) assumes it is dealing with a user, browsing the API manually.

That is: calling it with GET builds an empty html form, sending back the form with POST will trigger form validation, which can end up either in the form being redisplayed (200 Ok with a document included), or a redirection to be sent back (302 Found with empty content).

This is why your data is empty: the server sends an HTML document, while your angular probably tried to parse some JSON object.

The form view you use is absolutely not intended to be called from a script. This can be done, but you need to handle the result accordingly, which means analyzing the returned html page to look for error messages. Messy.

You should build your own login view if you want to access it from script easily.

2) Document vs request

You are dealing with two separate levels of semantics here.

  1. the meaning of the request.
  2. the meaning of the document enclosed in the request.

HTTP error codes are meaningful in the context of the request. They happen at a lower level. For instance, returning 401 code means "valid authentication credentials are required before performing this request".

So here, that basically would mean "you must have valid authentication credentials before I process your login request".

It could make sense, but only in a context where you have two layers of authentication. You would need to have authentication credentials valid for the first layer before it lets your second-layer-login-request through. In this case, you could get an 401 if you try to login with the second layer while not recognized by the first.

So, how does REST fit in?

The concept of REST, when applied to HTTP, is to try to match the request-level semantics and the document-level semantics. It fits particularly well because every REST concept has a matching HTTP verb, HTTP is cacheable, client-server, ... and... stateless.

Stateless means neither HTTP nor REST have the concept of logging in. Logging in is an abstraction, which usually means we use a workflow that looks like this:

  1. we authenticate to some endpoint (login/password, challenge, oauth, whatever).
  2. the endpoint returns some authorization token
  3. we send the authorization token with every next request to the server.

But truth is, every single request has to be authorized by the server. That is, the server will always start by authorizing the request, before looking at what's inside. If this step fails, 401 is an adequate response.

Except step #1. This request does not have the authorization step. It must be processed, the login/password must be retrieved and checked, and depending on the result, the server may decide to send back an authorization token.

So, what error codes would be appropriate if it chooses not to? Well, there are several you may choose from:

  • 200 Ok. The login request was successfully handled and yielded an error message, here is a document with the result. Your script would then read the document (could be a JSON object for instance) to see if it has errors or an authorization token.
  • 204 No Content. The login request was successfully handled, but yielded nothing and certainly no authorization token. Odd choice, but correct.
  • 400 Bad request. The login request was not handled successfully.

Only sure thing is, 401 is not an option. 401 would mean you were not allowed to attempt to login. Not that the login failed.

这篇关于Django Rest框架 - 为什么尝试使用不正确的凭据登录用户时返回200状态代码?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆