Tuesday, July 12. 2011
It took me a long time to figure this out, I didn’t want it to end up locked in my head, so here’s a rough guide on how I managed to get a pylons 0.9.7 project to do LDAP authentication. All of the below is done in config/middleware.py.
The key points are:
- “import ldap” (for the obvious reason) and “from paste.auth.basic import AuthBasicHandler”
- Wrap the stacked WSGI ‘app’ object in the AuthBasicHandler you just imported:
app = AuthBasicHandler(app, 'The value you want to appear on the browser dialog box', yourAuthFunctionHere)
- Define an auth function “yourAuthFunctionHere(requestEnvironment, username, password)”. Some tricky bits:
- If this function returns “True”, the request will proceed and there will be a new key in the Request object named ‘REMOTE_USER’ that contains the passed username.
- If this function returns “False”, the user will be prompted again until it succeeds. (I should probably find a way to limit these so people cannot just keep guessing.)
- Python’s LDAP has some strange behaviours:
- Do ldap.initialize outside the auth function or you will swamp the LDAP server with bind requests
- Use synchronous bind (‘bind_s’ as opposed to ‘bind’) – asynchronous bind in the WSGI middleware layer caused some really bizarre behaviour here, including segfaults
- Trap ldap.INVALID_CREDENTIALS and return False when it is raised, or watch all invalid logins crash the server process
- bind (and bind_s) return a tuple, if the first item in the tuple is int(97), the bind worked – otherwise, they might have bound but as an anonymous user, and we need to fail
- the second item in that tuple is a list of messages from the server – I’m not handling those at all today, becuase in the sole case we’re interested in (97, or “auth”), the messages appear to be blank in our environment – there’s no reason to believe this is consistent, and I should probably research this further at some point to provide meaningful feedback to the user on failed auth.
You can’t touch the session from within the WSGI middleware layer
All of this was done because a new server in our datacenter doesn’t have packages for the old build of Apache that we used to configure our LDAP auth back in the day. I’m actually quite pleased at how the new system works, and am glad to be rid of that Apache+PHP millstone that’s been lurking as a dependancy in all of our Pylons projects simply for the LDAP authentication solution.
Tuesday, October 5. 2010
I have a project at work where we are using Pylons/paster as the web service provider. One of the “clients” of this service is written in Flex/Flash, and had as a component the AlivePDF AS3 library for generating a static PDF of the Flash content.
Unfortunately, because Flash cannot save content locally, in order to actually GET this PDF content back to the user, AlivePDF posts a byte array to the service and expects the service to bundle that as a PDF and send it back. They provide a “content.php” file as an example – which, frankly, is some pretty inscrutable code until you manage to figure out what it’s working around. So when one of my employees (the one who selected AlivePDF in the first place) sent me the PHP file, it took as long to understand what he wanted as it did to come up with a Pylons solution. You can find the latter bit below – replace ${service} and ${controller} with your actual values through-out, and trim the ellipses (they are there to indicate there may be additional context on either side of the line I’m giving you):
${service}/config/routing.py:
def make_map():
…
map.connect(’/${controller}/create.php’, controller=’${controller}’, action=‘pdf’) # put this before the default routes, if you have any
…
${service}/controllers/${controller}.py:
Class ${controller}(BaseController):
…
def pdf(self):
response.headers[‘Content-Type’] = request.environ[‘CONTENT_TYPE’]
response.headers[‘Content-Disposition’] = ‘inline; filename=”%s”’ % request.GET[‘name’]
return request.environ[‘wsgi.input’].read(int(request.environ[‘CONTENT_LENGTH’]))
…
Tuesday, November 4. 2008
The always brilliant author of the `from future import *` blog brings us an article discussing a potential JavaScript Hijacking [pdf] scenario – the simple answer is “Don’t send JSON data as a list, send it as an object instead”. That is, if you wanted to send:
[highlight lang=js]
[“foo”, “bar”]
[/highlight]
you can avoid the security hole by sending something like this instead:
[highlight lang=js]
{“data”: [“foo”, “bar”]}
[/highlight]
and then stripping the object on the other end.
Thursday, October 16. 2008
Drag this Make Page Editable link to your “Bookmarks Toolbar” in recent versions of Firefox, and click on it to enable the built-in “Page Composer”, allowing you to edit any page you want! 
Tuesday, October 14. 2008
As a Code Kata, I’ve been working my way through the Project Euler stuff.
Here’s the problem.
Here’s my solution:
[highlight lang=py]
- A generator to derive the Fibonacci sequence
def fib():
x, y = 0, 1
yield x
yield y
while 1:
x, y = y, x+y
yield y
if name == ‘main’:
idx = 0
sum = 0
gen = fib()
while idx <= 4000000:
idx = gen.next()
if (g % 2 == 0): h = h+g
print h
[/highlight]
Note: You want to be careful how you use infinite generators like the ‘fib()’ I created above.
One guy on the forums noted:
Now, replacing an odd number with O and an even with E, we get: O, O, E, O, O, E, O, O, E, O, O, E, O, O, E…And so each third number is even. We don’t need to calculate the odd numbers. Starting from an two odd terms x, y, the series is: x, y, x + y, x + 2y, 2x + 3y, 3x + 5y
Thursday, October 2. 2008
Spent the day poking at Pylons 0.9.7rc2 as well as the new documentation site that came out with the release of Python 2.6 – some sweet stuff in there.
WebOb: The New Middleware Layer on 0.9.7, its Reference page, How WebOb is different and Ian Bicking’s Blog Post about it – Ian is one of those guys who is so smart it fills me with a jealous rage. I’ve already found a lot of useful stuff in WebOb that was missing or hard to do with the older Pylons middleware.
Base Pylons Documentation, AuthKit Cookbook, Roadmap to Pylons 1.0 – just some good links to pylonshq
Python modules I need to brush up on, or just links I used in the course of today’s work:
2.6 Documentation Index, shutil, xdrlib, functools – a lot of functional paradigm stuff moved here?, StringIO, tempfile – probably the best tempfile implementation by a programming language, ever, simpleJSON revved to 2.0.1, 2.6 ‘Standard Library’ Index
Mako – I’m not sure why there are so dang many Pythons template layers. In fact, Preppy is another one that I might use more in the future due to its integration with ReportLab’s PDF Toolkit
The Pylons Book – I’ve already pre-purchased, but wish it had more “nuts and bolts” based on what I’ve seen so far.
Thursday, August 21. 2008
Sorry for the break – I spent the past week or so frantically preparing for, and then attending, my Director’s annual off-site planning meeting. As always, it was a valuable experience – the opportunity to interact with Managers in a more relaxed setting, and to see how each of us attacks a given problem from so many different angles, is incredibly cool. Plus, I got to play golf again. 
Today I’m bringing you a quick example of how to use jQuery to check with a Service to see whether the user should be allowed to toggle the state of a given checkbox. In my example, the “Service” only allows you to check boxes labelled with a prime number. I’m sure there’s a more jQuery-approved method, but this one was simpler to figure out than .val() – I couldn’t figure out how to make that *un*check a box.
Tuesday, August 12. 2008
PHP5’s XMLReader – which I used for my JSON-Like XML post, doesn’t implement a ‘clone’ handler, which came as quite a shock when I attempted to implement a wrapper class that would allow me to push values back into the stream when I had to read-ahead to implement ‘nested data structures’ as suggested by Davey. I had a hard time finding a good example of how to internally implement clone (even Sara Golemon’s book only gives it a brief mention), but I finally came up with something – I’m building it now to see how well it works, or even if it works at all.
Sunday, August 10. 2008
#phpc on Freenode had a discussion tonight about how there’s nothing in XML that’s quite as simple as JSON for encoding types. I came up with this off-the-cuff – as opposed to WDDX, this is more JSON-like in that each ‘XML Document’ encodes only a single value – but that value might be mapped to any of the built-in types.
Of course, the <object> stuff would only work with pretty simple objects – but the fact that it tries at all to instance a class is a step beyond what JSON does, which is ALWAYS an instance of stdClass. You could drop this extra ‘feature’ by remove removing line 43 ($class = …) and changing line 44 to:
[highlight lang=php]$data = new stdClass;[/highlight]
Continue reading "JSON-like XML"
Saturday, August 9. 2008
[highlight lang=php] public function offsetSet($key, $value) {
if ($key === NULL) return $this->push($value);
$this->throwEx(array(‘Do not directly set indices in a %s, use push() instead’, CLASS));
return false;
}
[/highlight] This allows the use of PHP’s ‘push’ syntax: $foo[] = ‘bar’;
Full class after the jump.
Continue reading "Refinement of ringBuffer"
Friday, August 8. 2008
I liked the SPL I used in my last post, so I cracked open my Python Cookbook to a random location and decided to try and implement whatever it landed on in PHP using SPL – that led to the following implementation of a ring buffer.
There certain may be better ways to do it, but this was my first pass, and I think it behaves much how you’d expect a ring buffer to.
Continue reading "Using SPL to implement a ringBuffer"
Thursday, August 7. 2008
Someone in ##PHP was looking for an array that had ‘case-insensitive’ keys, so I threw this together using SPL
Continue reading "Case-insensitive Array access in PHP"
|