230 likes | 510 Views
Sessions and Templates. CS/COE 1520 Jarrett Billingsley. Today:. sessions how users log in and stay logged in how we implement state on top of a stateless protocol templates model-view-controller templating engines. Sessions. Forget-me-not.
E N D
Sessions and Templates CS/COE 1520 Jarrett Billingsley
Today: • sessions • how users log in and stay logged in • how we implement state on top of a stateless protocol • templates • model-view-controller • templating engines
Forget-me-not • we don't the user to have to enter their credentials on every page. • we want them to be able to log in once, and carry that login around. 1. the user sends their credentials to the server. Secure Area 3. the user presents that ID card whenever they access anything in the secure area. 2. the server validates them and sends back an "ID Card". user1/p455w0rd VALID THRU 11/3/2019 as long as the ID is valid, they can continue to access the secure pages.
And for some reason they're called "cookies" • this is what cookies are for. 1. client sends credentials (bob/12345) Client example.com 2. server generates acryptographically securesession ID value, stores it,and sends it back Users 🍪Cookies 🍪 "bob": "12345" "example.com": "a9[flj%" Sessions GET(Cookie: "a9[flj%") "bob": "a9[flj%" POST(Cookie: "a9[flj%") 3. client stores that "cookie" and sends it along with every subsequent request
Encryption • of course, doing all this stuff out in the open would be pointless. • every computer on the network could see your credentials… • …and then perfectly impersonate you. • so instead, all these communications use HTTPS(ecure). Server Untrusted computers Encryption Decryption 9jnF(*#nf8028Y@n99nasfaco(N#( user1 p455w0rd user1 p455w0rd done correctly, the untrusted computers only see useless gibberish.
How does the server remember you? • the active session(s) need to be stored somewhere. • on the server: in memory, some file, a database, whatever. • on the client: in cookies! sensitive logins (like for financial transactions) could be stored in server RAM and only last a short time. less-critical ones could last months or years before requiring reauthentication, and would be kept in nonvolatile storage.
But remember… • NEVER. TRUST. THE CLIENT. • the client can see their own cookies. • JavaScript code can access (most of) the cookies. • DO NOT STORE information that should be private to the server on the client's machine. • any session data stored in cookies should be heavily encrypted. • DO NOT ASSUME that cookie data sent by the client is valid. hehehe
The session object • session is another "magic global" variable, like request. • it's "just a dict", but it's ~special~ flask.session 9jnF(*#nf8028Y@n99nasfaco(N#( 🍪 if you put things in it, then send a response… it's serialized (turned to text) and signedusing app.secret_key... and sent to the client to be stored as a cookie. subsequent requests from the client include the cookie… which the server checks (using the same key) and deserializes.
Using it in the code • all of this is handled for you transparently. you just… use it. • it's like a dict whose values magically persist across requests. • you do have to set app.secret_key • though you should use a properly generated cryptographically secure key. • let's have a look at fl5_session_login.py!
But there are downsides… • client-side sessions are super simple. • they require no server-side storage. • however, it's possible to view the contents of a Flask cookie. • https://www.youtube.com/watch?v=mhcnBTDLxCI • they are read-only: if the client tries to change the values, the signature will be wrong and the server will reject it. • the only way to properly sign it is to know the server's secret key. • cookies are also limited in size. • this is just the DEFAULT behavior in Flask. • it can be easily customized with extensions. • if you absolutely do not want the client to know any secret info… • you will have to store that info on the server… • and only give the client some kind of session ID number.
Model-View-Controller • in almost any program, you'll have three major components. a View presents the data from a Model to the user. users = {...} x = 10 name = 'bob' a Model is program state: variables, data structures, etc. if x == 10: for u in users: u.age += 1 elif name == 'bob': name = 'jill' a Controller is code that manipulates the Model.
Separation of concerns! • the idea behind this is to separate presentation from data. • kinda like not putting styling inside HTML… • basically, don't mix your input/output with the code that does stuff. users = {...} $ user add $ user list $ _ x = 10 name = 'bob' /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/ if the model doesn't care about how the input and output work… users.txt …then you can hook several kinds of inputs and outputs to it.
MVC in Flask • models are represented using databases. • that's next week. • your @app.route functions serve two purposes: • they can be controllers, changing the model's state • and they return the view, which is what the client sees. • some frameworks make this division more explicit. • but for now, let's focus on the views!
Like string formatting, but bigger • using strings and the .format() method is… not very nice. • what we want to do instead, is… write our HTML in an HTML file like regular HTML, except… <!doctype html> <html> <head> <title> 's profile! </title> </head> <body> This is 's profile. </body> </html> there are "blanks" that we can fill in with whatever we want. Bob by filling in those blanks, we produce the HTML that we actually serve to the user. Bob
Jinja (神社) • there are many templating engines and Flask comes with Jinja. • you can think of it like "HTML, but you can escape to Python." <!doctype html> <html> <head> <title>{{user}}'s profile! </title> </head> <body> This is{{user}}'s profile. </body> </html> each Jinja template file is like a Python function. it can have arguments. in this case, user is one of the arguments. {{expr}} will evaluate the expression and insert its result as text right there.
Statements and control structures • Jinja is basically Python with weird syntax. • {% these %}mark statements. {% if condition %} one thing {% elif condition %} another thing {% else %} a third thing {% endif %} {% fork,vindict.items() %} Use {{k}} and {{v}} here. {% endfor %} you've got full-powered Python for loops. {% block users %} {% endblock %} no colons, and you need endif. and this is… well…
Template inheritance • most pages on your site are gonna have some common features. header navigation main these things aren't likely to change much/at all across pages. footer so, DRY (don't repeat yourself.) you make a base template and have other pages inherit from that template.
blocks = "virtual methods" • think of jinja blocks as virtual methods in a class. • they can define default behavior, or just be empty. • inherited templates can override that behavior… • …and even call the "super()" function to evaluate the super-template's version of that block!
Message flashing idk why they named it this • what if the user types their username/password wrong? • well, what do most sites do? Your username/password were not recognized. Please try again. Jinja handles this with flashing: flash("Your username...") that message will be available on the next request with get_flashed_messages() this is done by actually storing the message in the user's session cookie!