Archive for May, 2008

Published by Fabian on 27 May 2008

Watch out with OpenID

Yesterday night i finished implementing openID with one of the web applications I am working on. In that case it was PHP based and using Zend_OpenID. At least I thought I finished it.
Today I was discovering that I missed an important part.
I guess it is because I was so happy that I finally got messages back from Google and claimID. But openID is a 4 step procedure, not a 3 step one:

  1. We take the user supplied openID url and validate that it matches one of our users.
  2. We request from that URL and get some HTML back where we need to discover the actual server back (Am I the only one finding this procedure hacky?)
  3. We redirect to the actual openID server, it will ask our user for login and redirect back.
  4. We get redirected back and get some information on the user. Take the openID url and are ready to go.
    What we are getting back is an HTTP-GET request made from an URL which we think comes from the openID provider. Actually the most important part of the openID authentication is to not trust this data. This could be faked by hackers, well actually even simple minded could do that :-) . So the last step is:
    Validate the received parameters against the same openID server.

The nasty thing is that you could think that after step 3  you are done. If you stop there you not just implemented openID, but login for everyone.

An interesting side note is that Yahoo! openID is broken at the moment. It returns on discovery via a valid openID:

<link rel="openid2.provider" href="https://open.login.yahooapis.com/openid/op/auth">
<link rel="openid.server" href="https://open.login.yahooapis.com/openid/op/1.1/auth">

Both actually are nonworking URLs. The first even states that Yahoo only supports the openID v2. Perhaps they should update then their discovery url so their service gets found?

Update:

Well actually Yahoo no longer uses HTML discovery, but they havent removed the discovery from the page. That was confusing me. Yahoo supports however now Yadis XRD based detection, which unfortunalty is not yet adressed in Zend Framework.

Published by Fabian on 15 May 2008

HyperJAXB 3 – the fastest way from XML to DB

In a current project we are about to collect XML and send them out aggregated each day. Its basically a trivial Task, but keeping it maintainable and extendable for next phase of the project possibly coming is the main requirement.

In the Past I was a regular fan of JOX, which allows you to model your XML as java classes. But at that time you had to do it by hand.

Some time later now JAXB is a really good tool (actually its an API, there is a RI from Sun that also is part of Java 6). It creates Java Classes from XSD. Then only the way to the DB would be your work.

HyperJAXB to the rescue! Originally created to support Hibernate, it now is fully compatible to EJB3/JPA standards. It invokes JAXB generator on the given schema and post processes then the generated classes, making them persistable.

The project offers a complete Maven2 package that does all the tricks for you. just put your XSD inside. fire up the maven build and enjoy these complicated technologies (Maven, XML using JAXB and Java Annotations, ORM using Hibernate and Java Annotations and JPA) doing most of the work for you. All what is left for you is to write a class that does:

//get JAXB Helper to do XML->Object conversion (unmarshalling)
Unmarshaller u = JAXBContext.newInstance("demo").createUnmarshaller();
//read the object
DemoObject item = (DemoObject) u.unmarshal(new File("\\tmp\\demo.xml"));
//get JPA Helper to do Object->DB
EntityManager em = Persistence.createEntityManagerFactory("demo").createEntityManager();
//persist the object
em.persist(data);

I think this is really, really nice. I liked JAXB and JPA before I found HyperJAXB 3, but now I love them even more. You can start solving the functional issues and stop fighting the infrastructure.

Well not completely, depending on who wrote the XSD, the generated classes and Hibernate tables might look a bit messy. If that bothers you (because you might want use direct SQL from somewhere) you can tweak the XSD to make the result nicer. Either by playing with XSD mechanics (referencing elements, rather than nesting them) or customize the XSD with some HyperJAXB 3 annotations.

Update:
there is a new package: hibernate.entitymanager 3.3.2.GA that does not need the workaround below.
Make sure to update the pom.xml of your HyberJAXB project.

Note:
Unfortunately there is a small glitch in latest Hibernate packages that had cost me half a day :-)
The hibernate.entitymanager 3.3.1.ga package depends on hibernate 3.2.4ga
But 3.2.4.ga contains a bug that prevents automatically generated PKs from working. This is in the HyberJAXB cases by default true for all objects.

To resolve the issue you need to modify your pom like this:

		<dependency>
			<groupId>org.hibernate</groupId>
			<artifactId>hibernate-entitymanager</artifactId>
			<version>3.3.1.ga</version>
			<exclusions>
				<!--  Hibernate core 3.2.4.ga is buggy -->
				<exclusion>
					<groupId>org.hibernate</groupId>
					<artifactId>hibernate</artifactId>
				</exclusion>
			</exclusions>
		</dependency>
		<dependency>
			<groupId>org.hibernate</groupId>
			<artifactId>hibernate</artifactId>
			<version>3.2.4.sp1</version>
		</dependency>

Published by Fabian on 03 May 2008

Creating cleaner, RESTful actions using sfPopulatedRouting

When I was thinking about the MVC separation concerns some people have with symfony I came across something that I noticed in most of my actions that seem like a violation of MVC logic. In almost every action I do a database lookup. Not only is that more a part of the controller, rather than the view (I consider the view made up action and template), but also Java Frameworks can do dependency injection (which works declarative rather than programmatic).

So I was thinking of a User Edit action. It usually looks like

$this->user = UserPeer::retriveByPK(this->getRequestParameter('user'));
$this->forward404Unless($this->user);

I would assume that 2/3 of the actions in all symfony applications have similar lines at the beginning. And its not only extra effort to code these two lines every action, you also put code into that somehow fulfills a different purpose. The action should assume that the user to edit is already retrieved.

As a solution for those issues I propose the use of sfPopulatedRouting. It uses the exact configuration as the current sfPatternRouting (standard routing.yml file), but it treats the requirement differently.

Ideally this would be only a slim extension on top of sfPatternRouting, but I had quite a lot of issues extending the class. As I see the implementation anyway just as a proof of concept this is okay and can be fixed later on. Using that new routing your action will look like:

$this->user = this->getRequestParameter('user');

I came up with the idea to recycle the requirements parameters in routing as the meaning does nicely overlap :-) . Here an example:

edit_user:
  url:  /edit/:user
  param: { module: user, action: edit }
  requirements: { user: UserPeer::retrieveByPk }

As you see it will use propel pk getter to return the user from the Peer object. Even though the use of slugs is widespread, also many people use the PK in the url. for that you can use the better shortcut:

edit_user:
  url:  /edit/:user
  param: { module: user, action: edit }
  requirements: { user: User }

Ideally this would detect your ORM and perform the right query.

you can find the prototype sfPopulatedRouting.class.php and a diff file (against sfPatternRouting) here.
(requiring php 5.2.3 due to call_user_func() signature)

Let me know what you think of this, and if you have any good idea on for example auto publish the parameters to the action. Because

$this->user = this->getRequestParameter('user');

doesn’t look like injected. But making it

echo $this->user->getName();

requires modifying code of the action dispatcher. Something like the bad register_globals :-)