Tuesday, September 13, 2011

Grails Logging & New Website launched

This month I’ve got special news. We just launched our new family site http://scheelethek.de. :)
It’s developed in Grails and shows once more that Grails is the right application framework for fast, fun and reliable web-development.
Ok, it took some time to launch it. But that wasn’t Grails’ fault. There was just no time besides my professional and family life. I coded up to one hour every several weeks only.
But Grails makes it easy to stay connected without the need to read up on the previous development again and again.

This month I decided to post the logging configuration of this application. This is a part of Grails that isn’t very intuitive.
I think the logging requirements of my application are sophisticated but still very common:

  • In Development and Test-Mode logging should be done to the console (“Stdout”)
  • In Production-Mode logging should go to a file (and “Stdout” should be deactivated)
  • The file should be recreated on size-threshold or time (“rollingFile”)
  • In Development and Test-Mode logging should be done on “Debug-Level”; for Production it should be the “Info-Level
  • The Logging should include the name of the logged in user (or session-id if not logged in). The format is as follows:
    2011-09-11 17:19:02,290 [http-8080-5] (0646291FBCC5F8E95BE6E10C4AB9DFBE) INFO user.RegistrationController - User 'Hans Wurst' has registered. Sending email to: hans_wurst@sdfds.de
  • When Warnings or Errors are logged, an eMail should be sent directly into my mailbox; including the message
  • Of course: All components of my application should have logging activated

My configuration for Grails 1.3.7 in the Config.groovy looks like this:
def logPattern = '%d{yyyy-MM-dd HH:mm:ss,SSS} [%t] (%X{user}) %p %c{2} - %m%n'
log4j = {
    
	appenders {
   	 
      	console name:'stdout', layout:pattern(conversionPattern: logPattern)
      	'null' name:'stacktrace'
     	 
      	environments {
          	production {
               // rolling file per size
              	rollingFile name:'fileAppender', maxFileSize:'2MB', file: "/opt/mypath/myLog.log", layout:pattern(conversionPattern: logPattern)
                // rolling file per date
                //appender new DailyRollingFileAppender(name: 'file', datePattern: "'.'yyyy-MM-dd", fileName: "/opt/mypath/myLog.log",layout: pattern(conversionPattern: logPattern))
              	'null' name:'stdout'
              	// mail appender
              	appender new org.apache.log4j.net.SMTPAppender(
                  	name: 'mail',
                  	to: 'myemail@mysdfwhatever.de',
                  	from: 'noreply@mysdfwhatever.de',
                  	threshold: org.apache.log4j.Level.WARN,
                  	bufferSize: 1,
                  	subject: "Error on ScheeleThek",
                  	layout: pattern(conversionPattern: logPattern),
                  	//SMTPDebug: true,
                  	SMTPHost: 'localhost'
              	)
          	}
      	}
	}
    
	root {
    	     error 'stdout', 'fileAppender', 'mail'
	}

	error  'org.codehaus.groovy.grails.web.servlet',   
       	'org.codehaus.groovy.grails.web.pages',  
       	'org.codehaus.groovy.grails.web.sitemesh',  
       	'org.codehaus.groovy.grails.web.mapping.filter',  
       	'org.codehaus.groovy.grails.web.mapping',  
       	'org.codehaus.groovy.grails.commons',  
       	'org.codehaus.groovy.grails.plugins',  
       	'org.codehaus.groovy.grails.orm.hibernate',  
       	'org.springframework',
       	'org.hibernate',
       	'net.sf.ehcache.hibernate'

	warn   'org.mortbay.log'
    
	debug  'de.scheelethek',
        	'grails.app'
	 
	environments {
   	   production {
        	  info	'de.scheelethek',
        	    	'grails.app'
   	    }
	}
  	 
}
As described above the logging outputs the name or session-id of the current user. This is very useful when all activities of a user should be collected later on. To make this work you need a Grails filter like this:
      class UtilityFilters {
    
	SpringSecurityService springSecurityService
    
	def filters = {
   	 
   	 
    	/**
     	* Used for setting the log4j diagnostic context:  Username if available; otherwise the session-id
     	*/
    	logContext (controller: "*", action: "*") {
       	 
        	before = {
            	if (springSecurityService.isLoggedIn()) {
                	MDC.put('user',"${springSecurityService.principal?.username}")
            	} else {
                	if (RequestContextHolder.getRequestAttributes()!=null) {   	// if we have a valid web-request
                    	MDC.put('user',"${session.id}")
                	}
            	}
        	}
       	 
        	afterView = {
            	MDC.remove 'user'
         	}
       	 
    	}
   	 
	}

}

Monday, August 1, 2011

Grails Security - XSS Prevention using Html-Codecs

There are so many applications out there that don’t care about Cross-site scripting (XSS) attacks. Try some of your favourite sites. Just type something like
<script type="text/javascript">alert("attack")</script>
into an input field and check if you get such a message:



Grails has a nice feature for fixing this basic XSS issue.
All you need to do is set the default-codec to html in your Config.groovy:
grails.views.default.codec = "html"
Now every expression inside the ${...} syntax gets encoded in your GSPs:
${'<script type="text/javascript">alert("attack")</script>'}
would become
&lt;script type=&quot;text/javascript&quot;&gt;alert(&quot;attack&quot;)&lt;/script&gt;

Beyond that you need to be careful with Tags (e.g. <g:message...>). Output from those Tags are not encoded by the default-codec. It’s up to the Tag’s implementation.

But what’s with the exception of the rule? What if you have some Html output which should not be encoded, but printed like it is? Or what if you have an email-template which is sent as plain text where variables are not allowed to be encoded?
You can do the following to avoid encoding in special cases :

  • Use the syntax <%=expression%> (instead of ${expression})
  • Put <%@page defaultCodec="none"%> on the top of your template. All ${expression} inside this GSP are not encoded

There is still one small criticism regarding the default codec in Grails:

If you generate a new Grails project the default codec is ‘none’. I saw so many projects in my Grails consulting that didn’t change this (because they did not know or just forgot it). To change this afterwards is a pain and leads to increased effort.
I hope in Grails Version 2.0 the default-codec will change to ‘html’.

Thursday, July 7, 2011

Grails - Accessing the Http-Session from Services

Holy Cow. I didn’t make it the last six months to write a post here. Too much stuff is going on in private and business life. But I promise improvement by writing an article at least once a month.
As I’m currently working most of the time on Grails projects, I restart the Blog with a little Grails series. Starting with the question: Is it useful to access a http-session in a Grails Service.

In general it isn't a very good idea to access the web session from within Services.
First of all you never know if the web session is available: Think about calling the service method from a job or JMS call (instead of a controller). There wouldn't be any http-request associated with the current thread.
Second, it's a common and good design pattern to separate the service logic from client specific stuff.

But there are circumstances where it may be adequate to access the session within a service.
One way to do it would be to use a method parameter for transferring the session object.
However, that could clutter method signatures which isn't a nice design also.
Another way could be to use Spring's session scope beans. This seems to be right for
many cases, but could be a little too much overhead for simple use cases.

A pretty alternative is to implement a small service that encapsulates the access to
the http-session in a safe manner.

This service could look like this:

 class WebUtilService {

    void withSession (Closure closure) {
        try {
            GrailsWebRequest request = RequestContextHolder.currentRequestAttributes()
            GrailsHttpSession session = request.session
            closure.call(session)
        }
        catch (IllegalStateException ise) {
            log.warn ("No WebRequest available!")
        }
    }
    
}

It's used like this:

class MyService {
    
    WebUtilService webUtilService
    
    void doSomething() {
        webUtilService.withSession { HttpSession session ->
            log.info ( session.myValue )
            session.newValue = 'Possible, but should be exceptional'
        }
    }

}