I dont understand request flows - django

Having read a bit, I still don't understand. Can you help me see where I am going wrong?
a view function sends out a request and gets a response
a httprequest contains info about a currently requested url.
httprequest objects have 2 attributes containing info submitted by
user. GET and POST
Use post when requesting sensitive information, use get when not.
Post data is generally submitted from an html Form.
OK then. If I want sensitive information from a user such as their name, dob etc, I put the requested info inside a form on the html side. On the server side I gather that info by using an object
request and its attribute POST. I then point it to the html input name I specifically want. Thus we have request.POST['Name'] this will return a string value which I give to a variable of my choosing. Thus name = request.POST['Name']. name on the server side will now hold the users entered name.
Before I continue, is there anything I have gotten wrong?

You're nearly right.
The distinction between GET and POST, however, isn't anything to do with sensitive information. It's true that GET data is visible in the URL (after the ?) and POST data isn't, but that doesn't make POST any more secure - it's trivial to get that data if you want to.
In fact the difference is really one of semantics. GET is used when you're just requesting particular information from the server - for instance, page 2 of a set, or a specific search query. POST is used when you're updating information - submitting a form to change stored data.
Apart from that, you're just about there. One thing that will probably help you is to read up on Django's forms framework, which does a lot of the work in generation and validation of forms for you.

You got one tiny bit of it wrong.
The user sends out a request, which the view function receives, then the view function sends out a response.
And HTTP objects have a lot more information included than just GET and POST variables. See Django's official documentation for more information about this.

Related

Make extra parameters passed in URL as optional

I have this URL path('user/delete/<int:pk>/', views.UserDeleteView.as_view(), name='delete_user'),
to delete a selected user via passing the pk of the user to be accessed by the DeleteView . However, I want to delete multiple users by using a form with checkboxes. For that, I have used a separate view.
my question is that is there any way that I can make this <int:pk> as optional parameter so that I can use the same view for POST as well as GET requests. Just in case I want to use the POST method for the same URL. Can this be done? Someone said it can be done optional in Ruby on Rails. Is there any way to do this here in Django?
You can define two paths, one with the primary key, and another one without the primary key:
path('user/delete/', views.UserDeleteView.as_view(), name='delete_user'),
path('user/delete/<int:pk>/', views.UserDeleteView.as_view(), name='delete_user_id'),
We thus have two views here: 'delete_user' that takes no pk, and 'delete_user_id' that takes a primary key. Both direct to the same UserDeleteView.
You can inject a value for the missing parameter, by using the kwargs= parameter:
path('user/delete/', views.UserDeleteView.as_view(), name='delete_user', kwargs={'pk': None}),
path('user/delete/<int:pk>/', views.UserDeleteView.as_view(), name='delete_user_id'),
That being said, using GET requests are supposed to have no side effects. That is how the HTTP protocol [wiki] is designed:
The GET method requests a representation of the specified resource. Requests using GET should only retrieve data and should have no other effect. (This is also true of some other HTTP methods.) The W3C has published guidance principles on this distinction, saying, "Web application design should be informed by the above principles, but also by the relevant limitations.".
The W3 organization has also guidelines when to use GET or POST:
Use GET if:
The interaction is more like a question (i.e., it is a safe operation such as a query, read operation, or lookup).
Use POST if:
The interaction is more like an order, or
The interaction changes the state of the resource in a way that the user would perceive (e.g., a subscription to a service), or
The user be held accountable for the results of the interaction.
If you want to delete items, you usually make a DELETE or a POST request. Django for example will protect such requests with a CSRF token, to prevent cross-site request forgery [wiki].
I therefore strongly recommend that you only allow POST/DELETE requests for these views, of course with extra checks to see if the user is authorized to make the changes.

Why use URL parameters over request body in API?

When making an API endpoint in Django Rest Framework for example, why would I ever use URL parameters to receive data rather than just putting everything in the request data?
I don't get the difference between the two.
Putting some query data in the URL allows the URL to store the "state" of your web application.
For example a state can be "I queried how do I make cheese on stackoverflow", and the URL would be https://stackoverflow.com/search?q=how+do+make+cheese.
This allows the web app to interact as expected with browser tools like Refresh, Go Back, etc. Without the state stored in the URL, refreshing the page might just take you back to the homepage, instead of showing you the same query results (the expected behaviour).
Additionally, you can copy & paste the URL. When someone clicks on it, they will be taken directly to that specific state.
On the other hand, you shouldn't use the URL to store/send sensitive data (as it can easily be seen, use the body instead), and you should make sure reloading an "action" URL won't execute the action again (like paying for a product twice!).
The URL parameters and body parameters server different purpose. The REST API grammar says
GET Method is used when you want to retrieve data back and don't want to update any of the record in system. The GET method will not pass body parameter and hence whatever filter parameters passed to API will be through URL parameters.
POST/PUT Method is used whenever you want to update your database. The value could be single parameter or even no input but you have to use POST/PUT method, if you are trying to update database record(s).

View design for a Django website which has a RESTful API from the get go

I am trying to build a Django powered website. I want the website to be dynamic. For example, I want the profile page for a authenticated user to contain multiple resources (like a friends list, a group list, usage history etc) and these resources should be loaded in the same area on the page by making API calls without reloading the page.
Here is my understanding of the process:
Browser on the client side requests the profile page at www.example.com/user:id
The server returns a HTTP response and sends the html, css and javascript to the browser.
To load variable resources on the webpage, for example, the friend list, the javascript makes API calls using HTTP and sending context in JSON.
The API returns a JSON response which contain the data requested.
Javascript renders the data as html and the client is able to see new content on the same page.
I thought that in order to do this, some of my server side views need to be ordinary Django views which returns an HTTP response, while some others need to be API views which return JSON.
Now here's my confusion. Let's say www.example.com/user:id is processed using an ordinary django view, while www.example.com/user/:id/friendslist is processed using an API view. Now if the user inadvertently points the browser at www.example.com/user/:id/friendslist by typing the entire URL and hits go, what happens?
If I go with the flow of logic that I mentioned above, then the view will simply return a JSON. No html, css or javascript. In this case, how will the browser know what html to display?
I am just a beginner and I am sure I got the flow of logic wrong. Can someone please point out which part I got wrong?
Now if the user inadvertently points the browser at www.example.com/user/:id/friendslist by typing the entire URL and hits go, what happens?
It depends on how you coded your server. In Django you can use is_ajax to check whether the request was AJAX or not. You could return an HTTP error code when the request is not an AJAX one, if you wanted. So a user who inadvertently points the browser to your URL but does not take any further action will get an error.
Note here that a knowledgeable user could circumvent is_ajax by setting the request header field HTTP_X_REQUESTED_WITH to XMLHttpRequest manually.
If I go with the flow of logic that I mentioned above, then the view will simply return a JSON. No html, css or javascript. In this case, how will the browser know what html to display?
Setting your returned data type to application/json already tells the browser what it is dealing with. The least a browser would do this with this is display it as text.
Here's an example of an API call that returns JSON: https://api.zotero.org/users/475425/collections/9KH9TNSJ/items?format=json My browser just shows the JSON.

In what case can CSRF-exempt be dangerous?

This question is more a re-insurance than one directly about how to code. As an autodidact i did not have a lot of possibilities to ask professionals such things, so i try here.
I have read the documents in the django-docs ( https://docs.djangoproject.com/en/1.3/ref/contrib/csrf/ ) and some info on that page: http://cwe.mitre.org/top25/#CWE-352
As far as i have understood, django delivers a token (some kind of pin-code) to a user. And to verify it really is him, he has to return it the next time he does a request. And some guys at Google found out that this is even possible with ajax-requests, which is why we have the new policy of protecting them too since 1.2.6. And CSRF is about someone giving me something (bad, dangerous code, corrupt files or something like that) pretending to be someone else.
So if i have some code like this:
#csrf_exempt
def grab(request):
"""
view to download an item
POST because it stores that a user has downloaded this item
"""
item_id = request.POST.get('item', None)
if not loop: return HttpResponseBadRequest('no item id provided')
item = Item.objects.get(pk=int(item_id))
that should be save, as i'm not giving access to the database or any part of my application before trying to convert the given value to an integer. And there is not too much damage if i do a wrong record of someone downloading a file (in this case it is almost none). Assuming i would write bills relying on this view, the CSRF-exempt would be vary bad idea (Is that right?).
I also do not understand why somebody can't steal the CSRF-token from a user and use it to still trick me (or the user). So i have some questions about this topic:
1) are my assumptions from above right?
2) can somebody tell me, what (and probably how) some not so nice guy could use the view above to do dirty tricks, and what would they be?
3) is a CSRF an example of a man-in-the-middle attack, is it just related to it, or is it something entirely different?
4) Any valuable links to do further reading on such dangers?
Maybe some of these questions sound no too well informed, but i'm trying to get over that. I would be very glad if someone could help me.
CSRF attacks are about forcing a victims browser to send forged requests. A simple <img> or automatically submitted <form> suffice to do this for both GET and POST method. And as the requests are send by the browser, it sends any authentication credentials along and thus making the requests seem authentic and legitimate from the server’s point of view as they basically don’t differ from those initiated by the user’s actions.
And that’s exactly what the CSRF token is used for: establish a difference between requests that were initiated by the user and those that were forged by a third party site. For this purpose the CSRF token acts as a secret that is only known to the server and the user. The server puts the secret in the document in a response and expects it to be send back in the next request.
And as the secret is embedded in the response’s document that is assigned for this specific user, an attacker would need to eavesdrop that specific response or access the document in some other way. There certainly are attacks get the CSRF token (e. g. eavesdropping, MITM, XSS, etc.). But if you are protected against those attacks, an attacker won’t be able to forge an authentic request.
CSRF attack
I trick you into viewing a webpage where I inserted some code (a request, typically through img or form) to another site (where you possibly have some rights).
Innocuous example
<img src="http://www.yoursite.net/changelanguage?lang=fr">
I cruelly changed the language of your session to french. Oh noes! You can safely remove csrf protection and save a db hit.
Dangerous examples
<img src="http://www.yourbank.net/sendmoney?amt=9999&account=123>
If you were logged in in yourbank.net (and it has no csrf or any other protection), your account should feel lighter by now. (I am 123.)
<img src="http://www.yoursite.net/admin/users/123/edit?admin=1">
If you were logged in in yoursite.net as an admin, then we both are. (I am 123.)

Django: do I need to do HttpResponseRedirect to render a simple string after a POST?

I've got a mobile app that makes POST requests to a Django site.
I want to return a simple string (not a template-based page) after the app makes the POST request, saying 'Success' or 'Failure' (EDIT: plus a bit of extra info) as appropriate.
****EDIT: note that it's not a browser making the request, it's an app (so there's no BACK button involved) and I'd like to do some extra app-side work based on the results of the POST request - basically I want to hand back some information.*****
However I know that after a POST request in Django you're supposed to do a HttpResponseRedirect. But, do I really need to redirect to another page and write a new function to handle it, all to output a string?
And if so, how do I pass the success/failure status of the app in the HttpResponseRedirect, since it's only supposed to take one argument?
Thanks!
If this is a user-generated POST (standard web site), then S. Lott's advice is correct.
But if you're POSTing as an API call, then just return the string. On a mobile device, the customer pays for every HTTP request.
do I really need to redirect to
another page and write a new function
to handle it, all to output a string?
Yes.
If they hit "Back" on the browser, you'll wish you had provided a redirect-after-post.
If you don't redirect and they hit "Back" on the browser, they could repost the form again. You probably don't want to deal with that, so it's easier to redirect after post.
how do I pass the success/failure status of the app in the HttpResponseRedirect
See this: http://docs.djangoproject.com/en/dev/ref/request-response/#django.http.HttpResponse.status_code
Edit
If there's no browser, then there's no back button. Since there's no back button, there's no need for a redirect.
"after a POST request in Django you're
supposed to do a HttpResponseRedirect"
Doesn't make any sense. You're not "supposed" to do it. Django helps you do it.
You do not redirect after POST as part of web services.
You must redirect after POST to help people use their browser.
As S.Lott says, yes you really do want to redirect.
However I'm not sure what you mean about showing the 'success/failure status of the app" after the redirect. The redirect should only happen if the POST was successful; otherwise, you'd redisplay the form with any validation errors showing.
Is there javascript? Then maybe you could make an ajax request and simply change the content after the result comes. That should also prevent problems from 'Back' and you don't need to redirect.