Class.forName(className) does not work properly in Groovy. If you type Class.forName, the JVM does not use the correct class loader.
The solution is to use this instead:
Thread.currentThread().contextClassLoader.loadClass(className)
Class.forName(className) does not work properly in Groovy. If you type Class.forName, the JVM does not use the correct class loader.
The solution is to use this instead:
Thread.currentThread().contextClassLoader.loadClass(className)
Your browser caching pages served from Grails can be quite a nuisance. Defining a preventCache()-method like below, and calling that from your controller method, stops the caching.
private static final String HEADER_PRAGMA = "Pragma";
private static final String HEADER_EXPIRES = "Expires";
private static final String HEADER_CACHE_CONTROL = "Cache-Control";
protected preventCache (response) {
response.setHeader(HEADER_PRAGMA, "no-cache");
response.setDateHeader(HEADER_EXPIRES, 1L);
response.setHeader(HEADER_CACHE_CONTROL, "no-cache");
response.addHeader(HEADER_CACHE_CONTROL, "no-store");
}
Groovy has convenient classes for working with XML. You can use the XmlParser (or XmlSlurper) if you want to parse existing XML into a tree structure. You can use the XmlBuilder, if you want to build XML from scratch. But what if you want to read existing XML, change it, and write it back again? It’s easy. You can use the XmlNodePrinter object for that:
def xmltree = new XmlParser.parseText("<node text='hello'>")
xmltree.@text = 'goodbye'
StringWriter writer = new StringWriter()
new XmlNodePrinter(new PrintWriter(writer)).print(xmltree)
writer.toString()
Lately I wrote about the Grails security plugin, not providing sufficient security if you configure it using annotations. The first thing you might have done after that, is secure your whole application in SecurityConfig.groovy, like this:
<!-- this provides basic security for the whole application --> /**=ROLE_XXX <!-- TODO: add more specific rules for specific patterns and pages -->
If you go to any page in your application, the grails security plugin will be triggered and send you to the login page… which is also secured, triggering the grails security plugin to send you to the login page…
Of course, you have to exclude the login page from the security rules. How can you do this? By adding a rule specific for the login page, allowing anonymous access to it:
<!-- this excludes the login page --> /login/**=IS_AUTHENTICATED_ANONYMOUSLY <!-- TODO: add more specific rules for specific patterns and pages --> <!-- this provides basic security for the whole application --> /**=ROLE_XXX
Note that the security rules must be ordered from more specific to less specific. If the security plugin finds a pattern that matches, it will not look at the other patterns anymore. That’s why the basic rule for securing the whole application must be put last.
The Spring Security Plugin offers a very easy way to secure URLs in your grails application. It works with users, roles and url patterns. Each user can be assigned a number of roles. Based on the roles a user has, access to URL patterns is granted or rejected by the Spring Security Plugin.
The documentation for the plugin describes three ways to specify the URL patterns that must be secured: by storing security mappings in the database, by storing them in a text file, or by defining annotations on controllers and actions.
Annotations seem to offer an attractive way to define security. But be warned. On grails 1.1.2 and the grails-acegi-plugin-0.5.2, I found a security leak using annotations. The security leak is caused by the way grails handles extensions on a URL.
Look at the following controller:
class TestController {
@Secured(['ROLE_ADMIN'])
def index = { render text: "this page should be secured" }
}
If you surf to http://myserver:8080/myapp/test/index, you are presented a login screen, because the index controller is secured with @Secured(['ROLE_ADMIN']). This is the intended behaviour of the plugin. However, if I add “.html” to the URL, the whole login screen is bypassed. The content of the controller is shown without ever having to login. This is a major security issue, I would say.
The solution I chose, was to use text-based security. This way, you can prevent the above from happening, BUT YOU STILL HAVE TO BE CAREFUL. Do not forget to follow the instructions HERE, or otherwise you will still have the same problem.
Another way of solving the problem, is to disable content negotiation (which is enabled by default!). In Config.groovy, change
grails.mime.file.extensions = true
to
grails.mime.file.extensions = false
This is not a solution if you need to use content negotiation of course.