So it's important from time to time to talk about ways that you as a web application developer have a responsibility to create secure web applications. And so I want to call your attention to places where you write code that seems like on the surface that it's what could go wrong, and then you realize, oh wait a sec, that could go wrong. So it turns out that you take data from the user in the request object, whether it's from a form or from the URL. And like guess equals 42 seems innocuous enough. But then what I did is I just concatenated that into HTML and I sent that back. And so the problem is, what if somebody with ill intent tries to produce data that actually does something? And the problem is if I take data straight from the user and put it back in the HTML response, well, HTML and JavaScript are programming language. Your browser is being programmed. And that means that a user typing data into your system can program the browser. And what's even worse is that, I mean, having them program their own browser is not such a big deal. But in a way, what they do is they put some data in your system that turns into code and then they kidnap someone else's browser when they take a look at the data that came in. This is called cross-site scripting, where in a sense what it's doing is it's trying to run code so that it can read stuff from your site and then hand it to a rogue site. And so we have to protect against this and it's a very simple thing. So if we take a look at the code that was bad, basically we have this parameter guess, and in the last time I showed you that was 42. And we just took this request.GET guess, which is this stuff, and we simply concatenated it into some HTML. Well, if I carefully construct my guess with %C3, blah, blah, blah, all the, blah, blah, blah, all that stuff, well that turns into this is a URL encoding of less than b Bold greater than bold slash, so that turns into HTML. So I passed into this application some HTML, and I as the developer took that and I concatenated it together. So the response source has HTML, it's HTML that mostly comes from the application. But this little bit of HTML came from the person who put it in. And like I said, it's not such a critical problem if I in my browser put stuff to take over your browser. But it is if you can move that into someone else's browser. So what happens is that the browser sees this bold text in HTML and instead of showing us the less than and the greater than, it actually shows it to us as bold. Now this seems innocuous enough until you do something much more clever, and that is I am going to carefully construct some code, JavaScript. And so what happens is this here is encoding of that line right there, the script alert Owned slash script. And so what happens is that came in and it was concatenated straight out. And if you run this page, you won't see the data, but that actually JavaScript will run and it's going to show up in an alert box that says Owned and OK. Now, you can go ahead and look at the Wikipedia entries on cross-site scripting. Generally, the idea is once you're in JavaScript, you don't say alert that I've owned your browser. What you do is you do something like grab a cookie and send it to a third party, or you call, say, a web service on the system with a cookie and do bad things. Like you can convince a teacher to log in and change someone else's grade or delete all the grades in a class. Once you're into a person's browser in JavaScript, you can do a lot. So that's really quite scary and there's all kinds of scenarios where you're taking data from the user and you've got to be careful. Because yes, I said the guess is supposed to be a number, but if it's not a number, if I concatenate it without escaping it, it's a problem. So here is a safer version of that. So I've got another view function called game and it takes that same request and it still pulls that GET data off, which is this bit right here. But then it calls a function and that's django.utils.html escape, right? So what that does is that concatenates that into the HTML. But escape processes any dangerous characters and turns them into what are called HTML entities. So less than becomes ampersand lt, greater than becomes ampersand gt, right? These two, these four things with ampersands are a safer version of it. And so that means that even though I put in the data for bold, it comes out with the less thans and greater thans showing and it's not actually interpreted, right? So this whole notion of escaping or HTML entities, running the data from a user through an HTML entities automatic filter, ensures that the user cannot provide you data that turns into code in their or someone else's browser eventually. So that's the kind of thing you have to think of as you're concatenating stuff together. And the key thing is the request.GET guess, that came from the user. And so we think the user's going to be nice, but a user with bad intent can send data that they carefully construct to cause the maximum trouble. But if you just escape your data before you concatenate it, there's nothing they can do about it. So another of the views is where we're going to parse the parameter off of the URL itself. These URLs are a little prettier sometimes than the question mark key word equals value, and so let's take a look at this. The way you do this is in your URL patterns, you have a path and instead of just having the path name, the view function name, you actually have this bracket int colon guess bracket. And what that is, and you can go look this up in the Django documentation, there's a whole series of these things, that says the parameter after the word rest is an integer and please pass it in as the parameter guess. So I've chosen the name to pass it in as a parameter and then once Django sees this it, it pulls that 41 off and hands it to us. So we don't have to tear the URL part. Actually in this request object, we do get the URL, we could do a bunch of splits and fool around, but nah, it doesn't matter. Let's let Django do all that work. Let's just tell it we want that parameter after the word rest. It's supposed to be an integer and pass it to me in the variable guess. And then that same 41 comes in, I am cleverly escaping it before I concatenate it. And then I return a text-based HTML response with some HTML back to the browser. So this escape is there just because of cross-site scripting, I don't, I'm still taking this value still coming from the user. So if any value comes from the user, you have to properly escape it before you show it to them. Now, those are all function based, which are sort of a lower level. We haven't got to the point where we're talking about forms, but eventually in those lower-level functions, you have to check whether you've got get a GET request or a POST request. A POST request often comes from forms. And so this class-based view allows us to get a method for POST and let Django pick whether it's a GET or a POST. And this is an object, and if you're a little rusty on objects, I've got a URL there on Python for Everybody.com to review just like what a self is. I'm not going to cover all that. In the path command, you just have a string that comes after the application routing to this. The MainView.as_view is something you've got to add to it because MainView is a class, not a function, but as_view is a function. And then we have to create a method get, self of course is just part of Python's object oriented work, request is that first parameter, right? And so this one here is a stock response and I, just like the other ones, I return an HttpResponse. Now this looks a little more complex than the other one that did the same thing, but it turns out there is tons of things that we can do and inheritance, the fact it's a class, there are so many things about object oriented programming that over the next few lectures we're going to really take advantage of this. And we ultimately will rarely write the old school function-based view, we'll do class-based views. And so we can also pass parameters to class-based views just like we can pass them to function-based views. You say okay with a prefix of remain, slug is a kind of string and then guess is the parameter. So that says pull the string after the word remain off, right? It uses the name of the view, remain is the view within the application. And then this third parameter is the guess and it's automatically parsed and handed to us in guess. And then we're going to respond to a get request, self of course is the object oriented thing. Here's the whole request and guess is that little piece that comes off of the end of the URL. We're going create a response by escaping the user-provided guess bit so that if the user puts something nasty in for cross-site scripting, ha ha, we stopped them from doing that. And so that produces the same kind of output, Your guess was abc123-42-xyzzy. So talking about return values, everything we've shown you up till now is your basic 200 OK, which means you asked for a page, I gave you a page. You're probably familiar with 404 Not Found, which means you ask for a page, that page doesn't exist. There is another kind of response that's not actually a page, which is a response header that says, you know what, it's not like like you made a mistake, but you're at the wrong place, and it's called a redirect and 302 means I know where you're supposed to be and it isn't here. And it was originally used for sites that would move. And it's all handled by the location header on the HttpResponse. And so we send a redirect response, which is a 302 with the location header being set, and it uses a URL. And when the browser gets the 302 and a location header, it doesn't show you what it just got but it immediately re-GETs that URL and then shows you that URL. And the original idea was that if you renamed a domain or something and you wanted to have the old domain redirect web browsers and search engines, you used these 302s. There's also a 301 header that can be used to redirect all this stuff. But now we use it for all kinds of things and it's very much a controller function. If you go to Model-View-Controller, controller says, okay, we're done with that, but I want your browser to go over there. So like that routing, that sort of routing the browser, changing the browser, putting the browser where you want it to be, that's part of the application's controller phase. So we can send a redirect from a Django view. And so here we go, if you go to this bounce, it's going to actually not end up at this. It's going to bounce it to somewhere else. And in the path, we just say if you go to the bounce view, run to this function. This is not a class-based function, this is an old-school function. And so the request data is passed in and instead of now returning an HttpResponse, which we would put in here HTML, we are doing an HttpResponseRedirect and now we put a URL. And what we're saying with this whole thing is you're at the wrong place, please browser when you get this response back, go here. So it's like it bounces to the browser and then bounces back and then reads that URL. And you can have some output but folks generally don't need output when you're doing a redirect. So if you take a look at that bounce, watching it in your network console in a JavaScript debugger, what you see is you see a set of three requests, actually just two. You'll see the first request is going to bounce, and if we take a look at this request, we see that it's a 302, it's kind of small. You see we got a 302, which tells the browser something's wrong, I'm not at the right place. And then also the server sends the location header that says this is where you're supposed to be and the browser immediately turns around and does a GET to that URL simple.htm. And then that's what we see. And then this 404, interestingly, the three statuses I talked to you about, is because at this new location dj4e.com/simple.htm, there's no favicon. And remember the favicon is the thing that shows up like right there in the top tab bars, the favicon. And I don't have a favicon, at least not now, for dj4e. I should put a favicon there, but we get to see a 404, and all that means is the browser looked for a favicon and didn't find it. So we see a 302 which is moved with a location header, and then we see a GET which returns then a 200 which is a success, and we see the document, and then we see a 404 because it tries to grab the favicon. And so the HTML you get back from dj4e.com/simple.htm, that's this simple page with with a simple link, okay? So that's how the redirect works. So that's a series of views, both the input, class-based, function-based, and we did two, both the HttpResponse and the HttpResponseRedirect. So up now coming up next we're going to talk about how building templates makes us do a lot less concatenation. [MUSIC]