<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	>

<channel>
	<title>Cake Solutions Team Blog</title>
	<atom:link href="http://www.cakesolutions.net/teamblogs/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.cakesolutions.net/teamblogs</link>
	<description>void magic() { }</description>
	<pubDate>Wed, 18 Jun 2008 16:23:48 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.5.1</generator>
	<language>en</language>
			<item>
		<title>Spring London User Group</title>
		<link>http://www.cakesolutions.net/teamblogs/2008/06/18/spring-london-user-group/</link>
		<comments>http://www.cakesolutions.net/teamblogs/2008/06/18/spring-london-user-group/#comments</comments>
		<pubDate>Wed, 18 Jun 2008 16:22:11 +0000</pubDate>
		<dc:creator>Jan Machacek</dc:creator>
		
		<category><![CDATA[Jan's Blog]]></category>

		<category><![CDATA[London]]></category>

		<category><![CDATA[SLUG]]></category>

		<category><![CDATA[Spring]]></category>

		<guid isPermaLink="false">http://www.cakesolutions.net/teamblogs/?p=54</guid>
		<description><![CDATA[As you all know, Aleksa and I presented a case study at the first Spring London User Group meeting (I think we should call it SLUG); we now give you video of our presentation.
Jan and Aleksa presenting
]]></description>
			<content:encoded><![CDATA[<p>As you all know, Aleksa and I presented a case study at the first Spring London User Group meeting (I think we should call it <i>SLUG</i>); we now give you video of our presentation.<br />
<a href='http://video.google.com/googleplayer.swf?docid=-5567199984952929585&#038;hl=en' >Jan and Aleksa presenting</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.cakesolutions.net/teamblogs/2008/06/18/spring-london-user-group/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Declarative caching and Hibernate</title>
		<link>http://www.cakesolutions.net/teamblogs/2008/06/18/declarative-caching-and-hibernate/</link>
		<comments>http://www.cakesolutions.net/teamblogs/2008/06/18/declarative-caching-and-hibernate/#comments</comments>
		<pubDate>Wed, 18 Jun 2008 16:08:41 +0000</pubDate>
		<dc:creator>Jan Machacek</dc:creator>
		
		<category><![CDATA[Jan's Blog]]></category>

		<category><![CDATA[Caching]]></category>

		<category><![CDATA[Hibernate]]></category>

		<category><![CDATA[Spring AOP]]></category>

		<guid isPermaLink="false">http://www.cakesolutions.net/teamblogs/?p=53</guid>
		<description><![CDATA[We successfully use the Caching SpringModule. In short, this allows us to declaratively cache values returned from method calls. The Caching module supports many different cache implementations; we have picked OsCache for development. To get started, let&#8217;s take a look at the MemberService and its implementation.


public interface MemberService {
       [...]]]></description>
			<content:encoded><![CDATA[<p>We successfully use the Caching SpringModule. In short, this allows us to declaratively cache values returned from method calls. The Caching module supports many different cache implementations; we have picked OsCache for development. To get started, let&#8217;s take a look at the <code>MemberService</code> and its implementation.<br />
<code>
<pre>
public interface MemberService {
        @Nullable
	Member complicatedLookup(@NotNull ComplexArgument argument);
}

public class DefaultMemberService implements MemberService {
        @Nullable
        @Cacheable(modelId = "Member")
        public Member complicatedLookup(@NotNull ComplexArgument argument) {
                // some complex stuff
        }
}
</pre>
<p></code><br />
This code works perfectly well: when you call the <code>DefaultMemberService.complicatedLookup(...)</code> method more than once with the same (read <code>equal(Object)</code>) <code>ComplexArgument</code> object, the caching framework intercepts the call in and only the first call will go to do the <code>// some complex stuff</code>.<br />
The problem is when you return an object from a Hibernate DAO call and that object is enhanced by CGLIB. Now the cache has a reference to an object that references an invalid <code>Session</code>.<br />
We found this when our integration tests worked fine on their own, but started failing when we ran them as part of our automatic build. The prospect of going through every possible code path to find out if there is a cached CGLIB-enhanced object was daunting. Luckily, Spring AOP was quick to rescue. We wrote a simple little aspect that checks that any method with the <code>@Cacheable</code> annotation does not return a CGLIB-enahanced object.<br />
<code>
<pre>
@Aspect
public class CacheManagerAspect {

    @AfterReturning(pointcut =
            "@annotation(org.springmodules.cache.annotations.Cacheable)",
                returning = "ret",
                argNames = "jp, ret")
    public void indicateLazilyLoaded(JoinPoint jp, Object ret) throws Exception {
        checkNotCGLIBEnhanced(jp, ret);
    }

    private void checkNotCGLIBEnhanced(JoinPoint jp, Object o)
        throws IllegalAccessException, InvocationTargetException {
        if (o == null) return;
        String name = o.getClass().getName();
        if (!name.startsWith("uk.co.package")) return;
        if (name.contains("$$Enhancer"))
                 throw new RuntimeException(
                        "You cannot cache a CGLIB-Enhanced object at " + jp);

        PropertyDescriptor[] descriptors =
                 BeanUtils.getPropertyDescriptors(o.getClass());
        for (PropertyDescriptor descriptor : descriptors) {
            Object value = descriptor.getReadMethod().invoke(o);
            checkNotCGLIBEnhanced(jp, value);
        }
    }

}
</pre>
<p></code><br />
Simple, but powerful stuff from SpringModules and Spring AOP!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cakesolutions.net/teamblogs/2008/06/18/declarative-caching-and-hibernate/feed/</wfw:commentRss>
		</item>
		<item>
		<title>A Week of Web Releases</title>
		<link>http://www.cakesolutions.net/teamblogs/2008/06/05/a-week-of-web-releases/</link>
		<comments>http://www.cakesolutions.net/teamblogs/2008/06/05/a-week-of-web-releases/#comments</comments>
		<pubDate>Thu, 05 Jun 2008 09:29:16 +0000</pubDate>
		<dc:creator>Andrew Chalkley</dc:creator>
		
		<category><![CDATA[Andrew C's Blog]]></category>

		<guid isPermaLink="false">http://www.cakesolutions.net/teamblogs/?p=52</guid>
		<description><![CDATA[It&#8217;s been an exciting week on the web front with jQuery 1.2.6 and Ruby on Rails 2.1 being released, both providing feature enhancements and performance improvements.
Here is a brief run down:
jQuery

Event Handling is 103% Faster
CSS Selectors are 13% faster
.offset() is 21% faster
.css() is 25% faster
Exposed Speeds
.toggle() can now accept more functions
You can now unbind bound [...]]]></description>
			<content:encoded><![CDATA[<p>It&#8217;s been an exciting week on the web front with jQuery 1.2.6 and Ruby on Rails 2.1 being released, both providing feature enhancements and performance improvements.</p>
<p>Here is a brief run down:</p>
<p><a href="http://jquery.com/blog/2008/06/04/jquery-126-events-100-faster/">jQuery</a></p>
<ul>
<li>Event Handling is 103% Faster</li>
<li>CSS Selectors are 13% faster</li>
<li>.offset() is 21% faster</li>
<li>.css() is 25% faster</li>
<li>Exposed Speeds</li>
<li>.toggle() can now accept more functions</li>
<li>You can now unbind bound .toggle() and .one() functions</li>
<li>.index() supports jQuery collections</li>
<li>jQuery.makeArray can convert ANYTHING to an array.</li>
<li>beforeSend can cancel Ajax calls</li>
<li>Exposed Speeds</li>
</ul>
<p><a href="http://weblog.rubyonrails.org/2008/6/1/rails-2-1-time-zones-dirty-caching-gem-dependencies-caching-etc">Ruby on Rails</a><br />
Major New Features:</p>
<ul>
<li>Time zones</li>
<li>Dirty tracking</li>
<li>Gem Dependencies</li>
<li>Named scope</li>
<li>UTC-based migrations</li>
<li>Better caching</li>
</ul>
<p>Ryan Bates has produced some awesome screencasts on the above new features in rails. I highly recommend you check his <a href="http://www.railscasts.com">Railscasts</a> out.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cakesolutions.net/teamblogs/2008/06/05/a-week-of-web-releases/feed/</wfw:commentRss>
		</item>
		<item>
		<title>SpringOne - Jan presenting</title>
		<link>http://www.cakesolutions.net/teamblogs/2008/06/02/springone-jan-presenting/</link>
		<comments>http://www.cakesolutions.net/teamblogs/2008/06/02/springone-jan-presenting/#comments</comments>
		<pubDate>Mon, 02 Jun 2008 14:16:41 +0000</pubDate>
		<dc:creator>Guy Remond</dc:creator>
		
		<category><![CDATA[Guy's Blog]]></category>

		<category><![CDATA[Conference]]></category>

		<category><![CDATA[Jan]]></category>

		<category><![CDATA[Presentation]]></category>

		<category><![CDATA[SpringOne]]></category>

		<guid isPermaLink="false">http://www.cakesolutions.net/teamblogs/?p=51</guid>
		<description><![CDATA[Following on from the very successful presentation given by Jan and Aleksa at the inaugural Spring User Group (SUG) meeting on Friday, Jan will be presenting a slightly extended version of the same presentation at SpringOne.
SpringOne is being held at MetroPolis Business Center, MetroPolis Antwerp, Groenendaallaan 394 2030, Antwerp, Belgium. More information can be found [...]]]></description>
			<content:encoded><![CDATA[<p>Following on from the very successful presentation given by Jan and Aleksa at the inaugural Spring User Group (SUG) meeting on Friday, Jan will be presenting a slightly extended version of the same presentation at SpringOne.</p>
<p>SpringOne is being held at MetroPolis Business Center, MetroPolis Antwerp, Groenendaallaan 394 2030, Antwerp, Belgium. More information can be found <a href="http://www.springone.com">here</a>.</p>
<p>Jan will be presenting on Thursday 12th June at 14.00 - 15.00 and both he and I will  be at the Conference for most of the two days. If you are attending the conference please let me know and we can arrange to meet up over a coffee/beer.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cakesolutions.net/teamblogs/2008/06/02/springone-jan-presenting/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Area51</title>
		<link>http://www.cakesolutions.net/teamblogs/2008/06/02/area51/</link>
		<comments>http://www.cakesolutions.net/teamblogs/2008/06/02/area51/#comments</comments>
		<pubDate>Mon, 02 Jun 2008 08:35:42 +0000</pubDate>
		<dc:creator>Jan Machacek</dc:creator>
		
		<category><![CDATA[Jan's Blog]]></category>

		<category><![CDATA[Spring User Group]]></category>

		<category><![CDATA[SpringModules]]></category>

		<category><![CDATA[Workflow]]></category>

		<guid isPermaLink="false">http://www.cakesolutions.net/teamblogs/?p=50</guid>
		<description><![CDATA[We&#8217;ve now ordered a new sub-domain area51.devcake.co.uk. As you can guess from its name, we will publish all experimental code there. In fact, this will give you a read-only access to a subset of our subversion repository. You will be able to download any code that we are thinking about donating to the community, but [...]]]></description>
			<content:encoded><![CDATA[<p>We&#8217;ve now ordered a new sub-domain <code>area51.devcake.co.uk</code>. As you can guess from its name, we will publish all experimental code there. In fact, this will give you a read-only access to a subset of our subversion repository. You will be able to download any code that we are thinking about donating to the community, but is not yet up to scratch. The code will work, but it may not be completely documented and it may not have complete unit and integration test coverage.<br />
The first project to appear in area 51 will be the Workflow SpringModule, which we first introduced on Friday at the Spring User Group meeting in London.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cakesolutions.net/teamblogs/2008/06/02/area51/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Workflow SpringModule</title>
		<link>http://www.cakesolutions.net/teamblogs/2008/05/31/workflow-springmodule/</link>
		<comments>http://www.cakesolutions.net/teamblogs/2008/05/31/workflow-springmodule/#comments</comments>
		<pubDate>Sat, 31 May 2008 11:17:47 +0000</pubDate>
		<dc:creator>Jan Machacek</dc:creator>
		
		<category><![CDATA[Jan's Blog]]></category>

		<guid isPermaLink="false">http://www.cakesolutions.net/teamblogs/?p=49</guid>
		<description><![CDATA[I have introduced the Workflow SpringModule at Friday&#8217;s Spring User Group meeting in London; I was very pleased to see that people are interested in the module. Unfortunately, it is not available in the main SpringModules project yet, but I will make it available from our subversion repository tomorrow or on Monday.
I look forward to [...]]]></description>
			<content:encoded><![CDATA[<p>I have introduced the Workflow SpringModule at Friday&#8217;s Spring User Group meeting in London; I was very pleased to see that people are interested in the module. Unfortunately, it is not available in the main SpringModules project yet, but I will make it available from our subversion repository tomorrow or on Monday.<br />
I look forward to hearing any comments from the early adopters; depending on the feedback, I will include a more detailed discussion of the workflow module in my Spring One talk on Thursday 12th June.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cakesolutions.net/teamblogs/2008/05/31/workflow-springmodule/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Spring User Group - Jan &#038; Aleksa presenting</title>
		<link>http://www.cakesolutions.net/teamblogs/2008/05/28/spring-user-group-jan-aleksa-presenting/</link>
		<comments>http://www.cakesolutions.net/teamblogs/2008/05/28/spring-user-group-jan-aleksa-presenting/#comments</comments>
		<pubDate>Wed, 28 May 2008 17:36:01 +0000</pubDate>
		<dc:creator>Guy Remond</dc:creator>
		
		<category><![CDATA[Guy's Blog]]></category>

		<guid isPermaLink="false">http://www.cakesolutions.net/teamblogs/2008/05/28/spring-user-group-jan-aleksa-presenting/</guid>
		<description><![CDATA[As you may already know the Spring User Group UK is having its first meeting on the afternoon of 30th May at the the Crypt, in St. James Church, next to Skills Matter.
The organisers have put together a very interesting event, with speakers from SpringSource, Cake and UBS. Followed by interactive breakout sessions to chat [...]]]></description>
			<content:encoded><![CDATA[<p>As you may already know the Spring User Group UK is having its first meeting on the afternoon of 30th May at the the Crypt, in St. James Church, next to Skills Matter.</p>
<p>The organisers have put together a very interesting event, with speakers from SpringSource, Cake and UBS. Followed by interactive breakout sessions to chat with the speakers and other User Group members, this is a fantastic opportunity to learn, share your experience, broaden your network and join this community. Come join us and find out about the exciting new developments of the Spring framework and how practitioners are enabling their businesses, by using Spring as a core construct of their solutions.</p>
<p>Event Details What: London Spring User Group : First London Spring User Group Event<br />
Where: The Crypt, St. James Church, Clerkenwell, EC1R<br />
When: This Friday - 30 May 2008 Starts at 12:00</p>
<p>    * Dave Syer of Spring Source will be telling us about Spring Batch<br />
    * Rob Purcell &#038; Manoj Bajaj of UBS will give a talk on reliable database/messaging transactions without 2PC<br />
    * Jan Machacek of Cake will present a case study of a project at Central Government, where Spring was used successfully.</p>
<p>SpringSource, Skills Matter and Cake Solutions! are all sponsors of the event.</p>
<p>Please register <a href="http://skillsmatter.com/event/java-jee/first-london-spring-user-group-event">here</a></p>
<p>I hope to see you there.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cakesolutions.net/teamblogs/2008/05/28/spring-user-group-jan-aleksa-presenting/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Brand New Site Around the Corner</title>
		<link>http://www.cakesolutions.net/teamblogs/2008/05/08/brand-new-site-around-the-corner/</link>
		<comments>http://www.cakesolutions.net/teamblogs/2008/05/08/brand-new-site-around-the-corner/#comments</comments>
		<pubDate>Thu, 08 May 2008 14:13:36 +0000</pubDate>
		<dc:creator>Andrew Chalkley</dc:creator>
		
		<category><![CDATA[Andrew C's Blog]]></category>

		<category><![CDATA[jQuery]]></category>

		<category><![CDATA[website]]></category>

		<guid isPermaLink="false">http://www.cakesolutions.net/teamblogs/2008/05/08/brand-new-site-around-the-corner/</guid>
		<description><![CDATA[When I&#8217;ve had a spare hour or two between projects I have been working on the brand-spanking new cake site. 
It will have some smooth UI tweaks thanks to jQuery and pretty interesting features on the contact page with integrated Google Maps. 
The site is almost ready. Just a few odds and ends to tie [...]]]></description>
			<content:encoded><![CDATA[<p>When I&#8217;ve had a spare hour or two between projects I have been working on the brand-spanking new cake site. </p>
<p>It will have some smooth UI tweaks thanks to <a href="http://www.jquery.com">jQuery</a> and pretty interesting features on the contact page with integrated <a href="http://code.google.com/apis/maps/">Google Maps</a>. </p>
<p>The site is almost ready. Just a few odds and ends to tie up.</p>
<p>Once the site is launched I&#8217;ll blog a quick feature tour with some insights into the technologies used.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cakesolutions.net/teamblogs/2008/05/08/brand-new-site-around-the-corner/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Acegi Concurrent Login</title>
		<link>http://www.cakesolutions.net/teamblogs/2008/05/08/acegi-concurrent-login/</link>
		<comments>http://www.cakesolutions.net/teamblogs/2008/05/08/acegi-concurrent-login/#comments</comments>
		<pubDate>Thu, 08 May 2008 09:05:05 +0000</pubDate>
		<dc:creator>Aleksa Vukotic</dc:creator>
		
		<category><![CDATA[Aleksa's Blog]]></category>

		<category><![CDATA[acegi]]></category>

		<category><![CDATA[concurrent login]]></category>

		<category><![CDATA[concurrentloginexception]]></category>

		<category><![CDATA[java]]></category>

		<category><![CDATA[Spring]]></category>

		<guid isPermaLink="false">http://www.cakesolutions.net/teamblogs/2008/05/08/acegi-concurrent-login/</guid>
		<description><![CDATA[It is a security requirement for most web sites to disable concurrent logins, so users cannot login from different machines using same login details.
Let&#8217;s see how to enable this functionality with Acegi Security.
Firstly, add org.acegisecurity.concurrent.SessionRegistry implementation bean to your security context:


&#60;bean id="sessionRegistry" class="org.acegisecurity.concurrent.SessionRegistryImpl" /&#62;


We are using default Acegi implementation org.acegisecurity.concurrent.SessionRegistryImpl.
Next, define the org.acegisecurity.concurrent.SessionController bean:


  [...]]]></description>
			<content:encoded><![CDATA[<p>It is a security requirement for most web sites to disable concurrent logins, so users cannot login from different machines using same login details.</p>
<p>Let&#8217;s see how to enable this functionality with Acegi Security.</p>
<p>Firstly, add <code>org.acegisecurity.concurrent.SessionRegistry</code> implementation bean to your security context:<br />
<code>
<pre>
&lt;bean id="sessionRegistry" class="org.acegisecurity.concurrent.SessionRegistryImpl" /&gt;
</pre>
<p></code></p>
<p>We are using default Acegi implementation <code>org.acegisecurity.concurrent.SessionRegistryImpl</code>.</p>
<p>Next, define the <code>org.acegisecurity.concurrent.SessionController bean</code>:</p>
<pre>
<code>
    &lt;bean id="sessionController" class="org.acegisecurity.
           concurrent.ConcurrentSessionControllerImpl"&gt;
        &lt;property name="exceptionIfMaximumExceeded" value="true"/&gt;
        &lt;property name="maximumSessions" value="1" /&gt;
        &lt;property name="sessionRegistry" ref="sessionRegistry"/&gt;
    &lt;/bean&gt;
</code>
</pre>
<p>As you can see, it takes <code>sessionRegistry</code> property, as well as two additional properties <code>maximumSessions</code> and <code>exceptionIfMAximumExceeded</code>.<br />
<code>maximumSessions</code> says how meny concurrent login sessions  are allowed (in our case just one)<br />
if <code>exceptionIfMAximumExceeded</code> property is set to true, exception will be thrown every time the user tries to login concurrently. You can check this exception in your login controller and display user with a message.<br />
Otherwise, if <code>exceptionIfMAximumExceeded property</code> is set to false, exception will NOT be thrown. If user tries to login concurrently, he will be allowed, but his last login session (before the concurrent one) will be invalidated.</p>
<p>Last step is to add  <code>sessionController</code> property to your <code>ProviderManager</code> bean:<br />
<code>
<pre>
     &lt;bean id="authenticationManager" class="org.acegisecurity.providers.ProviderManager"&gt;
		&lt;property name="providers"&gt;
			&lt;list&gt;
				&lt;ref local="daoAuthenticationProvider"/&gt;
			&lt;/list&gt;
		&lt;/property&gt;
        &lt;property name="sessionController" ref="sessionController"/&gt;
    &lt;/bean&gt;
</pre>
<p></code></p>
<p>And you&#8217;re ready to run.</p>
<p>Some users have encountered problems with concurrent logins: If a user logs out, and then tries to log in again, the <code>ConcurrentLoginException</code> is thrown, so user cannot log in again. This happens when Acegi logout does not remove the session data for the user that has been logout out (before his login session has expired)<br />
In order to fix this, you can manually clear the authentication session for the user that&#8217;s logged out:<br />
<code>
<pre>
public void logout() {
        SecurityContext context = SecurityContextHolder.getContext();
        if (context == null) return;
        Authentication authentication = context.getAuthentication();
        if (authentication == null) return;
        String sessionId = SessionRegistryUtils.obtainSessionIdFromAuthentication(authentication);
        this.sessionRegistry.removeSessionInformation(sessionId);
}
</pre>
<p></code><br />
You will also need this code to be run when Acegi session gets unpublished.<br />
For this implement <code>org.acegisecurity.ui.session.HttpSessionEventPublisher</code>, and configure listener for it in your web.xml:<br />
<code>
<pre>
public class MyHttpSessionEventPublisher extends HttpSessionEventPublisher {
    private static final Log logger = LogFactory.getLog(MyHttpSessionEventPublisher.class);
    private UserContext userContext;

    public void sessionDestroyed(HttpSessionEvent event) {
        logger.info("unpublishing session");
        if (userContext == null) {
            this.userContext = lookupBean(
                        WebApplicationContextUtils.
                             getWebApplicationContext(
                              event.getSession().getServletContext()),
                       "userContext",
                       UserContext.class);
        }

        this.userContext.invalidate();
        super.sessionDestroyed(event);
    }

    private  T lookupBean(final ApplicationContext applicationContext, final String beanName, final Class c) {
        //noinspection unchecked
        return (T) applicationContext.getBean(beanName, c);
    }
}
</pre>
<p></code></p>
<p>In web.xml you will have:<br />
<code>
<pre>
&lt;listener&gt;
        &lt;listener-class&gt;net.cakesolutions.service.security.acegi.BimHttpSessionEventPublisher&lt;/listener-class&gt;
&lt;/listener&gt;
</pre>
<p></code><br />
And you&#8217;re ready to go.</p>
<p>Hope this article has helped anyone in configuring concurrent logins with Acegi Security.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cakesolutions.net/teamblogs/2008/05/08/acegi-concurrent-login/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Email Header Injection security</title>
		<link>http://www.cakesolutions.net/teamblogs/2008/05/08/email-header-injection-security/</link>
		<comments>http://www.cakesolutions.net/teamblogs/2008/05/08/email-header-injection-security/#comments</comments>
		<pubDate>Thu, 08 May 2008 08:31:08 +0000</pubDate>
		<dc:creator>Aleksa Vukotic</dc:creator>
		
		<category><![CDATA[Aleksa's Blog]]></category>

		<guid isPermaLink="false">http://www.cakesolutions.net/teamblogs/2008/05/08/email-header-injection-security/</guid>
		<description><![CDATA[If you web application sends emails based on information entered in the form, you should pay attention to the possibility of Email header injection attack.
Email header injection attack is based on flaws in the email protocol. Headers in the MIME message are recognized by SMTP servers by the line feed ([LF]). So typical email message [...]]]></description>
			<content:encoded><![CDATA[<p>If you web application sends emails based on information entered in the form, you should pay attention to the possibility of Email header injection attack.<br />
Email header injection attack is based on flaws in the email protocol. Headers in the MIME message are recognized by SMTP servers by the line feed ([LF]). So typical email message looks like this:<br />
<code><br />
[LF]to: recipient@domain.com<br />
[LF]Subject: recipient@domain.com<br />
[LF]Content type: recipient@domain.com<br />
[LF]Message body<br />
</code><br />
Now if a user can enter recipient email in the form he/she can do something like this:<br />
<code><br />
recipient email: johndoe@serbiancafe.com%0Asubject:this is new even subject.<br />
</code><br />
%0A is actually line feed.<br />
Now, it will depend from SMTP server and email client which subject will it show, some use first one, some the lates one, some append all subjects to email.</p>
<p>Malicious user can change any header of your message this way, to, cc, bcc fields, content-type, even the actual message.</p>
<p>Message body can be changed in the same way, only without the header name. But note that body added like this will be PREPENDED to the email message. So if someone uses your email form to send an email message with new body he/she can enter the follwing in the available form filed (in our case recipient address):<br />
<code><br />
recipient email: johndoe@serbiancafe.com%0Asubject:this is new even subject.%0AThe Spam message body, you didnt want this, but it will come to your inbox<br />
</code><br />
And without knowing it, your &#8216;email this page to a friend&#8217; form will become the source of spam!</p>
<p>Now how to resolve this issue?<br />
You shpuld check all the fields that are available for user input in your email form for  and  characters (&#8217;\n&#8217; and &#8216;\r&#8217; in your java code).</p>
<p>You have two approaches available. You can either:<br />
1. reject to send any email that contains any of these characters (recommended)<br />
2. remove the characters and send the email as it is </p>
<p>The java code that does this is very simple:</p>
<p><code><br />
public static boolean isHeaderInjection(String value) {<br />
        if (value == null) return false;<br />
        if ((value.indexOf("\n") != -1 || value.indexOf("\r") != -1) || value.indexOf("%0A") != -1) {<br />
            return true;<br />
        }<br />
         return false;<br />
     }<br />
</code></p>
<p>Make sure to check all your email form fields, and you should be safe from this kind of attack.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cakesolutions.net/teamblogs/2008/05/08/email-header-injection-security/feed/</wfw:commentRss>
		</item>
	</channel>
</rss>
