Thursday, July 29, 2010

How to do runtime property substitution for web.xml

  1. Place ${propertyName} in you web.xml file and specify the actual value via -DpropertyName=value (see a forum entry related to this...) also known as variable substitution.
  2. If you can afford to do this at compile time then:
    1. do so using a build tool such as maven (an example)
    2. Filter the web.xml file by configuring the maven-war-plugin as shown in the last post in this thread. There are some generic examples here too but they aren't as clear cut for the web.xml file.

Friday, July 23, 2010

Flex 4: Best Practices for working with Events & Event Listeners

In Flex 4, it is easy to separate a component into an actionscript and mxml file, one for the logic and another for layout and skinning.

The actionscript file usually contains common framework methods such as partAdded(), partRemoved(), getCurrentSkinState() etc. whereas the skin file had all the visual components laid out.

Best Practices:
  1. When adding event listeners, always put them in using the partAdded() method and NOT in the constructor.
    Because if your component is included in multiple states, then somewhere along the line while you may be switching back & forth between the states, the event listener which was added in the constructor will just disappear and it will seem like any events that you are dispatching for that listener aren't getting caught and disappearing into limbo.
    A guess here is that even though the listener may not have had a weak reference, taking the component on & off the stage between state changes might cause its listener to get garbage collected.
    With the use of partAdded() method to add the event listener, this risk disappears because even if the same component is being taken off the stage and being put back then the framework will make sure to call partAdded() again. Unlike the constructor which had already been used to create the object.

Friday, July 9, 2010

Flex Deep Linking and Server Side Redirects

With Flex its easy to:
a) use deep-linking (IBrowserManager & BrowserManager) to create application URLs that allow the use of the browser's backward & forward navigation buttons,
b) bookmarking a deep-linked URL and reloading it also works just fine

B U T ... what doesn't work is when you need to authenticate users before letting them access their bookmarked content. The reason behind this is simple ... the out-of-the-box javascript (history.js file) provided by the flex framework uses the # (pound/sharp) symbol to manage the deep link fragments. For ex:

1) http://www.hostname.com/application.swf#view=account
2) http://www.hostname.com/application.swf#view=profile
3) http://www.hostname.com/application.swf#edit=account
4) http://www.hostname.com/application.swf#edit=profile

Now according to the HTTP spec, the part after the # symbol is not sent over to the server in the HTTP request. This means that your server has no clue where to redirect the users after they successfully authenticate!

What can you do?

Workaround # 1:
1) Provide a bookmark button in the application itself and replace the # symbol with the ? symbol when storing the link.
2) Edit your client side to treat the ? symbol in the same way it treats the # symbol, therefore picking up the deep link fragments properly.

Workaround # 2:
1) Have your users manually edit their bookmarked links to replace the # symbol with the ? symbol.
2) Now that the deep link fragment is making it over to your server side as a URL parameter, edit your server side to replace the ? symbol with the # symbol when redirecting the user back to their bookmarked link. If you are using the spring-security framework then you can refer to the following blog as a reference on how to configure your application context's xml files properly.

Friday, July 2, 2010

Spring Security: Redirect back to target URL after successful authentication

Most, if not all, users will bookmark their favorite pages in any online application. One would be hard pressed to find folks that bookmark the login pages!

When accessing application URLs directly, if a login page is presented to the web users, they expect to end up at their original destination rather than some application specified home page.

As the Spring Security framework has progressed it has supported this use-case in an evolving manner.

Spring-Security 2.0.x
SavedRequest is used by AbstractProcessingFilter and SavedRequestAwareWrapper to reproduce the request after successful authentication. An instance of this class is stored at the time of an authentication exception by ExceptionTranslationFilter.
  1. If we look at the source code, it is easy to see that for an incoming unauthenticated user, the ExceptionTranslationFilter's sendStartAuthentication(...) method will preserve the original request (+/-)
         SavedRequest savedRequest = new SavedRequest(httpRequest, portResolver);
         httpRequest.getSession().setAttribute(AbstractProcessingFilter.SPRING_SECURITY_SAVED_REQUEST_KEY, savedRequest);

  2. And a successful authentication, AuthenticationProcessingFilter will leverage its parent AbstractProcessingFilter's determineTargetUrl(...) method to determine if it should load the saved target URL (+/-)
         String targetUrl = alwaysUseDefaultTargetUrl
    ? null : targetUrlResolver.determineTargetUrl(getSavedRequest(request), request, SecurityContextHolder.getContext().getAuthentication());

  3. So the only question remaining is how to set the alwaysUseDefaultTargetUrl property? This can be done:
    1. Simply via the http tag (+/-)

      <http ...>
          ...
          <form-login ...
            always-use-default-target='false' />
      </http>

    2. Or via the bean if your configuration happens to be more involved (+/-)
           <bean id="authenticationProcessingFilter" class="org.springframework.security.ui.webapp.AuthenticationProcessingFilter">
           <property name="alwaysUseDefaultTargetUrl" value="false" />
           </bean>

Spring-Security 3.0.x
Spring Security 3.0.x offers this out-of-the-box as well, have a look at this class: SavedRequestAwareAuthenticationSuccessHandler

Here's how it works:
  1. ExceptionTranslationFilter will save the original URL in a RequestCache before the user is sent/redirected to the appropriate location for authentication to happen.
  2. When the user has successful authenticated ... the Filter which extends AbstractAuthenticationProcessingFilter will be able to leverage this parent's already existing successfulAuthentication() method.
  3. The method will further call upon SavedRequestAwareAuthenticationSuccessHandler's onAuthenticationSuccess() to pull out the original URL from the cache where the user should now be redirected for a happy ending.
Here are the odd mistakes that one might make that will cause this well-oiled mechanism to breakdown:
  • You have a Filter that redirects the user somehow before ExceptionTranslationFilter ever gets the chance to store the original URL in the HttpSessionRequestCache.
  • Your Filter, neither extends AbstractAuthenticationProcessingFilter ... nor does it call a AuthenticationSuccessHandler like SavedRequestAwareAuthenticationSuccessHandler for doing this work explicitly.