<?xml version="1.0"?>
<rss version="2.0">
<channel>
  <title>The Kitchen in the Zoo - security tag</title>
  <link>http://blog.maxant.co.uk:80/pebble/tags/security/</link>
  <description>&lt;small&gt;A blog where Ant writes about anything he finds interesting! &lt;a href=&#039;http://www.linkedin.com/in/maxant&#039;&gt;&lt;font color=&#039;white&#039;&gt;Who is Ant?&lt;/font&gt;&lt;/a&gt;      &lt;a href=&#039;/pebble/pages/copyright.html&#039;&gt;&lt;font color=&#039;white&#039;&gt;Copyright 2005-2012 Ant Kutschera&lt;/font&gt;&lt;/a&gt;&lt;/small&gt;</description>
  <language>en</language>
  <copyright>Ant Kutschera</copyright>
  <lastBuildDate>Thu, 10 May 2012 20:07:00 GMT</lastBuildDate>
  <generator>Pebble (http://pebble.sourceforge.net)</generator>
  <docs>http://backend.userland.com/rss</docs>
  
  
  <item>
    <title>Java EE Security and Spring</title>
    <link>http://blog.maxant.co.uk:80/pebble/2009/06/02/1243967400000.html</link>
    
      
        <description>
          &lt;p&gt;&lt;a target=&#034;_blank&#034; href=&#034;http://static.springsource.org/spring-security/site/index.html&#034;&gt;Spring Security&lt;/a&gt; (originally ACEGI) does not seem to work out of the box with Java EE security (see &lt;a target=&#034;_blank&#034; href=&#034;http://forum.springsource.org/showthread.php?t=31388&#034;&gt;here&lt;/a&gt;). I guess the reason is clear, namely that the people from Spring don&#039;t want you to be tied into Java EE and that makes sense because Spring something that you can use without Java EE. But instead of having to learn something new and instead of having to configure my security in a non-standard way, I wanted a way to ensure my services are only called by someone with the right authorization, exactly when they are deployed in a Java EE environment. &lt;br /&gt;
&lt;br /&gt;
Since a standard web application running in a Java EE container can be configured to have security, I expected to be able to configure Spring to use the web request to check the Principal for its security roles before calling a service, but that isn&#039;t possible. So, I set to work to quickly create a little library to help me out. &lt;br /&gt;
&lt;br /&gt;
The first step was to implement a Filter in the web application so that it could intercept every call and insert the web request (containing the Principal) into a ThreadLocal variable. The idea was that the ThreadLocal variable could then be used further up the call stack to query the security roles of the authenticated user. The filter implementation looks like this: &lt;br /&gt;
&lt;br /&gt;
&lt;code&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public void doFilter(&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; ServletRequest request,&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ServletResponse response,&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; FilterChain chain) &lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; throws IOException, ServletException {&amp;nbsp;&lt;br /&gt;
&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //set the request in the security thread local&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; SecurityHelper.set((HttpServletRequest)request);&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;chain.doFilter(request, response);&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //all done, so remove references to unwanted objects&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; SecurityHelper.finished();&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;/code&gt;&lt;br /&gt;
&lt;br /&gt;
The filter is configured in the Java EE web application&#039;s web.xml like this: &lt;br /&gt;
&lt;code&gt;&lt;filter&gt;&lt;/filter&gt;&lt;filter-name&gt;&lt;/filter-name&gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;filter&amp;gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;filter-name&amp;gt;maxantSpringSecurity&amp;lt;/filter-name&amp;gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;filter-class&amp;gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; uk.co.maxant.spring.security.SecurityFilter&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/filter-class&amp;gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/filter&amp;gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;filter-mapping&amp;gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;filter-name&amp;gt;maxantSpringSecurity&amp;lt;/filter-name&amp;gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;url-pattern&amp;gt;/*&amp;lt;/url-pattern&amp;gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/filter-mapping&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;/code&gt;The filter calls the SecurityHelper which uses a ThreadLocal variable to store the web request as follows. The web request can be used to gain access to the Principal, as well as ask if the Principal has a given role. &lt;br /&gt;
&lt;code&gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; private static ThreadLocal&lt;httpservletrequest&gt;&lt;/httpservletrequest&gt; tls = new ThreadLocal&lt;httpservletrequest&gt;&lt;/httpservletrequest&gt;();&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public static void set(HttpServletRequest request){&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; tls.set(request);&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; public static boolean isInRole(String role){&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; HttpServletRequest req = tls.get();&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; if(req == null){&lt;br /&gt;
&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; return false;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }else{&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; return req.isUserInRole(role);&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;/code&gt;&lt;br /&gt;
&lt;br /&gt;
The Security Helper also contains an additional method which can be called to release the reference to the request. This is important because the web request contains a reference to the session and that might be large. We don&#039;t want to be holding on to such things for a long time as they may use memory unncessarily. This method can is called as soon as all security queries are finished, and is implemented as follows. For more information on thread locals and threads that are stored in pools, see &lt;a target=&#034;_blank&#034; href=&#034;http://blog.maxant.co.uk/pebble/2008/09/23/1222200780000.html&#034;&gt;here&lt;/a&gt;.&lt;code&gt;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; public static void finished(){&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; tls.remove();&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;/code&gt;&lt;br /&gt;
&lt;br /&gt;
The final step was to configure my Spring configuration to setup an aspect to intercept all service calls. The advice which this aspect gives is whether the current user has the role required to call the method. The required role comes from an annotation added to the service methods and the current user comes from the Principal stored in the ThreadLocal from step one, above. If the user has rights, the service method is called. If not, a simple SecurityException is thrown, providing details about the missing roles. In cases where the user is not logged in, the Security Exception is also thrown. In cases where a Service method has no annotation, then no security is checked. The aspect is configured in the Spring configuration like this: &lt;code&gt;&lt;bean id=&#034;security&#034; class=&#034;uk.co.maxant.spring.security.SecurityAspect&#034;&gt;&lt;/bean&gt;&lt;!-- execute before the transactional advice (hence the lower order number)
			but after say profiling --&gt;
&lt;property value=&#034;2&#034; name=&#034;order&#034;&gt;&lt;/property&gt;
&amp;nbsp;&lt;aop:config&gt;&lt;/aop:config&gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;!-- security aspect --&amp;gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;bean id=&amp;quot;security&amp;quot;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; class=&amp;quot;uk.co.maxant.spring.security.SecurityAspect&amp;quot;&amp;gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;!-- execute before the transactional advice (hence the lower order number)&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; but after profiling --&amp;gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;property name=&amp;quot;order&amp;quot; value=&amp;quot;2&amp;quot; /&amp;gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/bean&amp;gt;&lt;br /&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;aop:config&amp;gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;!-- this advice will execute around the transactional advice --&amp;gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;aop:aspect id=&amp;quot;securityAspect&amp;quot; ref=&amp;quot;security&amp;quot;&amp;gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;aop:pointcut id=&amp;quot;serviceMethod&amp;quot; &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; expression=&amp;quot;execution(* uk.co.maxant.gwtdemo16.server.*Service.*(..))&amp;quot; /&amp;gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;aop:around method=&amp;quot;checkSecurity&amp;quot;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; pointcut-ref=&amp;quot;serviceMethod&amp;quot; /&amp;gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/aop:aspect&amp;gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/aop:config&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The expression in the above pointcut needs to be configured to match your package and Service naming conventions.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;The aspect itself is implemented like this: &lt;br /&gt;
&lt;code&gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; public Object checkSecurity(ProceedingJoinPoint call)&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; throws Throwable {&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; String[] requiredRoles = null;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; MethodSignature ms =&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; (MethodSignature)call.getSignature();&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Method m = ms.getMethod(); //lets check it for the&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp; // RolesAllowed annotation&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; RolesAllowed roles = m.getAnnotation(RolesAllowed.class);&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; if(roles != null){&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; requiredRoles = roles.value();&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; for(String role : requiredRoles){&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; if(SecurityHelper.isInRole(role)){&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //ok, no problem, lets continue &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //with the call&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; requiredRoles = null; //since we can now&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; // carry out the call&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; break;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if(requiredRoles == null){&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Object returnValue = call.proceed();&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; return returnValue;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }else{&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; String rrs = &amp;quot;[&amp;quot;;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; for(String s : requiredRoles){&lt;br /&gt;
&lt;/code&gt;&lt;code&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/code&gt;&lt;code&gt;rrs += s + &amp;quot;, &amp;quot;;&lt;br /&gt;
&lt;/code&gt;&lt;code&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/code&gt;&lt;code&gt;}&lt;br /&gt;
&lt;/code&gt;&lt;code&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/code&gt;&lt;code&gt;rrs = rrs.substring(0, rrs.length() - 2) + &amp;quot;]&amp;quot;;&lt;br /&gt;
&lt;/code&gt;&lt;code&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;
&lt;/code&gt;&lt;code&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/code&gt;&lt;code&gt;throw new SecurityException(&amp;quot;To call [&amp;quot; +&lt;br /&gt;
&lt;/code&gt;&lt;code&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/code&gt;&lt;code&gt;call.getSignature().toLongString() +&lt;br /&gt;
&lt;/code&gt;&lt;code&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/code&gt;&lt;code&gt;&amp;quot;] the user must be authenticated and &amp;quot; +&lt;br /&gt;
&lt;/code&gt;&lt;code&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;quot;&lt;/code&gt;&lt;code&gt;authorized &lt;/code&gt;&lt;code&gt;in these roles: &amp;quot; + rrs);&lt;br /&gt;
&lt;/code&gt;&lt;code&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/code&gt;&lt;code&gt;}&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;
&amp;nbsp;&lt;/code&gt;&lt;br /&gt;
The annotation is defined as such: &lt;br /&gt;
&lt;code&gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; @Retention(value=RetentionPolicy.RUNTIME)&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; @Target(value={ElementType.METHOD})&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; public @interface RolesAllowed {&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; String[] value();&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;/code&gt;&lt;br /&gt;
&lt;br /&gt;
The annotation is used like this, on all service methods requiring security: &lt;br /&gt;
&lt;code&gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; @RolesAllowed (&amp;quot;registered&amp;quot;)&amp;nbsp;&lt;/code&gt;&lt;br /&gt;
&amp;nbsp;&lt;br /&gt;
What I now have is a simple library which I can configure using a Filter and an Aspect. Additionally to allow the user to log in in the first place, I can use a standard Java EE security constraint in my web application. The standard steps to use this security extension of Spring would be: &lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;Add a security constraint to the web application&lt;/li&gt;
    &lt;li&gt;Add the annotation to the service methods requiring security&lt;/li&gt;
    &lt;li&gt;Add the filter to the web application&lt;/li&gt;
    &lt;li&gt;Add the aspect to the Spring configuration&lt;/li&gt;
    &lt;li&gt;Add the library to the classpath&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I understand that Spring does not want you to need a dependency on Java EE, but on the other hand if I have that dependency due to other requirements, I do not want to have to configure my application using a third party security concept (Spring) as opposed to a standard one (Java EE). Spring Security is not even part of Standard Spring - it is downloaded seperately. The more extensions you use, the more skills your developers need. The maxant Spring Security extension provides a very simple way to secure your service methods. &lt;br /&gt;
&lt;br /&gt;
Download the library including source code &lt;a href=&#034;http://www.maxant.co.uk/tools.jsp#maxantSpringSecurity&#034;&gt;here&lt;/a&gt;. &lt;br /&gt;
&lt;br /&gt;
Copyright (c) 2009 Ant Kutschera&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div class=&#034;tags&#034;&gt;&lt;span&gt;Social Bookmarks : &lt;/span&gt;&amp;nbsp;&lt;a href=&#034;http://slashdot.org/bookmark.pl?url=http://blog.maxant.co.uk:80/pebble/2009/06/02/1243967400000.html&amp;amp;title=Java+EE+Security+and+Spring&#034; target=&#034;_blank&#034; title=&#034;Add this post to Slash Dot&#034;&gt;&lt;img src=&#034;common/images/slashdot.png&#034; alt=&#034;Add this post to Slashdot&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://digg.com/submit?url=http://blog.maxant.co.uk:80/pebble/2009/06/02/1243967400000.html&amp;amp;title=Java+EE+Security+and+Spring&#034; target=&#034;_blank&#034; title=&#034;Digg this post&#034;&gt;&lt;img src=&#034;common/images/digg.png&#034; alt=&#034;Add this post to Digg&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://reddit.com/submit?url=http://blog.maxant.co.uk:80/pebble/2009/06/02/1243967400000.html&amp;amp;title=Java+EE+Security+and+Spring&#034; target=&#034;_blank&#034; title=&#034;Add this post to Reddit&#034;&gt;&lt;img src=&#034;common/images/reddit.png&#034; alt=&#034;Add this post to Reddit&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://del.icio.us/post?url=http://blog.maxant.co.uk:80/pebble/2009/06/02/1243967400000.html&amp;amp;title=Java+EE+Security+and+Spring&#034; target=&#034;_blank&#034; title=&#034;Save this post to Del.icio.us&#034;&gt;&lt;img src=&#034;common/images/delicious.png&#034; alt=&#034;Add this post to Delicious&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://www.stumbleupon.com/submit?url=http://blog.maxant.co.uk:80/pebble/2009/06/02/1243967400000.html&amp;amp;title=Java+EE+Security+and+Spring&#034; target=&#034;_blank&#034; title=&#034;Stumble this post&#034;&gt;&lt;img src=&#034;common/images/stumbleupon.png&#034; alt=&#034;Add this post to Stumble it&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://www.google.com/bookmarks/mark?op=edit&amp;amp;bkmk=http://blog.maxant.co.uk:80/pebble/2009/06/02/1243967400000.html&amp;amp;title=Java+EE+Security+and+Spring&#034; target=&#034;_blank&#034; title=&#034;Add this post to Google&#034;&gt;&lt;img src=&#034;common/images/google.png&#034; alt=&#034;Add this post to Google&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://technorati.com/faves?add=http://blog.maxant.co.uk:80/pebble/2009/06/02/1243967400000.html&#034; target=&#034;_blank&#034; title=&#034;Add this post to Technorati&#034;&gt;&lt;img src=&#034;common/images/technorati.png&#034; alt=&#034;Add this post to Technorati&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://www.bloglines.com/sub/http://blog.maxant.co.uk:80/pebble/2009/06/02/1243967400000.html&#034; target=&#034;_blank&#034; title=&#034;Add this post to Bloglines&#034;&gt;&lt;img src=&#034;common/images/bloglines.png&#034; alt=&#034;Add this post to Bloglines&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://www.facebook.com/share.php?u=http://blog.maxant.co.uk:80/pebble/2009/06/02/1243967400000.html&#034; target=&#034;_blank&#034; title=&#034;Add this post to Facebook&#034;&gt;&lt;img src=&#034;common/images/facebook.png&#034; alt=&#034;Add this post to Facebook&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://www.furl.net/storeIt.jsp?u=http://blog.maxant.co.uk:80/pebble/2009/06/02/1243967400000.html&amp;amp;t=Java+EE+Security+and+Spring&#034; target=&#034;_blank&#034; title=&#034;Add this post to Furl&#034;&gt;&lt;img src=&#034;common/images/furl.png&#034; alt=&#034;Add this post to Furl&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;https://favorites.live.com/quickadd.aspx?mkt=en-us&amp;amp;url=http://blog.maxant.co.uk:80/pebble/2009/06/02/1243967400000.html&amp;amp;title=Java+EE+Security+and+Spring&#034; target=&#034;_blank&#034; title=&#034;Add this post to Windows Live&#034;&gt;&lt;img src=&#034;common/images/windowslive.png&#034; alt=&#034;Add this post to Windows Live&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://bookmarks.yahoo.com/toolbar/savebm?opener=tb&amp;amp;u=http://blog.maxant.co.uk:80/pebble/2009/06/02/1243967400000.html&amp;amp;t=Java+EE+Security+and+Spring&#034; target=&#034;_blank&#034; title=&#034;Add this post to Yahoo!&#034;&gt;&lt;img src=&#034;common/images/yahoo.png&#034; alt=&#034;Add this post to Yahoo!&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&lt;/div&gt;
        </description>
      
      
    
    
    
    <comments>http://blog.maxant.co.uk:80/pebble/2009/06/02/1243967400000.html#comments</comments>
    <guid isPermaLink="true">http://blog.maxant.co.uk:80/pebble/2009/06/02/1243967400000.html</guid>
    <pubDate>Tue, 02 Jun 2009 18:30:00 GMT</pubDate>
  </item>
  
  <item>
    <title>Cross Site Scripting (XSS) and Denial of Service (DoS) using AJAX and other Technologies</title>
    <link>http://blog.maxant.co.uk:80/pebble/2008/10/16/1224192960000.html</link>
    
      
        <description>
          &lt;p&gt;The other day I was wondering how Google Analytics works... You put a few lines of Javascript into your page and it loads another script to send data back to one of its servers. I assumed they used an AJAX XMLHttpRequest to send stats to their server. However, an XMLHttpRequest created in Javascript (or any script language for that matter) can only make calls back to the server where the browser made the original request, not where it loaded the script. So if for example a site abc.com has a page which loads a script from def.com, the script can create an XMLHttpRequest object but it can ONLY make calls to abc.com.&lt;br /&gt;
&lt;br /&gt;
Hmmm... that&#039;s not entirely true. With IE 6.0.2900 and probably earlier versions of Firefox / other browsers it was possible to make the XMLHttpRequest object call any server, which would be great for a Denial of Service (DoS) attack. Imagine you have a site with millions of page views a day? And your&#039;e feeling unfriendly and want to create a DoS attack against your foe. Easy, you put some script in a page which is frequently viewed, and unknowingly, every one of your readers viewing that page makes a call to your foe&#039;s website, stretching its abilities to relpy to all requests, resulting in the DoS attack, which might even take down the server... Or even worse, an unfriendly user of yours posts some content to a forum containing a script to perform that DoS on their own enemy!&lt;br /&gt;
&lt;br /&gt;
Luckily, that security issue was fixed in IE 7 and Firefox 2 (at least the versions I tested on which included service packs). But there is another reason why it is dangerous for an AJAX client to be able to call any server: Scripts have access to cookies and the URL, which means they have access to session IDs. If scripts can send data anywhere, they can easily hijack the session ID and pass it back to a malicious server. As a reminder, a session ID works like this: a user makes a request to view a page on a server. The server checks for a session ID in a cookie or the URL. If its not present, creates a unique ID and sends it back to the user, and probably sends them the login page instead of the original page they wanted to view. Once the user sends their login credentials and the session ID back again, the server checks their credentials and remembers that the user is authenticated and only relies on the session ID being around in every call which the user makes. So anyway, a script can send the cookies and URL to a malicious server which in turn can make its own request to the original server, pretending to be that user. Such an attack is known as a cross site scripting (XSS) attack. Theoretically, the malicious server could change the password, transfer funds to its own account, make forum postings on the users behalf, etc. Whether the connection between the user and the original server is secured over SSL is irrelevant because the script is running inside the users browser.&lt;br /&gt;
&lt;br /&gt;
But how does a malicious script get put on a site in the first place? Its not like the author of a site would go to those lengths, since his server has the session ID anyway, and the user is one of his customers! Well luckily, this is the hard part, and as a systems designer, you can still protect yourself against such attacks. Lets say someone has the intent to create such an attack. They need to somehow get the script into a page which other people can view. To do that, they would look for a forum or page where they can make a posting. So most corporations like banks or online shops are already protected because they don&#039;t allow such posting, although it has become trendy for customers to be able to post reviews, like on Amazon.com.&lt;br /&gt;
&lt;br /&gt;
Hold on though, two paragraphs ago I said an AJAX client could NOT make calls like this, to send session info to a malicious server. But somehow, Google Analytics sends that kind of data back to its servers, and thats where it got interesting - how do they do it? I had a go at reading the Javascript which Google uses, but its been obfuscated and instead of using meaningful names for their functions, they all have simple letters for their names. I did get as far as noticing that they seem to be loading some Flash, so I assumed that Flash has a model like Java Applets in which they can send data back to the server from which they are loaded. So I wrote a tiny applet and posted it to my own site. The applet does nothing more than send a string back to the server where the applet was loaded from. Note that applets are restricted to only talking to the server from which they originated, so they cannot be used for DoS attacks. The next step was to write some Javascript which loads that applet, passing it a string parameter, which contains the URL from the browser as well as all the cookies. I then posted that script to a forum (my own I hasten to add - I&#039;m not in the business of hacking peoples accounts!). To post the script, I logged in as myself and created a thread with an enticing name and some provocative text (I want lots of people to read it so I can steal their sessions!). As well as the provocative text, I included the Javascript to load the applet and pass it the cookies and URL. Since browsers don&#039;t show script to the user, they don&#039;t know whats happening.&lt;br /&gt;
&lt;br /&gt;
I then logged in as a different user on a different browser and read the bogus posting. Indeed, the applet posted the session info back to my server. A few milliseconds after &amp;quot;the user&amp;quot; had read the provocative thread, I had their session ID. Whats more, I&#039;d already programmed the malicious server to make a posting on behalf of the different user, telling the world that the site had been hacked :-)&lt;br /&gt;
&lt;br /&gt;
I nice little experiment I thought, but let me repeat, this was all done on my own servers, in fact locally on my laptop - no ones accounts are in danger! The point is, that its VERY easy to steal session IDs, if there is a way to make a posting that contains script. So by default, my bank is NOT open to such an attack, which makes me happier about using their online services. Even if it were, they have gone to the extent of requiring me to retype parts of my password if I want to transfer funds to a different account, although as I&#039;m writing this I don&#039;t think that&#039;t the case when I pay bills...&lt;br /&gt;
&lt;br /&gt;
By far the best protection against such XSS attacks is to strip out any script and simply not allow it to be posted. Lots of big sites do that (e.g. Mediawiki doesn&#039;t even let you post HTML, they have their own format). I have read that Google even has their own parsers for stripping malicious code out of postings, which shows how important they think it is to protect the world against such attacks.&lt;br /&gt;
&lt;br /&gt;
Other forms of protection I have seen as to put all postings inside an &amp;quot;IFrame&amp;quot; - a special HTML tag which loads content from a site inside a frame protecting the rest of the page from that content. In my tests, code running inside an IFrame still had access to some of the cookies from the main outer page, so if a session ID is contained in cookies, its still not safe. It was interesting to note that Firefox 2 provided some of the cookies while IE 6 didn&#039;t provide any.&lt;br /&gt;
&lt;br /&gt;
The final way to protect your sites users is to get them to provide parts of their password again, when they are doing anything important, like making payments or postings. That way, a malicious script has no chance of spoofing their actions.&lt;br /&gt;
&lt;br /&gt;
Copyright (c) 2008 Ant Kutschera&lt;/p&gt;&lt;div class=&#034;tags&#034;&gt;&lt;span&gt;Social Bookmarks : &lt;/span&gt;&amp;nbsp;&lt;a href=&#034;http://slashdot.org/bookmark.pl?url=http://blog.maxant.co.uk:80/pebble/2008/10/16/1224192960000.html&amp;amp;title=Cross+Site+Scripting+%28XSS%29+and+Denial+of+Service+%28DoS%29+using+AJAX+and+other+Technologies&#034; target=&#034;_blank&#034; title=&#034;Add this post to Slash Dot&#034;&gt;&lt;img src=&#034;common/images/slashdot.png&#034; alt=&#034;Add this post to Slashdot&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://digg.com/submit?url=http://blog.maxant.co.uk:80/pebble/2008/10/16/1224192960000.html&amp;amp;title=Cross+Site+Scripting+%28XSS%29+and+Denial+of+Service+%28DoS%29+using+AJAX+and+other+Technologies&#034; target=&#034;_blank&#034; title=&#034;Digg this post&#034;&gt;&lt;img src=&#034;common/images/digg.png&#034; alt=&#034;Add this post to Digg&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://reddit.com/submit?url=http://blog.maxant.co.uk:80/pebble/2008/10/16/1224192960000.html&amp;amp;title=Cross+Site+Scripting+%28XSS%29+and+Denial+of+Service+%28DoS%29+using+AJAX+and+other+Technologies&#034; target=&#034;_blank&#034; title=&#034;Add this post to Reddit&#034;&gt;&lt;img src=&#034;common/images/reddit.png&#034; alt=&#034;Add this post to Reddit&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://del.icio.us/post?url=http://blog.maxant.co.uk:80/pebble/2008/10/16/1224192960000.html&amp;amp;title=Cross+Site+Scripting+%28XSS%29+and+Denial+of+Service+%28DoS%29+using+AJAX+and+other+Technologies&#034; target=&#034;_blank&#034; title=&#034;Save this post to Del.icio.us&#034;&gt;&lt;img src=&#034;common/images/delicious.png&#034; alt=&#034;Add this post to Delicious&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://www.stumbleupon.com/submit?url=http://blog.maxant.co.uk:80/pebble/2008/10/16/1224192960000.html&amp;amp;title=Cross+Site+Scripting+%28XSS%29+and+Denial+of+Service+%28DoS%29+using+AJAX+and+other+Technologies&#034; target=&#034;_blank&#034; title=&#034;Stumble this post&#034;&gt;&lt;img src=&#034;common/images/stumbleupon.png&#034; alt=&#034;Add this post to Stumble it&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://www.google.com/bookmarks/mark?op=edit&amp;amp;bkmk=http://blog.maxant.co.uk:80/pebble/2008/10/16/1224192960000.html&amp;amp;title=Cross+Site+Scripting+%28XSS%29+and+Denial+of+Service+%28DoS%29+using+AJAX+and+other+Technologies&#034; target=&#034;_blank&#034; title=&#034;Add this post to Google&#034;&gt;&lt;img src=&#034;common/images/google.png&#034; alt=&#034;Add this post to Google&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://technorati.com/faves?add=http://blog.maxant.co.uk:80/pebble/2008/10/16/1224192960000.html&#034; target=&#034;_blank&#034; title=&#034;Add this post to Technorati&#034;&gt;&lt;img src=&#034;common/images/technorati.png&#034; alt=&#034;Add this post to Technorati&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://www.bloglines.com/sub/http://blog.maxant.co.uk:80/pebble/2008/10/16/1224192960000.html&#034; target=&#034;_blank&#034; title=&#034;Add this post to Bloglines&#034;&gt;&lt;img src=&#034;common/images/bloglines.png&#034; alt=&#034;Add this post to Bloglines&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://www.facebook.com/share.php?u=http://blog.maxant.co.uk:80/pebble/2008/10/16/1224192960000.html&#034; target=&#034;_blank&#034; title=&#034;Add this post to Facebook&#034;&gt;&lt;img src=&#034;common/images/facebook.png&#034; alt=&#034;Add this post to Facebook&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://www.furl.net/storeIt.jsp?u=http://blog.maxant.co.uk:80/pebble/2008/10/16/1224192960000.html&amp;amp;t=Cross+Site+Scripting+%28XSS%29+and+Denial+of+Service+%28DoS%29+using+AJAX+and+other+Technologies&#034; target=&#034;_blank&#034; title=&#034;Add this post to Furl&#034;&gt;&lt;img src=&#034;common/images/furl.png&#034; alt=&#034;Add this post to Furl&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;https://favorites.live.com/quickadd.aspx?mkt=en-us&amp;amp;url=http://blog.maxant.co.uk:80/pebble/2008/10/16/1224192960000.html&amp;amp;title=Cross+Site+Scripting+%28XSS%29+and+Denial+of+Service+%28DoS%29+using+AJAX+and+other+Technologies&#034; target=&#034;_blank&#034; title=&#034;Add this post to Windows Live&#034;&gt;&lt;img src=&#034;common/images/windowslive.png&#034; alt=&#034;Add this post to Windows Live&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://bookmarks.yahoo.com/toolbar/savebm?opener=tb&amp;amp;u=http://blog.maxant.co.uk:80/pebble/2008/10/16/1224192960000.html&amp;amp;t=Cross+Site+Scripting+%28XSS%29+and+Denial+of+Service+%28DoS%29+using+AJAX+and+other+Technologies&#034; target=&#034;_blank&#034; title=&#034;Add this post to Yahoo!&#034;&gt;&lt;img src=&#034;common/images/yahoo.png&#034; alt=&#034;Add this post to Yahoo!&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&lt;/div&gt;
        </description>
      
      
    
    
    
    <comments>http://blog.maxant.co.uk:80/pebble/2008/10/16/1224192960000.html#comments</comments>
    <guid isPermaLink="true">http://blog.maxant.co.uk:80/pebble/2008/10/16/1224192960000.html</guid>
    <pubDate>Thu, 16 Oct 2008 21:36:00 GMT</pubDate>
  </item>
  
  </channel>
</rss>

