Configure player

Close

WWDC Index does not host video files

If you have access to video files, you can configure a URL pattern to be used in a video player.

URL pattern

preview

Use any of these variables in your URL pattern, the pattern is stored in your browsers' local storage.

$id
ID of session: wwdc2001-617
$eventId
ID of event: wwdc2001
$eventContentId
ID of session without event part: 617
$eventShortId
Shortened ID of event: wwdc01
$year
Year of session: 2001
$extension
Extension of original filename: mov
$filenameAlmostEvery
Filename from "(Almost) Every..." gist: ...

WWDC01 • Session 617

WebObjects Security

WebObjects • 48:10

This session discusses security within WebObjects applications. Topics include techniques for securing page generation and direct action invocation for anonymous users, gathering credentials for authentication, just-in-time login approaches, and using digital certificates. This session also covers automatic connection to pages over SSL to sites which require privacy, and access control.

Speaker: David Neumann

Unlisted on Apple Developer site

Transcript

This transcript was generated using Whisper, it has known transcription errors. We are working on an improved version.

Okay, well, I've got six areas I'm going to be covering today. Privacy is basically going to be covering things with SSL, because sometimes that can be a bit tedious to work with with WebObjects. Protecting resources, they're going to be talking about overriding things in the woof request response loop to kind of protect things and lock your app down. On authentication, just a little bit on using maybe some more irritating things with authentication. HTTP challenge panels and digital certificates.

For persistent data integrity, things like helping you make databases where your passwords and your credit card numbers, for example, aren't fully exposed. For messaging integrity, a little bit on using digital signatures to do things where you can do message between apps, where you can kind of verify what's going on. And in access control, that's kind of the biggest one. Unfortunately, I think I'm probably going to have to be able to spend the least amount of time on.

But in that, I'm talking about using access controls to protect your EOs and pages. And I've got a demonstration there, or at least some code that I can let you all have after this show, that shows using the Java ACL package and integrated that with EOs. So, a lot to go. So first, keeping it private.

This is the main problem with, I guess, SSL and WebObjects. You've got these partial URLs. And while that's great from an app server standpoint, the app doesn't have to know about the deployment environment. It's kind of a problem if you want to actually force things to go to a certain web server, or in this case, SSL, because if you came in over HTTP, that would be an HTTP URL. If you came in over HTTPS, you'd be okay.

So, the trick is, you've got to create absolute URLs or come to the app over absolute URLs. So, can I have a guess, too, please? Alright, so I'm going to come into here. This is a project, this WWDC app is something that I'm going to try and make available to any one of y'all that want to check it out. It basically is in code, everything I'm demoing here today, including just some reusable components. First of all, secure hyperlink.

is a way of generating absolute URLs. You can basically use this instead of WoW hyperlink. This is sort of the gist of what's going on. Notice I've got a WoW generic container here. It's an element named A for anchor. Instead of just binding this thing to an action, I bind invoke action to a method on the page called invoke action, and I have href bound to a method called href. The action that gets invoked on the server, I can set the URL or the href I want to associate with that action using this technique. So let's take a look at the source for this.

Okay. And that's how I'm generating the href. Normally, if WebObjects is just doing things normally, it asks the context for its component action URL. In this case, if this binding says it should be under a secure mode, all it does is take HTTPS and append the host name to the, prepend the host name to the URL. And then I do the same thing for a form. And these things are based on a framework. This is the secure form, by the way. Same basic thing.

This stuff is based on components you can find in WebObjects 5 called component elements. This stuff has been available, actually, I think since WebObjects 4. Not many people know about this framework. But basically what it is, is just about all the dynamic elements you're familiar with implemented as components using all the high-speed things that were done to make components fast. And I use that as a template. And in fact, I subclassed one of those guys called WX Hyperlink here to create the secure hyperlink. So what this looks like.

This is a page that right now is over SSL. And because of some demoing issues, I'm going to leave it over SSL. But just to give you a little bit of a sense of what it looks like. I'm going to have to take my word for it that that is an absolute URL behind that hyperlink, and it isn't... This doesn't look like HTTPS because I came in over HTTPS. It looks like HTTPS because that's the full URL that was put up there.

So, let me go back here. Can I have the slides back? Okay. Now, there's a better way, in my opinion, to actually get to SSL than using these hyperlinks. And that would be to do SSL via redirection. And the technique that I've used in the demo application is I override a pender response, and if you're not coming in over SSL, I basically tell you to either access is denied, or if the page requires it, I redirect you to it.

Of course, the trick there is detecting SSL. There's really no hard and fast rule for this. These are just some heuristics you might use in your implementation. I have an implementation called isRequestSecure that you can use that uses this type of information, the HTTPS header and the server port. But you really have to get with your deployment engineer to figure out exactly what they're doing so you can look for the right thing to tell whether or not they're coming in over secure connection. Okay.

So, can I have guest two again, please? So basically what this demo app is, just by the way, is a simple commerce application, and it isn't just purely demo-ware. I wanted to show some of these security concepts in the context of, like, a real application. And even apart from the security stuff, you might find this application useful as an example or as a starting point for making a commerce site.

So anyway, some of these things require SSL. As it turns out, this create account page requires HTTPS. Since I'm in it, the request is secure. If I'm not, a redirect occurs. Same thing with this sign-in page. If I'm not over a secure request, it does a redirect and comes in over SSL.

The reason I like this better than just making the link SSL, like, imagine that this particular username and password is a link to a website. The page is over HTTP, but the form was over SSL. The user wouldn't have any feedback that they're on a secure page. It would look unsecure to them, and they might feel uncomfortable about submitting it, even though it was safe.

If the page itself makes a decision as to whether or not it should be secure, and can make itself secure on the fly, then you're always guaranteed that when they get to this page, they're secure, and therefore when they submit it, you're secure. Okay, so back to the slides.

One thing I guess I should point out about the implementation that I've done here and that y'all can take a look at, Before the redirect happens, I try to do this redirect in a way where I don't get side effects. I've seen techniques like this before where you've got a double invocation of an action, or you've got a double appended response on the page, and I wanted you to have something where when you went to the page, it never generated at all unless it was okay to see it.

And furthermore, when you came back to it on the redirect, you didn't re-invoke the action. So when the redirect actually happens, instead of re-invoking the URI that you originally got, it basically re-invokes a URI that points to a direct action that's a special direct action I call SSL return that goes and recovers the page from the session and then tells it to finish generating its response.

Now, you've got your entire app over SSL, every page is accessed over SSL, and you think everything is really secure, except for this little thing. And what I mean by session hijacking is someone recovering your session ID through maybe looking over your shoulder, or you get up to go to the bathroom and come back to your system, and all of a sudden they have a session ID to your E-Trade account, and they're taking a look at your portfolio on their machine.

So you might want to disable this, and it's not terribly easy, because at some point the session ID has to be in the clear. If you put the session, but if you, what I, the solution I use is to emit a cookie that's specific to the session, and when I do that, I check for that on every single request.

And so if someone goes to some other machine, not only would they have to look over my shoulder casually, they'd also have to get on my machine, get my cookie file, get the cookie, go over to their machine, stick it in there, and then try and hijack it from there. And if they don't, I throw up like an access denied page.

So this section is somewhat similar to the SSL section in that I'm overwriting a pended response and some of the things in this section. Here I'm talking about overwriting whoops request handling stuff. As it turns out, there's lots of ways to get into a WebObjects application. You can specify a page name. You could specify a direct action on the URL. So it's kind of important to just have the app smart enough not to generate things.

by default, unless you're authenticated, just push the logic into the pages themselves to prevent them from accidentally rendering when they shouldn't. So one way you can do that is to override page generation, and that would mean overwriting append response and not calling super unless you're logged in for certain pages. The other thing you might do is page creation protection, where you override page with name in the application class, and therefore prevent page construction. And there's some pros and cons to this.

Boy, that's a tight one. The advantage to overwriting page with name is you prevent the constructor from ever executing. So if the constructor is doing something that requires sensitive code, it never executes unless you're authorized. But if you override page with name in context and not authorize for page, you return a page that they can't see, you might return null, you might raise an exception. Now the code that calls that needs to handle that. So basically, in order to take advantage of that, you have to alter all the places in your application where you use page with name.

With page generation protection, you actually let the page get created and you send it a message saying, "Is it okay to generate you?" And if so, then it can generate. The only downside is you have to make sure there's no sensitive logic in the constructor code of the page, because that will execute under this scenario.

Okay, now this is something else I don't think most people realize, but you know, if you log in and you have a link to a direct action, and if you never log in, you never see that link on the page, it really doesn't mean you can't type the direct action link in the location field of the browser and just directly access that thing anyway.

Now, if you use the technique I just talked about for pages, you might prevent the page from rendering. No one can see the page, but that doesn't prevent the direct action that got to that page from invoking. So, if there's something sensitive going on in there, and you just want to globally prevent any direct action from firing, unless it's actually okay or it's a non-sensitive direct action, you can override perform action name, inspect the passed in action name, and just don't call super. Don't call super if you're really not allowed to invoke that action. And you also have access to the will request, so in that method, you could look at the form values for the will request and the action name itself.

Now, you might not think this particular topic, backtracking, would be specific to I've put a demo example of a little algorithm that detects backtracking. Even if you disable client-side caching, you still might want to know or give the user some feedback that backtracking isn't something you want. In a commerce site, you want people to backtrack. But there are certain aspects of a commerce site, like the checkout process, when you're going through Step 1, 2, and 3. You probably don't want them to backtrack to Step 3 after they've already made the order.

So, it'd be kind of nice to detect backtracking, and I do it by comparing context IDs of the current request to the previous one, and some other things that are relevant to direct actions. And I don't call superinvoke action if they've backtracked on those pages. Instead, I just return null, which has the effect of refreshing the page.

So, can I have guest 2 again, please? This action here, Account Edit, requires authentication. And the page itself knows that it can't render itself unless you're authenticated. So instead, it shows the access denied page, which puts this big title, access not allowed, and you must log in to access this direct action. Now, this page down here, Secret Stuff, is a... Page, just a WOC component.

And again, this particular page, instead of the direct action, this time it's the page that's decided it can't render itself, and so it comes up like this. Now, if I log in, I've got a test account here. says, "I'm logged in. I should be able to go to account edit now." Okay, then I can see my account information. Okay.

You probably noticed that these security demos are kind of boring, and I couldn't do anything more graphical than just this, and sorry about that, but most of the stuff is happening behind the scenes, and I know it's not exciting when you see a URL change from HTTP to HTTPS, but it's the best I can do, okay? Okay, authentication.

This, I'm not going to go into all these different ways you can authenticate or gather credentials, but I will talk about a couple things like when to log in. The typical thing in a WebObjects application, as it turns out, is what I call this front gate login. But there's other ways that I think are more friendly, like on-demand, and you might prompt for login on a session timeout.

Now, this is the usual means, like people put a login panel on the main page, and you have to go through that login panel to get anywhere else. So even if you did have direct actions, if they went and followed the advice before and locked those down or didn't define any to vector into the app, well, it doesn't matter, because you've got to go in here. So it's like, hey, come to my site. I've got this really interesting thing over here, but I can't give you a URL to it, because you've got to log in, and then you've got to navigate to it, and then you can see it.

And people go, well, I'm not even going to bother. It'd be nice to just sort of put a direct action on an email message you send to someone, have them click on it, and if they're not authenticated, just have them prompt for it. So it'd be nice if you could do something a little bit better than this sort of front gate thing, and that's browse on demand. And the cool thing about the previous stuff I showed you about resource protection, when you override a pender response and perform action, you're basically making your direct action objects and your pages smart enough to know when it's okay for them to show themselves.

And given that, you can just navigate through the app, and instead of showing an access denied page like I just showed there, you might as well just prompt them for login, or prompt them for login to create an account. And if they create an account and they do so successfully, take them to the intended resource. Okay, so we've come to that. In this case, guess two, please.

I'm going to start a new session here. And let's see, I need to start just shopping here. So I've got some specials down here. By the way, the special logic actually works. It overrides the default price. And let's go home and drill through some of these categories. Let's see, I'll add this to my shopping cart. So I'm just browsing around the page, and I'm able to access some of this stuff, and then I come to this checkout button. And click that, and it says, hey, you're not logged in. So OK, I'll log in.

and it goes right where I left off. When I clicked that page, the page didn't know about it. It didn't actually, it was like a super class that figured out how to return the login page. If I had been logged in, I would have just gone here. So the way this algorithm works is you go to the page, append response starts to generate, the page goes, oh, my God, you're not logged in. Then it creates a login response instead. Instead of doing super append response on the page, it goes and gets the login page and tells it to generate response, and then returns that in an append response. So I see a login page.

But before it does that, I take the page and I put it in a session variable. So when they do successfully log in, the login action can recover that guy from the session and then tell it to finish generating this response, and then you see this step one of the checkout page right here.

[Transcript missing]

Okay. If I had time to put the Visa and MasterCard images up there, I would have, but that's what those things are, so I'm picking my credit card.

and do next. And OK. So I'm at the confirmation page. And let's say I backtrack. OK. It knows that I did that because it compared the context ID and knew that I--

[Transcript missing]

All right, now I'm not--don't be frightened by this. I'm not actually going to go through all those. I'm going to--I've already demonstrated HTML page. I'm going to talk about HTTP panel just a little bit and client certificates and just touch on biometric for a second.

The HTTP challenge panel--actually with WebObjects, since you've got an HTML page, it's probably not necessary to use this, but you might have a situation where you've got to use it because people are using the HTTP challenge panel, that thing that web server pops up or-- This pops up if you send back a certain header.

And it does kind of have an advantage that it can give you an effective single sign-on, but it can be a little tricky. Because if you're not used to it, you've got to look for certain headers in the request, you've got to emit certain headers, the headers are going to be base64 encoded, and your web server might not work as is. You might have to use a special web server.

For example, this authorization header is the one that gets sent back when you're authorized. And peer web service with CGI and Netscape with CGI don't pass it, but Netscape with NSAPI and the Apache module do. And I'm sure there's some other combinations that do as well, but you just have to be aware of it.

So you see the panel, and then you never get the header, and you wonder why. Well, this is why. The interface might not be supporting it. And the other thing that's really confusing is this realm. One way that you can get this sort of single sign-on effect... is you can pick a realm on your WebObjects app that matches the same realms that need to be protected on the web server side for static pages.

And so when you authenticate to the WebObjects application, and you access something else that matches that realm, like some of these static pages, your browser is going to pass the authorization stuff down to the web server, and then the web server does the authentication to see whether or not you can see it. Anyway, and that gives you the single sign-on effect. So that's kind of cool.

But you know what's cooler? Are these things, if you can get away with it. If you're on an intranet, you might be able to get away with this. Basically, have people authenticate with a client-side certificate. And you've heard of server-side certificates, the kinds of things that you buy to put in your web server so you can get SSL. This is a similar cert, but for the user. Something the user submits, something you configure the web server to ask for.

And it can also give you single sign-on, because you're basically doing a cryptographic operation between the client and the server and authenticating to the web server, and then getting access to everything behind it. And that might be good enough, and you're done, and the WebObjects app doesn't even have to be aware that it's happening. Let me get to this. I'll mention something about the second bolt, though.

However, in some cases, you might actually want to get the digital certificate. And unfortunately, that's a little bit problematic right now with the WoW adapters. So to address that, even though I'm not going to demo that, a nice gentleman made a special WoW adapter that works with Apache as a module on Mac OS X that will properly ask Apache for the certificate.

So you can go to that proper header where the certificate is and get that guy and pass it on to your WebObjects application so your WebObjects application can do things like validate it or look at user information in the certificate and see if there's an enterprise object associated with that guy in some type of hook on the application side, like Application Awake or something like that.

Now here's something you might actually want to do with that digital certificate on the server. You might want to see if the certificate's been revoked. That's one thing you might want to do in your code. And you do that by looking at a certificate revocation list. And VeriSign and all these other CAs have certificate revocation lists usually posted on the net over HTTP.

You can also go to some clearinghouse for this, a validation authority, and use OCSP maybe to get just the status of the particular certificate you're interested in. The reason you might want to do this is this Microsoft example I wanted to share with you. About a month ago, someone posing as a Microsoft employee went to VeriSign, and VeriSign mistakenly gave them a certificate and a private key that let this gentleman sign code as if he's Microsoft Corporation. So when you get that little panel that says, trust Microsoft Corporation, and you go, yeah, always, that means you could be downloading this guy's stuff, and God knows what you're installing. And that wouldn't happen.

That cert got immediately revoked. I mean, they found out they made a mistake. They immediately revoked the certificate, or VeriSign did. It was kind of VeriSign's flub, I guess. But if no one's checking the certificate status, and not many people do, talk about an interesting attack. Everything looks safe, and in fact, you're being attacked.

So it's probably not a bad thing to do. Okay. And lastly, in this authentication section, just a note on biometrics. Personally, I think they're interesting. I don't think I'd recommend them alone, but if you combine them with a password, they're pretty cool. And another thing I want people to show.

I'll show you at least one-on-one after this is an example of a biometric system where it detects who you are by how you type. It's kind of interesting. But most of these things are thumbprint, palmprint, something about you, your voice, that kind of thing. And a lot of times they're used with digital certificates as passphrases to unlock the private key.

Now, you've gone to all this trouble to have these strong passwords. You've got all the SSL, everything's hunky-dory, but then your users pick passwords like foobar, numbers, 1, 2, 3, 4, that kind of thing. And they're susceptible to dictionary attacks. So you might want to prevent people from logging in over and over again with a dictionary attack on your system. So I've got a... demo of that.

This app happens to implement an intrusion sort of detection stuff. Can I have a guess too, please? So, I'll log in with a valid username, but gibberish password. Did I say "password"? Must be from Texas. Okay. Wow, I must have, like, torqued that thing down to get only one shot at it. I thought I had it set to three, but I must have set it to one. But that's pretty rude. I think I'd, you know, maybe make that a little bit longer. That demo's over.

There's two kinds of counts you want to do. One based on the username and one based on the IP address. Even though people can spoof IP addresses, you know. But you still want to do it because you want to sort of discourage the possibility of someone going to a workstation and going to different workstations with the same username or going to the same workstation as many different usernames and attacking that way.

So if you check both and you make sure that not too many happen within a certain period of time, you know, then you should be, well, quite a bit safer. Plus, you've got a log. This particular demo application is writing these records to the database. When a failed login attempt happens, it writes this thing called an intrusion log to the database.

Now, persistent data integrity, this has to do with things that happen outside your application. There's hashing, encryption, and signatures and timestamps. So, in the case of passwords, it's I don't know how many people do this, but it sure seems I've been to a few sites, and I've seen these password columns, and that password looks pretty damn human-readable, you know? And it'd be kind of nice if it was at least encrypted or hashed. And basically, hashing a password is probably at least a pretty good way of storing it if you're going to store it in a database.

And the way the demo application works, by the way, is to do just that. When you sign in for an account and provide a password, the server hashes that password and stores the hash, and it's a one-way function, so you can't recover the password from the hash. And when I authenticate, when I go to that login panel, I'm fetching the user, taking the password that they inserted, hashing that, and then looking at the hash for the user's password, and I compare them, and if they're the same, then I know that they're okay and they get to get in. And that's a good way to do encryption.

I assume everyone knows what a hash is, so I'm going to have to move on. Encryption. Now this is a situation where you make the thing look scrambled, but you can actually recover it. And for passwords, that's not necessary, because you're just doing a comparison. But for credit card number, you might want to encrypt it. And again, I've seen a few websites, and you've probably heard of a few, where they go in and they hack in and they get all the credit cards. Sometimes those people do go ahead and encrypt their database.

And they just don't put the secret key in a safe place. But hey, at least you've got to encrypt things like that. And there's ways of doing it with key value coding, with special accessors, so it happens transparently, so the rest of your app doesn't have to care.

Well, unfortunately, I guess after you do that, people might hack the database, but to get the passwords, they have to hack the database, get the credit cards, then hack some server that's storing the private key or the secret key, and get that too. But you could put that secret key in a pretty safe place, kind of locks within the locks. And one place might be the--on 10, might be the Mac OS X keychain.

If you went to the, like, the security framework The keychain is locked down. In my demo example, I'm putting the secret key used for the encryption in a Java key file in the project. If you really want to be secure, you can put the key in a hardware device, like Chrysalis and Encipher create these things, where all the cryptographic operations happen on the device. The private key or the secret key never even leaves that device to get into memory, so they're extremely difficult to hack.

You actually really have to be at the machine and have possession of this hardware token in order to hack into it. And to do this stuff, can I have a guess, too, please? To do all this stuff, I'm actually using the Java cryptographic extensions. They work with Java 2, and that's kind of the nice thing about WebObjects 5, is that I can use all these Java 2 things and just drop the jars in from Sun's website and they work. So in this case, I'm just going to show the source code to my credit card class.

And actually, let me come to this. Worry about that in a second. OK. This is a method, the decrypted CC number and set decrypted CC number. This is the method that all the code calls. And it does the encryption and decryption on the fly. And the encryption and decryption is actually handled in this class called Security Utilities, Decrypted Base64 String.

Basically, what I tried to do in this demo was factor out as much of the security-related stuff into this class called Security Utilities. So you'd have one place to look at it and actually comment it. And that does the work of encrypting it and then Base64 encoding it.

And I Base64 encode it so I can just sort of drop it in any kind of database. And regardless of what type of-- even if they just have just barely a few ASCII characters supported for that column, I can safely store the thing. There's an actual attribute down here called credit card number. And that sets and gets this encrypted gibberish.

So if you look at the return value for that, you see the encrypted value, which is just a bunch of funky looking stuff. So can I have the machine back here? Actually, you can see one of the reasons I wanted to have this demo for you guys to download is that 99% of the stuff going on in these things is happening underneath the covers.

It's stuff you can't see. So I wanted you to be able to, if you came out here for the developer conference, I wanted you to be able to walk away with something that would carry you forth afterwards. Signatures and timestamps. And for this, this has to do with like safely storing documents.

You could store a hash of a document. You could store the document, you could store a hash, and that might be good if you're protecting against things like just accidental corruption of the file. Because you can check the hash and see if it matches up in a future date, and if it looks, if the hash for the document matches what's in the database, you have some reliance that it wasn't tampered with. But someone could always alter the document, create a new hash, and store both, and then you wouldn't see that someone had altered things.

So that's why you might want to digitally sign the document and store the signature with it. And if you want to make sure that, if it was important that something happened, like this was a contract, if it was important that time was recorded on this, you might want to use a third party to get a digital timestamp.

If you all don't know what that is, it's basically there's these third parties where you can take your document, hash it, take the hash, send it to these guys, I think surety.com is one of them, and they will basically put a timestamp in this. Take your hash. Put a timestamp. Digitally sign that, and then send that back to you, and you can take that and put it in the database.

And as it turns out, there's actually, this is what I'm describing is basically a digital receipt. And there's an XML standard for doing documents like this. You don't have to put things in two places. You can just put them all in one XML document. And that URL at the bottom is the org where you can find the DTD for that.

Messaging Integrity. This is actually very similar to the document stuff, but instead of storing things persistently, I'm talking here about throwing things up to the user. Adobe Five, not the reader, but Adobe Acrobat Five, supports digital signatures on Mac OS 9, it actually runs on Mac OS X and Classic, and should be, I guess, carbonized pretty soon, I'm not sure, and on Windows.

So you basically have this solution where you can put it on just about any desktop out there and get digital signatures done. And you might want to do that for, actually the point at the bottom I think is the coolest, paperless workflow, or, well actually employee forms processing, those two things inside a business.

You're in an intranet, you could actually distribute the software on clients, and your WebObjects application could, like, you're doing stuff and it returns a contract saying, "Do you really wish to agree to this type of insurance or claims processing for HR?" And you can have your private certificate, which, hey, might be embedded on one of these, which would be kind of cool, and then you can insert this, if it were a smart card, this one is, and don't get excited. If this were a smart card, you could stick it in the machine and then digitally sign the document with it.

You could, like, save the signed version on your system, or you could post the signed document back up to the server. And in a way that's a lot better than a handwritten signature, and there's nothing to fax, you know, there's no paper, and it's pretty secure, or can be if you have a pretty strong public key infrastructure.

This B2B thing is very similar to what you saw in a way last, just the other day, when you saw a WebObjects thing on XML. Here I'm talking about doing exactly what happened there. You got two WebObjects apps talking to each other, but it wouldn't be nice if you could digitally sign just some arbitrary content, and so the receiver of it could know that this wasn't some Joe Blow with no authority to buy the 100 Power Macs.

To do that in WebObjects, you have a few things to help you. You've got WoW Direct Actions to turn WoW apps into services. You've got the WoW Message API for programmatically creating requests, sending them to a server, and getting a response back. And you have some XML management stuff for generating it and interpreting it. So what I did, actually, I took the demo that you saw yesterday for XML processing, just took it and added Utility Class, which again is another thing that will be a resource for you guys.

And then added a little bit of code to the actual original source code to add a signature to that XML. So the request ends up getting signed, I put the signature in a header field, and then I send that down to the server, and the server validates that the content and the signature passed in are okay. So, go to that. Guest 2, please.

Okay, this is the class with all of the digital signature stuff. And let me show you where I build up this request. Let's see. Or actually interpret the response. Here's the code that does it. As it turns out, I've got an element called signature value, and then I take the body of the SOAP document in this case, I take those two pieces of information, and then I send them to this signature XML utilities class I was talking about, and say, "Veofer XML element with the signature, pass in the body, pass in the base64 encoded signature, and an output format for it to use." And then it just returns whether or not that thing was okay. This isn't specific to SOAP.

I mean, you could use this particular utility with anything. And it uses, again, the Java cryptographic extensions to perform the digital signature and the digital signature verification. I would show you the demo, but it's exactly like yesterday's. I mean, you just fill something in and you go to it, and besides, it's not running. So.

This is actually the last piece of this guy, the sixth part, access control. So you're authenticating to a web server, and you've authenticated, and now we know who you are. Most of the stuff I've talked about so far is, what do I do if I don't know who you are? Okay, but now I do. So I've got an enterprise object or a page, and the page has certain restrictions, and I'm a user, and I might be in certain groups. So whether I get to see it or edit it or do something else to it depends on the combination of state.

Now, here's something actually I presented, I think, before, with one little wrinkle here. Here's just an example implementation you might stick on an abstract superclass for enterprise objects. Can show and can edit and pass in a user object, and just let the enterprise object figure out what to do with it.

This is a nice, simple interface that the higher levels in your app can program to. Because if you just use a basic interface like that, You can apply conditionals, you can filter out EOs, and one thing I'd recommend in this particular area is if you have an EO editing context, you might subclass it and override Objects with Specific Attrification, call super, and the actual results that you kick back, you might ask the results set, are you readable, are you readable, are you readable, and if you are, put you in a subset and only return the subset. Then you kind of have a global way of keeping the results set to a minimum.

Just not so you don't show a count of seven and the user only sees five rows. That doesn't look good. And then maybe you could look at group membership based on the users to collectively hide and show big swaths of the UI. But anyway, let me back up.

The other thing I didn't-actually in my demo application I have examples of using an implementation of can show and can edit. I don't have an example of value for key user, take value for key user. But the idea for that is similar to key value coding, except the user argument is thrown in as well. And the reason you might want to add something like that, or an interface or something like that, is you might have a big honking record with like a hundred columns.

And guests can see this much, but certain privileged people only get to see these attributes. You know, and if you had a component which is smart enough to use that API, and just decided to use that and standardize on it, you know, you could control access at the granularity of the attribute with an interface like that.

Now, what about the implementation behind an interface like that? Okay, here's a very simple interface. It makes some assumptions. I've got a, uh, I've got a, uh, I've got a These are methods that might be on, say, a product or a category. As it turns out, in my demo application, the category entity and the product entity subclass from an abstract class called ProtectedObject, and they implement default implementations of this.

Mine are a bit more advanced, as I'll show, but that's where you'd put it. Just put it on an EO. And in this particular example, the thing might have a relationship to its creator, a 2-1 relationship, and it might have a relationship to its owners, a 2-many relationship.

And if, this particular logic says, if the passed-in user equals the creator, you get to see it. If it's a member of the owners, you get to see it. If not, it's false. And the can't edit is trivial. Basically, the rule is, if you can see it, you get to edit it. So, a simple one, but you could get more elaborate.

[Transcript missing]

This is a diagram view of the classes which are relevant to the Access Control Stuff I don't know if y'all knew this, actually it came as a surprise to me a few months ago. There's actually a Java spec for defining ACLs. It's called, if I remember correctly, javasecurity.acl and there's some classes in there. And so, what I've got here are a bunch of EOs, Eogeneric Records, that implement those interfaces.

And instead of like writing my own implementation of an ACL policy that interprets all the state and figures out what to do, I've got an EO that actually uses the implementation provided by Sun to digest the state and tell what's going on. So, actually it's not very much code.

The classes involved are: ACL Entry, which implements the Java ACL Entry user interface. UserGroup implements the group interface. Permission implements the permission interface. Person implements the principal interface. All these guys are networked together and basically ready to work with any Java ACL policy that adheres to the interfaces defined by JavaSoft. So, let me go into the application here. I knew I was going to do that. I've got to make sure I type this right.

Let me take a look at something that's protected categories. Now what I've done is kind of logged into an administration form of this application and I'm not even going to, I'm going to try to actually explain this. I don't know how I'm going to do it. Okay, so we've got product categories, and I'm logged in as the admin. I'm in the marketing group.

And what you're looking at here is a list of all of the categories in the system. So I'm in as an administrator, but I'm doing some things you'd never put in an administration user interface because I want to illustrate what's going on here. As it turns out, the accessories cool category, I can edit its name and so forth, it's got these three access control list entries. Okay, and I'm sorry the font's kind of small, but I'm going to go ahead and do that. I probably should have boosted for this.

But let me read it for you. If you're in the marketing group, you get to read it. If you're in the administration group, you get to read it. If you're the user M. Neuman, you get to read and write it. Okay, and as it turns out, admin is in the marketing group. And therefore, what does that mean? Marketing group, read. Now, what's kind of cool about ACLs is that unlike the Unix file system, if someone's in a group and they get to read it, you can strategically pull someone out, remove access.

So let me edit this guy. And what you're seeing here is that here's an ACL edit component. It's part of the project that you will get if you want it. And let's add an ACL here for, that's applicable to the admin, not applicable to a group. I'll make it a read permission and I'll select negate. Okay.

and save this. And if you look down here, I can't read it anymore, and this list of available permissions is now empty. Right, so that's how it works. And you can just sort of keep stacking these things on. And the way the Java policy works is it takes these two sets and it merges them, and negatives cancel out positives, and what you're-the resulting set is a set of available permissions. And then all I do in my canShow and canEdit methods is just call one line on the ACL policy which says, "Do you have this permission or not? Yes or no?" And then return that.

So it's a pretty clean little interface, I think. And you can, like, add new permissions to make up different things. ReadWrite, I added one called Upload. You might have other types of permissions or things you might want to randomly stick in here, and it's pretty easy to extend.

Okay, so the first thing I covered was protecting privacy. That was SSL components to generate absolute URLs. I showed redirection, detection of SSL, and doing that without side effects. I didn't want the side effect of the double generation of an action or the double generation of a page.

For protecting resources, I showed overriding some request handling methods. I think they were performActionNamed, pageWithName, and appendResponse. And one thing I didn't talk about, but I think might be important, is if you wanted to like totally override everything in the app, or at least inspect everything, you can override dispatchRequest on the application object.

And you can ask the request, "What is your request handler?" and actually lock down things like the resource manager. The resource manager is responsible for vending out images and maybe charts or dynamic graphs. If it's the resource manager, you can ask the request handler, "What is your request handler?" and actually lock down things like the resource manager. The resource manager is responsible for vending out images and maybe charts or dynamic graphs. If it's the resource manager, you can ask the request handler, "What is your request handler?" and actually lock down things like the resource manager.

The resource manager is responsible for vending out images and maybe charts or dynamic graphs. If it's the resource manager, you might look at the URL and you might look at what kind of resource it's trying to get, and if they're not logged in, maybe they don't get to see that. I meant to mention that and didn't, but that's just one of the things in protecting resources. On authentication, I talked about using digital certificates and the importance of actually validating their status.

and for persistent data integrity talked about and showed using hashing of passwords and encrypting credit cards and talked about digitally signing documents. And for messaging integrity, I actually did sign a document, digitally signed a request and then validated that request on a server. And then finally for access control, was using ACL implementation and combined that with EOs so you could get the best of these Java standards plus what UF has to offer.

These are the kind of places you might want to go to get some more information. This fact from RSA is awesome. If you want to know a lot about security in a nutshell, it's a pretty good resource. If you're interested in protecting your secret keys, InCypher has a pretty neat device for storing that. So do a few other companies. Rainbow comes to mind.

And Crystalis. Digital Receipt, that's an open source place you can get the DTD for the digital receipt stuff. Validating Certificates, that's a company that validates certificates. Certificate Authority, there's many companies that do that. You've got VeriSign, there's Thought, there's Interest.net. Digital Timestamp, actually that should be Surety.com. Surety.com. And then Signing Plugin, Adobe.com.

So. I guess we still have, there's still lab left today, so we're at 10:30, you still have a chance to go and play with WebObjects 5, and if you feel like it, you might even vote for the app server thing. And the next presentation is Optimizing WebObjects. That's coming up a little bit later. It's not directly related to it, but, you know, it's Friday, and there just isn't much left, so, you know, I had to put something on this slide. Feedback form, of course, on WebObjects later on today.

and here's who to contact if you have, like, want to know more or you want to have feedback on the product or problems and so forth. Our Director of WebObjects Engineering and Bob Frazier for product marketing at the same email address. And if you're interested in consulting, integration, and training and so forth, there's the iServices thing. You've seen all this many times this week.