@Oroz | Hello everyone |
@Oroz | First, as you probably already know Polkan Garcia talk that ws initially schedule for today has been moved to 18.00 GMT on Sunday |
@Oroz | But now it's time for Jose Nazario's talk titled "Writing web applications with python webapp frameorks" |
@Oroz | Jose is an Openbsd developer and security analyst from Ann Arbor, United States |
@Oroz | The slied for this talk are on his website: |
@Oroz | http://monkey.org/~jose/presentations/umeet05/slides/ |
@Oroz | as usual you can ask questions at any time in #qc |
@Oroz | Jose, |
@Oroz | all yours |
@jose_n | thank you oroz. |
@jose_n | hola a todos, thanks everyone for coming. my name is jose nazario |
@jose_n | and i'm goin gto be talking about building web applications in |
@jose_n | python using some simple components. |
@jose_n | i'll be referring to slides, so please follow along. |
@jose_n | |
@jose_n | [slide 1] |
@jose_n | here's a brief overview of the talk. i'm going to introduce the two |
@jose_n | main paradigms of this talk, web app frameworks and the MVC model |
@jose_n | of programming, in the next few slides. |
@jose_n | i'll then focus on the |
@jose_n | actual python frameworks we're using in this demo and how they fit |
@jose_n | together to form a working application. and finally i'll be sharing |
@jose_n | the code i wrote as the demos, aka "bloggy", a simple blogging system. |
@jose_n | |
@jose_n | [slide 2] |
@jose_n | web app frameworks are just that, pieces of code that let you write |
@jose_n | your functional web app veyr quickly. |
@jose_n | they contain a number of pieces |
@jose_n | that let you get right to it. this can include "boilerplate" code, |
@jose_n | or code that you'd write every time for almost every app. |
@jose_n | |
@jose_n | you can write web applications in a framework like the ones i'll |
@jose_n | be introducing, or you can write you own using pre-existing components. |
@jose_n | we're going to mix these two, using the CherryPy web handler framework |
@jose_n | and some components to extend its functionality. |
@jose_n | |
@jose_n | the important thing about any framework is that it typically lets you |
@jose_n | get right to the very important bits of your application quickly. they |
@jose_n | handle the heavy lifting of handling user requests and such, letting |
@jose_n | you focus on getting your specific needs met. |
@jose_n | |
@jose_n | i've been using the frameworks described here (CherryPy, SQLObject, |
@jose_n | and even Django) at work and in some applicatins i've been writing |
@jose_n | outside of work, as well. i've found them to be feature filled and |
@jose_n | useful for getting my job done quickly. |
@jose_n | one of the things i wrote |
@jose_n | this week was a simple, lightweight interface to our vulnerability |
@jose_n | and malware writeup database. took me about 2 hours and was done |
@jose_n | in under a few hundred lines of code when it was complete. |
@jose_n | |
@jose_n | [slide 3] |
@jose_n | the main paradigm we're using here is the Model-View-Controll design. |
@jose_n | we're going to clearly split the requirements of our application |
@jose_n | across these boundaries, making it easy to manage the code. |
@jose_n | |
@jose_n | the model refers to the data model, in this case an SQL-backed app. |
@jose_n | you can use any back end, including flat files or directories, but |
@jose_n | the idea is the same. |
@jose_n | you make this a clearly managed piece of code |
@jose_n | and you can change it as needed. the view handles how the user will |
@jose_n | see the data presented to them, such as blog posts or customer |
@jose_n | entries. and finally the controller is the piece of the app that |
@jose_n | mediates this interaction, including reading and writing. |
@jose_n | |
@jose_n | [slide 4] |
@jose_n | slides: http://monkey.org/~jose/presentations/umeet05/slides/ |
@jose_n | |
@jose_n | the benefits of this modular stack that we have here - CherryPy, |
@jose_n | CherryTemplate, SQLObject and FormEncode - is that by having modular |
@jose_n | code, we can separate our use of these components and speed up |
@jose_n | development. |
@jose_n | we can extend it easily, especially in an object |
@jose_n | oriented language like python, where we can inherit the classes |
@jose_n | to extend them. |
@jose_n | |
@jose_n | the nice thing about these modules is that they're flexible, meaning |
@jose_n | we can use them for a variety of purposes. also, they leave the |
@jose_n | grunt work - handling web browser requests, writing SQL queries - |
@jose_n | to the module, and we get a simple interface. |
@jose_n | |
@jose_n | if you've ever programmed in PHP or a CGI-BIN application language like |
@jose_n | Perl, compare the code here to what you had to do before. you'll see |
@jose_n | that it's easier, and much easier to maintain. PHP, which i've done |
@jose_n | a lot of work in for myself, suffers from mixing all of this without |
@jose_n | the use of some newer packages. |
@jose_n | almost any CGI-BIN app will have |
@jose_n | to print out the HTML itself, making it a pain to manage the actual |
@jose_n | logic within that mess. simply put, i can't go back, and i hope you |
@jose_n | see the benefits here, too. |
@jose_n | [slide 5] |
@jose_n | |
@jose_n | our demo app is "bloggy" a dead simple codebase that you can take |
@jose_n | with you to explore and play with. it's a simple blogging system, |
@jose_n | not suitable for real world use, but it illustrates these ideas |
@jose_n | cleanly, i hope. |
@jose_n | you can create posts and browse them easily. if |
@jose_n | you want to extend it, go for it. you'd probably do much the same |
@jose_n | if you wrote a full featured blogging system you'd probably do |
@jose_n | somethin like this at the core of the app. anyhow, we'll be using |
@jose_n | this code in the next few slides. |
@jose_n | |
@jose_n | the code is here: http://monkey.org/~jose/presentations/umeet05/ |
@jose_n | i wrote it using Postgres on OS X, but it's highly retargetable to |
@jose_n | any supported DB and and platform supported by python. |
@jose_n | |
@jose_n | [slide 6] |
@jose_n | this is the simple view of the bloggy index, so posts by title and |
@jose_n | date. nothing fancy, and clearly i'm no guru of web design. i leave |
@jose_n | the sytles to someone else. |
@jose_n | |
@jose_n | [slide 7] |
@jose_n | here's a specific post, you can see how you can essentially drill into |
@jose_n | a post from that index page. pretty simple, eh? and just like you'd |
@jose_n | do if you were browsing a full featured and mature blogging system. |
@jose_n | |
@jose_n | [slide 8] |
@jose_n | slides: http://monkey.org/~jose/presentations/umeet05/slides/ |
@jose_n | |
@jose_n | first up, the main component here, CherryPy. this is a simple |
@jose_n | web app framework, handling requests and mapping them to the |
@jose_n | code. in CherryPy (or CP), web directories are under the "root" |
@jose_n | object as their own objects, and pages and vews are methods of |
@jose_n | those objects. |
@jose_n | |
@jose_n | this is the CherryPy website: http://www.cherrypy.org/ |
@jose_n | |
@jose_n | this will be more clean when i show you some code in the next few |
@jose_n | slides, but think about it this way: it's a simple, intuitive way |
@jose_n | to map requests to your code to handle it. CP handles the request |
@jose_n | and maps the arguments given to it (in the GET or POST methods) to |
@jose_n | the code for you to handle. |
@jose_n | |
@jose_n | one major drawback of CP is that it wont run as a CGI, so some hosting |
@jose_n | providers wont be available to host your app. it works best |
@jose_n | behind apache and ProxyPass. |
@jose_n | |
@jose_n | [slide 9] |
@jose_n | over the next two slides, you'll see the actual code from CP that |
@jose_n | creates a simple standalone web application. we have our SQLObject |
@jose_n | imports (and our model, which we'll explain later), but the key thing |
@jose_n | here is the root class. the __init__() method handles the database |
@jose_n | connection in our case. but on the next slide, we can see the main |
@jose_n | page and the app setup. |
@jose_n | |
@jose_n | [slide 10] |
@jose_n | the index method is the base directory, "/", of the web app. when |
@jose_n | we go to 10.10.10.11 (my IP in this case) as http://10.10.10.11:8080/ |
@jose_n | we get this method called. |
@jose_n | |
@jose_n | notice "index.exposed = True", this attribute says that the CP server |
@jose_n | can expose this to web clients. if you had a method under the Root |
@jose_n | object that wasn't supposed to be exposed, set this to False. |
@jose_n | |
@jose_n | the main() function starts it up. the configuration tells the server |
@jose_n | how to behave: |
@jose_n | |
@jose_n | Ocho:~/python/bloggy jose$ cat simple.conf |
@jose_n | [global] |
@jose_n | server.socketPort = 8080 |
@jose_n | server.logToScreen = True |
@jose_n | server.socketHost = '0.0.0.0' |
@jose_n | |
@jose_n | we listen for any requests coming in on port 8080 and log to the |
@jose_n | screen, useful for dev/testing work. |
@jose_n | |
@jose_n | [slide 11] |
@jose_n | this rehashes some of what i said in the previous slides, but you |
@jose_n | get the idea. mapping requests and arguments to code in a simple |
@jose_n | fashion. arguments can be passed in as a named argument in a |
@jose_n | GET request (or a POST request), like this: |
@jose_n | def index(self, q): ... |
@jose_n | to handle |
@jose_n | http://10.10.10.11/q=test |
@jose_n | or you can handle them as a dictionary with lots of pieces and take |
@jose_n | it apart inside your code. |
@jose_n | |
@jose_n | [slide 12] |
@jose_n | slides: http://monkey.org/~jose/presentations/umeet05/slides/ |
@jose_n | |
@jose_n | to complement this, we use CherryTemplate to create dynamic web pages. |
@jose_n | we embed python in the pages and it gets evaluated. |
@jose_n | |
@jose_n | link: http://cherrytemplate.python-hosting.com/ |
@jose_n | |
@jose_n | CherryTemplate (or CT) has access to the variants in the scope |
@jose_n | where the method renderTemplate() is called. we get some nice stuff |
@jose_n | in CT, including iterators, conditional expressions, and variable |
@jose_n | reference. |
@jose_n | |
@jose_n | as in any good MVC app, leave the logic of the controller inside |
@jose_n | the app and leave only the bits needed for the view in the template. |
@jose_n | |
@jose_n | [slide 13] |
@jose_n | here's an example template from bloggy, see how the CT specific |
@jose_n | bits are highlighted in red. you can wrap any HTML around this, |
@jose_n | including CSS or javascript. very easy to use! |
@jose_n | |
@jose_n | here we loop over the posts and print the link to the post by |
@jose_n | ID and list the title and the date. |
@jose_n | |
@jose_n | again, i think this is pretty easy and illustrates a powerful web |
@jose_n | app design technique. nothing too complicated here, and that's good! |
@jose_n | |
@jose_n | [slide 14] |
@jose_n | to render a template, CherryPy actually returns the generated |
@jose_n | string. we use renderTemplate from CherryTemplate to go over the |
@jose_n | HTML template and fill it out. |
@jose_n | |
@jose_n | we call them as files in this case, but we could have used a static |
@jose_n | string if we wanted. the key thing here is that by making it files, |
@jose_n | we split up the maintenance of this and make it easy to find what |
@jose_n | matters to us. |
@jose_n | if you have web designers, they can work on the |
@jose_n | layout and markup and you can keep working on the logic. |
@jose_n | |
@jose_n | [slide 15] |
@jose_n | here's a few more templating languages: |
@jose_n | kid, which is very powerful as well, but i didn't like the syntax. |
@jose_n | CheetahTemplate, which i think predates CherryTemplate, and is a lot |
@jose_n | like Python server pages. |
@jose_n | Myghty, which is inspired by the Perl HTML::Mason framework but |
@jose_n | lacks very good beginner docs. |
@jose_n | and Python Server Pages, which are very powerful but complicated. |
@jose_n | i like CherryTemplate: it's easy to use, powerful, and not complicated. |
@jose_n | |
@jose_n | [slide 16] |
@jose_n | slides: http://monkey.org/~jose/presentations/umeet05/slides/ |
@jose_n | |
@jose_n | SQLObject is our big, heavy lifter here. if you've written a lot |
@jose_n | of SQL, you know it can be a pain to manage. instead, we use an |
@jose_n | object-relation mapper like SQLObject to do that heavy lifting for us. |
@jose_n | we can interface to most popular databases and change that on the |
@jose_n | fly with little, if any, work involved. it also uses native Python |
@jose_n | data types, and lets us do everything we want from our database: |
@jose_n | selects, joins, updates, and even table management. |
@jose_n | |
@jose_n | [slide 17] |
@jose_n | here's Bloggy's simple model. we have a table, BlogPost, that has |
@jose_n | three columns: a post title, a body, and a date. SQLObject now |
@jose_n | uses this for everything to access and manage that table and |
@jose_n | the rows within it. |
@jose_n | we map the types to SQLObject column types, |
@jose_n | so it knows what to expect from them and how to deliver data |
@jose_n | to them. very easy! |
@jose_n | |
@jose_n | [slide 18] |
@jose_n | to create the table, i usually make a simple script like this |
@jose_n | initialization script. i create the tables as needed and voila, |
@jose_n | SQLObject has done the work for me. |
@jose_n | |
@jose_n | deleting tables is also easy, and is also managed using SQLObject. |
@jose_n | (ie TableName.deleteTable()) |
@jose_n | |
@jose_n | [slide 19] |
@jose_n | here are the results of our createTable() calls as viewed in |
@jose_n | Postgres. we can see tat it creates two things implicitely. first |
@jose_n | is an "id" column, which is the primary key of the table. the |
@jose_n | second is the table for the index on that table. we can make |
@jose_n | more indices if we want, and add constraints easily. |
@jose_n | |
@jose_n | [slide 20] |
@jose_n | slides: http://monkey.org/~jose/presentations/umeet05/slides/ |
@jose_n | |
@jose_n | SQLObject link: http://sqlobject.org/ |
@jose_n | |
@jose_n | some more, unrelated examples, showing how to cross reference tables |
@jose_n | using a foreign key, and how to make database indices, even with |
@jose_n | the UNIQUE constraint! |
@jose_n | |
@jose_n | all very easy, thanks to SQLObject. |
@jose_n | |
@jose_n | [slide 21] |
@jose_n | with SQLObject, adding data is very easy. you just call the class |
@jose_n | and fill out the fields appropriately. it will create the database |
@jose_n | row for you, or it will bump up an exception if something has failed. |
@jose_n | |
@jose_n | to access the data you can select using any requirements you want. |
@jose_n | for example, model.Mytable.select(model.Mytable.q.id == 1) would get |
@jose_n | the row where "id = 1". this returns a list of results. |
@jose_n | |
@jose_n | finally, to update, we can just access the feature we have and reassign |
@jose_n | the attribute: |
@jose_n | m = model.Mytable.select(model.Mytable.q.id == 1)[0] |
@jose_n | m.title = "This is my new title" |
@jose_n | and voila, it's updated. |
@jose_n | |
@jose_n | [slide 22] |
@jose_n | finally, FormEncode, which lets us enforce the data mode using validators. |
@jose_n | these validators operate on user-supplied data (from an HTML form) and |
@jose_n | help us ensure that the data maintains its integrity. |
@jose_n | in a few lines |
@jose_n | of code, and bubble up errors to the user cleanly. what's even |
@jose_n | nicer is that it maps stuff to a format usable by SQLObject, which |
@jose_n | is just native Python data types. |
@jose_n | link: http://formencode.org/ |
@jose_n | |
@jose_n | [slide 23] |
@jose_n | the schemas used by FormEncode are a lot like the models used by |
@jose_n | SQLObject. we can allow extra fields in the form, which is handy |
@jose_n | if you have a form that will input into multiple tables and |
@jose_n | schemas, and you can filter them per-schema. |
@jose_n | |
@jose_n | the validators are almost like the types in SQLObject, and you |
@jose_n | can enforce any criteria you want on the input stream. you can |
@jose_n | also write your own validators, if you want to enfoce a format |
@jose_n | of the data. |
@jose_n | |
@jose_n | [slide 24] |
@jose_n | this is a modified CherryTemplate file showing you the places we bubble |
@jose_n | up the errors to the user. once rendered by the error form, they |
@jose_n | get wrapped in a CSS class that lets us change the color to red, |
@jose_n | for example (to make it highly visible). again, very easy. |
@jose_n | |
@jose_n | slides: http://monkey.org/~jose/presentations/umeet05/slides/ |
@jose_n | |
@jose_n | [slide 25] |
@jose_n | this is how we use FormEncode in our controller code. we basically |
@jose_n | run the form through the validator using htmlform.HTMLForm() |
@jose_n | and then look for any errors after we call the "validate" method |
@jose_n | on the resluting HTMLForm object. |
@jose_n | |
@jose_n | if we get any errors, we bubble up an error form (shown on the next |
@jose_n | slide) to the user. if not, everything must be ok, so we pass it |
@jose_n | on to the database for finally inserting it. |
@jose_n | |
@jose_n | voila, we have a new entry in our blog! |
@jose_n | |
@jose_n | [slide 26] |
@jose_n | again, a rehash of what was just said. we get user input in, we |
@jose_n | compare it against our scheme using validators, and if we have |
@jose_n | any errors, tell the user to try again. if not, we accept the |
@jose_n | data. |
@jose_n | |
@jose_n | very easy to do, an it only adds a few lines of code. |
@jose_n | |
@jose_n | [slide 27] |
@jose_n | this shows you how it looks to the user if an error has been |
@jose_n | found in our code. namely, a useful error is bubbled up telling |
@jose_n | the user that a problem was encountered. |
@jose_n | |
@jose_n | very easy to do! (i keep saying that, but it's true) |
@jose_n | |
@jose_n | |
@jose_n | [slide 28] |
@jose_n | and we're at the end, hopefully i've shown you how to use these |
@jose_n | simple components together in a robust web application framework. |
@jose_n | these pieces fit together nicely, and leave you able to focus on |
@jose_n | the bits that matter, namely how do you get your app's logic working. |
@jose_n | no complicated SQL, no need to manage HTTP requests, and CherryPy |
@jose_n | can even manage sessions for you. and finally, very simple but |
@jose_n | robust form validation, preserving your data's integrity. |
@jose_n | |
@jose_n | what's amazing to me is that Bloggy was only 80 lines of Python |
@jose_n | and 40 lines of HTML templates, hopefully ilustrating how easy it |
@jose_n | is to get a functional application up and running. |
@jose_n | |
@jose_n | enjoy, and hopefully Bloggy and the methods shown here are useful |
@jose_n | to you for your own application development. |
@jose_n | |
@jose_n | thanks! |
@jose_n | |
@jose_n | (slide 29 is just a list of related frameworks .. some easy t use, some not so easy, but you get the idea.) |
@jose_n | thank yo oroz! |
@Oroz | :) |
@jose_n | alejandro was asking in #qc how well CP and these tools protect your data against insertions or data integrity attacks |
@jose_n | to the best of my knowledge they do so very well ... i haven't figured out a way to do SQL injection in SQLObject-based apps yet ... |
DrFritz | anyone experienced in pda programing? |
@jose_n | XSS will bea matter of your own app's development, mind you ... |
@jose_n | thank you MJesus_ :) |
@alejandro | nice, SQL Object uses a mechanism similar to using Prepared Statements? |
@MJesus_ | thank you very much, indeed! |
DrFritz | any PDA coder? |
@alejandro | good talk jose_n. :-) |
@jose_n | alejandro: maybe ... |
* Salva res |
@jose_n | i haven't looked too closely, but i think so (along with simple simple sanitization) |
@jose_n | err simple input sanitization (ie scrubs ';' or what not) |
@alejandro | then it's hard to identify risks using these frameworks |
@alejandro | in .net framework there is validation per page and it mitigates some known vulnerabilities |
@alejandro | but I think there doesnt exist a way to mitigate these problems yet when you develop web applications |
@alejandro | because developers doesnt mind of validation, so we will have again security problems |
@alejandro | jose_n: how integrated are these frameworks with Web 2.0? using Ajax, EXL, etc? |
@jose_n | alejandro: not familiar with EXL, but you can easily layer someting like AJAX components on this, sure |
@jose_n | tat'd be more at the view layer of the stack |
@jose_n | very easy to do, they integrate nicely with that model |
@jose_n | ie the Prototype.js lib or Rico or what have you .. |
@alejandro | jose_n: I dont know if Web 2.0 is going to expose new security problems and more now with iniciatives like Web Desktop (google desktop, etc) |
@jose_n | so far it has exposed some new classes of problems quite nicely :) |
@alejandro | heh, ok thanks. |
@alejandro | good talk jose_n and thanks for your talk. |
@jose_n | to be fair, RoR is pretty hot and very feature rich |
@jose_n | some features of Ruby lend itself more positively to web programming than does python, ie continuations |
@jose_n | :) |
@jose_n | thank you everyone :) thanks to the organizers for anoher great umeet! |
@jose_n | :) |
@Oroz | thanks jose_n |
Max | plas |
@MJesus_ | oh Jose, the great umeet, is also for you and your nice presentations! |
@Oroz | Max: don't be shy ;) |
@MJesus_ | jeje |
@Oroz | Thanks one more time jose_n |
@Oroz | next talk would be tomorrow at 18GMT, in 22 hours and 30 minutes |
@Oroz | by Polkan Garcia about Inteligent agents embedded in the kernel |
genesis | clap clap |