Chapter 10. Don’t let strangers in—security


In this chapter

  • Why you need to consider security
  • How to protect your application from attacks
  • Implementing access control

Hubbub’s user interface has improved dramatically in the last couple of chapters, so it’s time to consider the implications of releasing Hubbub into the wild. That means understanding what might happen to the application when it’s public, and making sure nothing horrible happens. Welcome to the world of security.

10.1. Why security matters

We’re sure that you’re aware of some of the security issues related to web applications and perhaps some of the techniques for mitigating the risk. We’ll cover most of them in relation to Grails, so you’ll know what measures you can take to harden your applications against attack and unauthorized access. By the end of the chapter, you’ll have the confidence to publish a web application in the real world with real users.

Before we go into the details, though, we’ll tell a short story. Company A was a successful bank that wanted to provide an internet service for their customers. They realized that such a system would be under constant threat from villainous rogues trying to gain access to customers’ details and their money, so they brought in a system that would turn their internet portal into the virtual equivalent of Fort Knox. No man-in-the-middle attacks would fool it, customers never sent their credentials in full to the server, and everything was done over SSL. For all intents and purposes, it was impregnable.

Then, one day, an employee copied the details of thousands of customers to a laptop to continue working at home. The next morning, the employee accidentally left the laptop on the train, and it was gone. The details on that computer, all unencrypted, were worth far more than the laptop itself. It was a huge embarrassment to the company, which had to contact all the affected customers and inform them of the incident. Many of them closed their accounts and went elsewhere. The bank’s reputation suffered almost irreparable damage.

This is a fictional story, and we hope that no bank would ever allow employees to copy customer data (particularly unencrypted data) and carry it around. Yet there have been several high-profile incidents in which laptops have been left in public places and confidential information has been lost in the mail!

The point behind the story is that security isn’t a product or a technology; it isn’t something you can buy off the shelf. Making your application accessible only via SSL doesn’t magically make it secure. Security is a process and a mindset. We don’t expect you to push for a change of organizational mindset at your company, but we do think it’s important to keep the moral of that story in your mind when developing applications, even if you’re just working on a personal project in your spare time.

Let’s explore some of the threats that your applications face and the ways that you can protect against them.

10.2. Protecting against malicious intent

You have probably heard of the internet worms that travel the world in minutes and infect website after website, and of websites that have been defaced and applications that have been tricked into giving confidential information to people who shouldn’t have access to it. There’s certainly no shortage of people who are willing to invest a bit of time in these nefarious activities. Your job is to stop them from doing something similar to your own applications.

The most important thing you can do is think about what you’re developing and always consider the security aspect. If we can also get you thinking like an attacker, then so much the better! Just don’t turn into one and then blame us. We like to avoid legal entanglements.

In this section, we’ll take you through some simple steps and thought processes that will considerably reduce your risk of exposure and protect you against the majority of potential attacks. Although our examples are presented in the context of Grails, you can apply the concepts to any development in any language.

We’ll start by considering one of the biggest areas of weakness in software: dealing with external inputs.

10.2.1. Validate all your inputs

Imagine that you want to search in Hubbub for all posts that have been tagged “grails”. There are millions of such posts because it’s such a cool topic to discuss, and if Hubbub attempted to return all of them, the request would punish both the server and the client. To prevent this, Hubbub returns 50 by default. But suppose you only want the 10 most recent results.

We can deal with that in Hubbub by accepting a max parameter (which would contain the value 10) and passing that through to the underlying query:

def search = {
def max = params.max?.toInteger ( ) ?: 50
def results = Post.findAllByTag ( "grails", [ max: max ] )
...
}

Note that this code doesn’t match the Hubbub application as it stands, but it serves to illustrate an important point. You might look at it and think there’s nothing wrong, but there’s a fundamental flaw: it trusts the user. Consider what would happen if the user tried this URL: http://localhost:8080/hubbub/post/search?query=grails&max=1000000000.

That’s a max value of one billion! Our action will now attempt to return and display all the posts with the tag “grails” (there aren’t quite a billion such posts). A few requests like that, and your server will grind to a halt. It’s a classic denial of service (DoS) scenario.

The moral is simple: never trust external sources of data—validate everything you use. A simple solution in this particular case is to cap the value of max:

def max = params.max?.toInteger ( ) ?: 50
max = Math.min(max, 500)

This small change will allow a user to request up to 500 posts, but no more. This is a simple case, but what if you have several parameters to check across lots of actions?

An alternative approach is to use command objects, which allow you to declare validation constraints and check whether there are errors. Because you can reuse command objects in different actions, you end up with a system that’s much easier to maintain than if you manually validated the parameters. You also get all the other benefits of command objects that you saw earlier in the book.

Alternatively, if you don’t want the hassle of creating a command object, try the multitalented bindData() method instead. The following example binds all parameters except any named “created”:

def update = {
def post = new Post()
bindData(post, params, ["created"])
...
}

Chapter 5 introduced this blacklist version of the method, in which the third argument to bindData() is a list of the domain class fields that must not be bound. Because a user should not be able to affect the time at which a post is created, we exclude that field. bindData() also excludes some default properties: id, version, metaClass, and properties (the last two are related to Groovy, so don’t worry about them). Note that this method is dynamically injected into controllers, so you can’t use it from services or domain classes.


The dangers of binding to domain classes

As you have seen, you can also bind parameters directly to domain objects. This is dangerous, because any parameter value matching a domain class field will be bound. An attacker could modify a property that you don’t want them to.

You can use a command object instead, and then bind its properties to the domain object, like so:

def update = { PostCommand cmd ->
if (!cmd.hasErrors()) {
def post = new Post(cmd.properties)
...
}
...
}

“Aha!” we hear you cry. “What if I do the validation on the client? Then I don’t have to bother with it on the server.” Validation on the client is definitely useful for the user, but it would be a mistake to then leave it out of the server.

Double Validation

Whenever you develop a web application, remember that the interface to the application isn’t a browser: it’s the HTTP protocol. Anyone can send requests to your application from any client. They can even use telnet and manually craft the HTTP requests; after all, HTTP is a pretty simple text-based protocol. Your client-side validation won’t be activated in such a situation. Alternatively, the user may disable JavaScript in their browser.

What this means for your application is that it could receive anything from a client—and probably will. This is why you have to do validation on your server as well as in the client. We know it’s not DRY (Don’t Repeat Yourself), but unfortunately it’s the price you have to pay for a rich client backed by a publicly accessible server. This rule holds no matter what type of client you use, whether it be JavaScript in a browser, a Flash application, or a Java applet.

It’s not just the stuff in the params object you have to worry about, either. What if you’re handling requests that contain data that you need to read from the request directly?

Other Types of Requests

As you’ll see in the next chapter, you may have requests that contain XML, JSON, or even custom data. In such cases, the information is usually not added to the params object, so the data-binding techniques we’ve shown so far won’t work. What can you do?

If it’s possible with the data you’re receiving, you could parse it into a map of parameters and values that you could then use with the bindData() method. JSON data is particularly amenable to this approach. Alternatively, if you’re dealing with XML, you should consider using XML Schema. This allows you to add constraints to attribute values and element content, so you can provide input validation in a declarative manner.

If all else fails, you’ll have to roll your own validation, even if that means checking the values manually as we did with the max parameter in the example earlier. Using no validation at all isn’t an option, or at least not a safe one.

You should now see that validating input is crucial to protecting your application. Fortunately, with simple data checks, careful data binding, and constraints, you can easily protect yourself against malign HTTP requests. As you’ll see in the Hubbub source code for this chapter, we’ve implemented the necessary changes in the controllers.

Such code will get you a long way to ensuring that your web applications remain safe in a dangerous world, but don’t think the story is over. You’ll almost certainly write an application in the future that gets information from a different source or in a format that doesn’t fit the data-binding mechanisms. At that point, the most important thing to remember is that the input should be validated, come what may.

Usually, input validation isn’t enough on its own. Dangerous input isn’t always obvious and can be difficult to detect. That means you need to be careful about what you do with any input data you receive.

10.2.2. Escape all your outputs

Imagine that we have a controller action in Hubbub that displays all the posts for a given user. For example, here’s a useful query that does this:

def userId = "peter"
Post.findAll("from Post as post WHERE post.user.userId = '${userId}'")

This query uses a local userId property to control which posts are returned. Looks pretty innocent, doesn’t it?

Go ahead and try it in the Grails console—copy the two lines of the example, and execute. Depending on how much data you have, you should see something like the first screenshot in figure 10.1.

Figure 10.1. An HQL query run first with a perfectly safe input value (on the left) and a second time with an example SQL injection attack (on the right). In the latter case, all posts in the database are returned by the query.


Data and the console

If your database is configured for create-drop or has no data in it, the examples in this section won’t be particularly helpful. You can quickly populate the database with some sample data by running these two lines in the console:

def bs = new BootStrap()
bs.init()

Now imagine that an attacker modifies the URL of the request so that the userId parameter has the value in this example:

def userId = "' or 'test' = 'test"
Post.findAll("from Post as post WHERE post.user.userId = '${userId}'")

The query is the same, but this time userId doesn’t look like an ID at all. Look what happens when we substitute the value into the query:

... WHERE post.user.userId = '' or 'test' = 'test'

Oooh, sneaky! What the attacker has done is modify the query so that all posts are returned, which could quite easily bring your server to a grinding halt! This is an example of what is known as a SQL injection attack. The second screenshot in figure 10.1 shows its effect.

Input validation may stop the request from ever getting to the point where the query is executed, but in many cases validation can’t prevent dangerous values from getting through without blocking valid ones as well. Fortunately, there’s a simple solution: by escaping the input value before inserting it into the query, you foil the attack.


Note

You’ll rarely suffer from this problem in your Grails applications because both dynamic finders and criteria queries automatically escape their arguments.


We’ll finish off this little example with a modified version of the HQL query that’s safe from the attack because it escapes the value of userId:

def userId = "' or 'test' = 'test"
Post.findAll("from Post as post WHERE post.user.userId = ?", [ userId ])

This is the Hibernate equivalent of a JDBC parameterized query.

We’ll now consider another, related scenario. Start the Hubbub server, log in to the application, and then try to post this message (verbatim!):

<script type="text/javascript">alert("Got ya!")</script>

What happens? A dialog pops up showing the message “Got ya!” Now every time you refresh your timeline page, that message will pop up. Oops, that doesn’t look good. You have just demonstrated how a cross-site scripting (XSS) attack works. It’s another form of injection attack, but in this case it targets HTML and JavaScript rather than SQL.

Not surprisingly, the solution is the same as for SQL injection: escape the user input before displaying it in a web page. This can either be done manually, by calling the encodeAsHTML() method on the text you want to display, or automatically, by adding (or changing) this entry in grails-app/conf/Config.groovy:

grails.views.default.codec = "html"

With this setting, Grails will escape all expressions in your GSP files for HTML—and you don’t have to lift a finger!


Warning

Although the grails.views.default.codec setting works in most cases, it won’t escape any values in GSP tag attributes, nor will it escape the output of tags themselves. Tags should perform any required escaping or encoding themselves.


To see the effect of the setting in practice, consider this fragment of GSP code:

<div>${post.content}</div>
<g:textField name="test" value="${post.content}"/>

The post’s content is escaped automatically in the first line, because it’s referenced from inside a standalone expression. But Grails won’t do the same for the value attribute on the second line. That’s why the implementation of the textField tag does the equivalent of this:

attrs["value"].encodeAsHTML()

In general, though, if you use HTML as the default GSP codec and the standard Grails GSP tags, you don’t have to worry. Just be aware that any custom GSP tags you write should take account of escaping issues if they write any of their input directly to the output.

We’re almost done here, but we think it worth mentioning that escaping or encoding user input won’t work if you don’t pick the right codec for the job. For example, if an input value is going into a URL link, use the encodeAsURL() method; if it’s going elsewhere in an HTML page, use the HTML codec.

We’ve only given examples of two types of injection attack here, but there are others, such as code injection (say, if you allow users to provide Groovy code that you then run), OS command injection (anything passed to Runtime.exec() or equivalent), and file-path injection. In all these cases, be aware whether you’re dealing with untrusted input or not, and if so, escape it or cleanse it some other way.

Along with input validation, escaping your output appropriately protects you from a whole class of potential attacks. Although the potential consequences are severe, we hope that you’ll gain confidence from how simple it is to shield your application from those attacks. Awareness is the key: always think, “am I using untrusted input, and if so, what am I doing with it?”

We’ve so far concerned ourselves with dealing with inputs from untrusted sources, but if your application were to hold sensitive information about users, you’d face another issue. How do you transfer that information without people being able to read it?

10.2.3. SSL, encryption, and message digests

Imagine that your bank’s internet portal allowed you to send your user ID and password (or other credential) unencrypted. Does that sound like a safe thing to do? We certainly don’t think so, and that bank would lose customers pretty quickly. The problem is that although you think you’re sending information directly to the website, its route is often far from straight, and this gives attackers the opportunity to look at that information.

The standard solution is to use the HTTPS protocol, which encrypts all communication between the browser and the server by using Secure Sockets Layer (SSL). As an added bonus, SSL requires the server to publish an SSL certificate, which gives users confidence that they’re using the real website rather than a fake.

Running your Grails application in HTTPS mode is as simple as passing the --https argument to the run-app or run-war command. You’ll then be able to access the application via an https://localhost:8443/... URL as well as with the more usual http://local-host:8080/... one.

If you do run Hubbub or your own application like this, you’ll notice that your browser doesn’t seem too happy when accessing it. Figure 10.2 shows you what Firefox thinks of Hubbub over HTTPS. The problem is that Grails creates a self-signed SSL certificate on demand. In effect, your application is saying, “trust me, I am who I say I am.” In this case, you know that you can trust it because you started the server, but how can real users do so?

Figure 10.2. Trying to access Hubbub via HTTPS with Firefox 3. The browser doesn’t like the self-signed certificate, but you can accept it by adding it as an exception (see the link at the bottom of the screen).

In order to avoid such messages from the browser, you need to get your SSL certificate signed by what is known as a Certificate Authority (CA), like VeriSign, Thawte, Comodo, or Go Daddy. Most (if not all) browsers recognize and trust these providers by default, so when users access websites that have certificates signed by one of them, they see the locked padlock (or some other indication that the site is secure) and no warning or error messages.

So how do you get your certificate signed by one of these CAs? All the providers will give you explicit instructions for doing this, but the general procedure is something like this:

1.  

Create a private key for your server using the JDK’s keytool command.

2.  

Generate a Certificate Signing Request (CSR).

3.  

Send the CSR to the CA.

4.  

Wait for them to send you a signed certificate back, and then import it into your keystore.

SSL may be the closest most web application developers get to encryption, but that doesn’t mean it’s the only time you’ll ever need it. In case you ever find yourself contemplating using manual encryption or signing (a relative of encryption), here are a few guidelines that may help:

  • Use industry-standard encryption and hashing algorithms—don’t try to roll your own!
  • Don’t use algorithms with known vulnerabilities, such as DES, SHA-1, and MD5.
  • Don’t transfer private keys!

You’ll see that we mentioned SHA-1 and MD5 in that list. These aren’t encryption algorithms but hash functions that create a fixed-length representation of some given data. That representation is called a “hash” or “digest.” The idea is that if the data were to change, then so would its hash. This allows you to detect whether data has been tampered with if you know what its original hash was. Instead of SHA-1 and MD5, consider using SHA-256 or SHA-512. These have no known weaknesses at this time and can be used in the same way as the older hash functions.


Note

If you are interested in why SHA-1 and MD5 are considered vulnerable, the Wikipedia articles for the two functions are a good starting point.


We’re already using a hash function in Hubbub to store the users’ passwords, and this is quite a common technique. Any website that will reset your password instead of sending it to you is probably storing passwords like this—there’s no way for it to get the original data (the password, in this case) from the hash. It’s a one-way algorithm. The main reason for using hashing in this way is so that even if people have access to the data in the database, they can’t then use the password to impersonate another user.

That’s a pretty quick tour of cryptography, and we’ve barely touched the surface. For most people, using SSL will solve any confidentiality requirements that they have. Just make sure that users can’t access confidential information via (unencrypted) HTTP. Before we move on, we’d like to mention The Legion of the Bouncy Castle (http://www.bouncycastle.org/), who have an incredibly useful open source Java. Cryptography Extension (JCE) provider with quite a few encryption algorithms, such as Blowfish. They even have classes for working with OpenPGP.

We’ve now covered three areas of concern, but there’s one more left. It’s not a vulnerability, but it’s nearly as important.

10.2.4. Don’t give away information

Imagine for a moment that you’re one of those unscrupulous types who wants to hack into an application. What would you do? You could try some of the injection attacks we’ve already seen, but the developer has closed those holes. That means you have to try a lot of different attacks to find a vulnerability.

An alternative approach is to find out what platform the web application is based on. If you know that, you can narrow your hacking attempts to known vulnerabilities of the platform. Finding out that information can be trivial. Take a look at this URL: http://www.somecompany.com/orders/buy.php.

Unless the company is being clever, it’s a pretty safe bet that PHP is the underlying technology on this website.

Grails applications don’t make it quite so obvious, but there are still weaknesses. Try pointing your browser at this URL while Hubbub is up and running: http://localhost:8080/hubbub/path/unknown.

You can see the result in figure 10.3: any attacker now knows that Hubbub is a Java web application running on Jetty. Even worse, if your application throws an exception, Grails will display its standard error page. Then the attacker also knows that your application uses Grails.

Figure 10.3. Hitting an unknown page displays information about the platform by default. Try to avoid gifting attackers such useful information.

Back in chapter 5, we introduced you to a feature that helps in this situation: mapping response codes to controllers. Ideally, we want to map all the error response codes that Grails typically generates to our own views:

class UrlMappings {
...
"403"(controller: "errors", action: "forbidden")
"404"(controller: "errors", action: "notFound")
"500"(controller: "errors", action: "internalError")
}

You’ll see in the next chapter that there are plenty of other HTTP status codes you could map, but it’s only worth mapping the ones that your application uses. If any part of the application uses a different status code from those listed here, add an entry for it to the URL mappings.

Unfortunately, that’s not quite the end of the story. Certain parts of the GSP infrastructure are currently hard-coded to display the view grails-app/views/error.gsp if an exception is thrown by a GSP page. This completely bypasses the mechanism we just used, declaring to the whole world that your application is implemented with Grails. To work around this issue, we recommend that you modify the GSP to send a “500” error if the environment is set to production:

<%@ page import="grails.util.Environment" %>
<g:if test="${Environment.current == Environment.PRODUCTION}">
${response.sendError(500)}
</g:if>
<g:else>
...
</g:else>

This change means that your production application won’t be divulging information about its platform, but you still get the benefits of the error message and stack trace when running in development and test environments.

You can breathe a sigh of relief now—we’ve completed our coverage of typical web application vulnerabilities and the techniques you can use to remove them. You now know enough to make sure that your application isn’t as leaky as the typical website, plus you have the mindset and tools to tighten the security further.

All of the information we’ve discussed in this section and more is covered in the “CWE/SANS Top 25 Most Dangerous Programming Errors” (http://cwe.mitre.org/top25/) and the OWASP “Top 10” (http://www.owasp.org/index.php/Top_10_2007). These websites are a must-read—they give you lots of information about the hazards that await the application developer with regard to security. You’ll also find some useful tools at OWASP such as Scarab, a tool that will automatically test your application for common vulnerabilities.

Before we move on to another essential aspect of application security, we should mention that code reviews are a great way of preventing vulnerabilities from slipping into your code. So long as the whole team is always reviewing code with one eye on security, your applications will stay secure.

Protecting against malicious intent is a major part of application security, and by considering whether your code is vulnerable as you write it, you can mitigate a lot of the risk. Yet, that’s only part of the puzzle. If any part of your application is restricted to specific users or groups of users, you need to make sure that people can’t see or do what they shouldn’t.

10.3. Access control

Many applications need to know who the user is, either because they’re storing information that should only be visible to certain (known) people, or because they need to restrict access to some or all of their functionality. Maybe they need to track who does what. In Hubbub, for example, we’re not interested in anonymous posts: when a user posts a new message, Hubbub needs to know who posted it. We also want to make sure that only a user can modify his or her own profile. Nobody else should be allowed to do so, except perhaps a system administrator.

This is what access control is all about. It can range from simply making sure that only real people (as opposed to “bots”) can access an application, to using complex rules based on multiple permissions, projects, and groups. Hubbub falls firmly into the first category, but we’ll try to provide enough information that you can readily go beyond the basics.


A question of terminology

The phrase “authentication and authorization” is fairly common and means pretty much the same thing as “access control,” but the latter is currently the preferred term in security circles. Different security frameworks also tend to have their own jargon, which can make comparing them quite difficult. If in doubt, pick one that you understand.


Access control breaks down into two main aspects:

  • Is the person you’re communicating with who they say they are (authentication)?
  • Do they have the rights to perform a given action (authorization)?

Simple access control can be implemented via standard Grails filters and the session, but you’re almost invariably better off using one of the available security plugins. Why reinvent the wheel? These are the main candidates:

  • Authentication plugin The Authentication plugin is a lightweight authentication implementation with no dependencies on any third-party libraries. It’s good for websites that require registered users but don’t have complex authorization requirements.
  • JSecurity plugin The JSecurity plugin provides full-featured access control and cryptography via the Apache JSecurity library (currently an Incubator project). Although JSecurity isn’t widely known yet, it has been used in production systems for several years.
  • Spring Security (Acegi) plugin Formerly known as Acegi Security, Spring Security is a well-known and widely used framework for Java web applications. It provides the most comprehensive suite of authentication options of the three plugins listed here. Newcomers often find it difficult to understand, but the plugin does a great job of hiding much of the complexity.

A couple of options we haven’t listed here are the standard Java Authentication and Authorization Service (JAAS), which comes as part of the JDK, and J2EE access control as provided by J2EE containers. Although standards, they aren’t widely used in the Grails community, and JAAS is quite difficult to use and understand. That said, if you find yourself using them, documentation for both should apply to Grails applications.

The plugins operate as gatekeepers to the web application, as illustrated in figure 10.4. They decide whether a particular request is allowed through to the application, based on configured rules. If a request is allowed, the plugin displays the application’s response. Otherwise, it may require the client to log in, or it may display an “access denied” page.

Figure 10.4. How the typical Grails security plugin fits into the request/response cycle. The “?” highlights where the request may or may not be forwarded to the application at the plugin’s discretion.

We can’t cover all of these plugins in this chapter, so we’ll concentrate on the Spring Security plugin. Many of the ideas we’ll discuss apply equally to the other plugins, so you should have no trouble using them in combination with their online documentation.

10.3.1. Getting started with Spring Security

Access control is impossible without determining who the current user is. Hubbub currently does this by requiring users to enter their user ID and password on the login page and then storing the corresponding User instance in the HTTP session (assuming authentication is successful). We want to replace this basic mechanism with the more full-featured Spring Security.

The first step is to install the plugin:

grails install-plugin acegi

You may find the name of the plugin a little confusing, but it makes sense when you realize that the plugin was first created while the framework was still called Acegi Security.

With that done, you now have access to a small collection of useful scripts, one of which generates the domain classes that the Spring Security plugin needs. Without them, you’ll have no access control.

If you were creating an application from scratch and using Spring Security from the start, this process would be straightforward:

grails create-auth-domains org.example.User org.example.Role org.example.Requestmap

This would create three classes in grails-app/domain/org/example: User, Role, and Requestmap. We’ll explain what these are for in due course, but first we have to deal with the fact that we already have a User class, and we’d quite like to keep it. So, rather than using the preceding command, we use this one:

grails create-auth-domains DummyUser com.grailsinaction.Role Requestmap

In this case, our existing User class won’t be overwritten, but now the plugin is configured to get user information from the DummyUser class.

Not to worry, that’s easily fixed. The plugin can use any domain class for the user as long as it contains fields for the username, password, whether the account is enabled or not, and a collection of authorities, or roles. Our User domain class already has the first two, so all we have to do is add the other two:

class User {
String userId
String password
boolean enabled

static hasMany = [ authorities: com.grailsinaction.Role,
... ]
static belongsTo = com.grailsinaction.Role
...
}

We also need to fix the Role class, because it’s currently linked to DummyUser, so we change the relationship like so:

class Role {
static hasMany = [people: User]
...
}

Because we have our own user class, we don’t need DummyUser any more. Removing it helps keep the application uncluttered. Because the associated scaffold pages won’t work without the domain class, we should also remove DummyUserController and its views (grails-app/views/dummyUser).

The User and Role classes form the basis of our access-control system, determining who can do what. It’s a simple model, as demonstrated in figure 10.5. One last thing we need to do is update the code in BootStrap so that all the preconfigured users are assigned a role, or authority. Users who have none can’t log in. What the code for this looks like is unimportant at this stage, but you can see the changes in the sample Hubbub code for the chapter. You’ll also see in the code that we use the plugin’s authenticateService object to encode passwords before storing them in the database:

authenticateService.encodePassword("password")
Figure 10.5. The relationship between the core access-control domain classes. The model is simple.

Although we’ll move on now, don’t worry. We’ll come back to this service a little later.

Next, we need to configure Spring Security to work with our custom User class. When you ran the create-auth-domains command, it sneakily added an extra file to your grails-app/conf directory: SecurityConfig.groovy. This one file allows you to control many aspects of the plugin and Spring Security—it even has an extensive reference page: http://www.grails.org/AcegiSecurity+Plugin+-+Customizing+with+SecurityConfig.

The copy of SecurityConfig.groovy in Hubbub currently looks like this (give or take a comment or two):

security {
active = true
loginUserDomainClass = "DummyUser"
authorityDomainClass = "com.grailsinaction.Role"
requestMapClass = "Requestmap"
}

You should recognize the last three values because they were the ones you passed to the create-auth-domains command. You can probably guess what we do next: change the loginUserDomainClass value to com.grailsinaction.User. Voila! Spring Security is now using our own user class.


Warning

Be careful with the active configuration option: setting it to false will disable Spring Security, and you’ll lose your access control! Even more important, the same will happen if the option is removed from the file or the file itself is deleted.


We’re not quite done yet. By default, the plugin expects the user domain class to contain fields named username and passwd, but ours are userId and password. To fix this, we add the following two options to SecurityConfig.groovy:

userName = "userId"
password = "password"

So far so good. Spring Security isn’t doing anything for us yet, but it’s primed and ready. All we have to do is point and shoot, or, more specifically, configure the URLs that we want protected.

10.3.2. Protecting URLs

We’re going to start with a simple security model for Hubbub: all pages will require an authenticated user except the home page, which anyone will be able to view. The plugin gives us three options for specifying this information:

  • Static config— The rules are declared in SecurityConfig.groovy.
  • Dynamic— The rules are stored in the database as Requestmaps.
  • Annotations— The rules are declared using annotations in controllers and services.

Now you know what the Requestmap domain class is for! It maps URLs to permissions, or “authorities” in Spring Security terminology. This approach is useful if you want to change the security settings after the application has been deployed. Annotations allow you to secure controllers regardless of the URL used to access them. They’re also convenient for securing service methods.

For Hubbub, though, we’re going with the old-fashioned static-config approach, partly because it keeps all the security information together, and partly because we need to talk about the ordering of rules. Because we aren’t using dynamic URL rules, we can delete the Requestmap domain class, its corresponding controller, and the associated views.

Let’s now look at the configuration we’ll be using to implement the required access control. Listing 10.1 shows you the SecurityConfig.groovy file that we end up with once the URL rules are added. This ensures that all users have access to the home and login pages, but only authenticated users can see the rest of the application. We also make sure that all JavaScript, CSS, and image files are unsecured.

Listing 10.1. Spring Security configuration for Hubbub’s simple access-control model

The first half of the file is mostly stuff you’ve seen already—it’s the second half that we’re interested in right now. In order to use the static config, we first disable the dynamic Requestmap handling . Then come the URL rules themselves, in a multiline string assigned to the requestMapString option . Note that the configuration is line-based, so make sure every entry is on its own line.

The first two lines of the configuration are general settings and are typically included in all Spring Security configurations. The first one forces Spring Security to lowercase the URLs of requests before comparing them to the rules. A URL like

http://localhost:8080/hubbub/starPost/showAll

would become

http://localhost:8080/hubbub/starpost/showall

before the comparison. That means your URL rules in requestMapString should be all lowercase. The second general setting specifies that Spring Security will use standard Ant path-matching behavior when comparing request URLs to rules. This means that to create a rule that matches all .js files, you could use /**/*.js, which specifies any file with a .js extension in any directory.

After the general settings, we declare the rules we want in order. Because we want the home page accessible to anyone, the first rule assigns IS_AUTHENTICATED_ ANONYMOUSLY to the root URL (/). We also need to allow everyone access to the login page (/login/auth) provided by the plugin—otherwise no one could log in! The static resources, such as JavaScript, CSS, and image files (provided by the application and plugins), are also configured this way. Finally, we restrict access to all other URLs to authenticated users—those who have successfully logged in.

You have to be careful with the order of these rules, because Spring Security uses the first one that matches the request URL. For example, if you put the last rule first (/**), all pages of your application would require an authenticated user regardless of the rules that come after. The more specific the URL pattern in a rule, the earlier it should go in the list.

Hubbub is now secured against anonymous access. If a user doesn’t have an account, he can’t post any messages. Try it out by starting the server and pointing your browser at http://localhost:8080/hubbub/post/timeline. You’ll automatically be redirected to the plugin’s login page, shown in figure 10.6.

Figure 10.6. The Spring Security plugin’s standard login page, with the “Remember me” check box

You can log in using one of the existing users, such as glen with a password of password, but this will generate a server error. We still need to integrate the login with the rest of the application, which currently expects to find the User instance in the session.

Before we do that, let’s take a quick look at that “Remember me” option on the plugin’s login page. It’s a feature we’re sure you’re familiar with from various websites, and it suits Hubbub quite well. The application doesn’t need a high degree of security, so allowing the user to access the application without logging in every time is a big win. The problem is, if you come back to Hubbub after some time, you’ll find you can’t access the application. In fact, the browser gets confused because it keeps being redirected to the same page again and again. Spring Security sees that the user is remembered and bypasses the login page. Unfortunately, most of the application’s pages require a fully authenticated user, so the user is redirected to the /login/denied page. This also requires a fully authenticated user, so we get stuck in a loop!


Warning

Never allow the user to select the “Remember me” option if the application doesn’t support it. If you’re using the default login page provided by the plugin, remove the “Remember me” check box.


For Hubbub, we want to support “Remember me,” and to do that we change this URL rule

/**=IS_AUTHENTICATED_FULLY

to this:

/**=IS_AUTHENTICATED_REMEMBERED

That’s it! The “Remember me” feature now works, and the browser won’t get stuck.

Now that we’ve sorted out that problem, let’s make the access control work better for Hubbub.

10.3.3. Getting hold of the current user

The access control is looking promising so far, and we haven’t had to do much work. It’s not quite working for us yet, but that won’t take long to fix. The first thing we need to do is fix the user’s timeline page, which is currently generating a “500” error because it can’t access the logged-in user.

We have a couple of options available to us. First, we could store the User instance in the session when the user logs in, because we can edit the login controller that the plugin created for us (grails-app/controllers/LoginController.groovy). But this would be a bit of a waste because we can get it from Spring Security directly. Why use up valuable session space if we don’t have to? So instead, we’ll go with the second option: change the application code to get the user from Spring Security.

One way to do this would be to get the current Spring Security context from the SecurityContextHolder class and extract the user. This context represents all the security information related to the current user, so it can provide you with pretty much anything you need. It’s not particularly pleasant to deal with, though, so it’s fortunate that the plugin provides the authenticate service. This service contains lots of useful methods, most of which are listed in table 10.1.

Table 10.1. A summary of useful methods provided by the plugin’s authenticate service

Method

Description

isLoggedIn()

Returns true if the current user is logged in, otherwise false

ifAllGranted(roles)

Returns true if the current user has all the given roles, otherwise false; roles is a comma-separated list of role names as a string

ifNotGranted(roles)

Similar to ifAllGranted, but only returns true if the user has none of the given roles

ifAnyGranted(roles)

Similar to ifAllGranted, but returns true if the user has at least one of the given roles

userDomain()

Returns the domain instance for the current user

encodePassword(pwd)

Encodes the given password with the configured hash algorithm and returns the hash; this hash can be stored in the password field of the user domain class

isAjax(request)

Returns true if the given HttpServletRequest appears to be an AJAX one

As you can probably guess, we want to use the userDomain() method to get hold of the User instance. One thing to bear in mind is that the method returns a detached instance, which means it isn’t bound to the underlying Hibernate session. That means we can’t access any of its collections or save any changes to it until we reattach it to the session. In this case, because we want to make sure we have the user’s latest details, we refetch the user from the database.

Here are the changes we need to make in the post controller:

class PostController {
def authenticateService
...
def list = {
def user = authenticateService.userDomain()
user = User.get(user.id)
...
}
...
def add = {
def content = params.postContent
if (content) {
def user = authenticateService.userDomain()
user = User.get(user.id)

if (user) {
...
}
}
...
}
...
}

The plugin’s authenticate service will be injected into the authenticateService property by Grails, and we can then use it to get hold of the current user.

That fixes the controller, but if you try to access the /post/timeline page, you’ll still get an error. Our sidebar GSP template still grabs the user directly from the HTTP session. Your first thought may be to access the authenticate service from the template (an ugly solution, and a bad idea) or add the user to the model returned by the action (a better idea). Unfortunately, the sidebar template is referenced from a layout, so all views that use that layout will require the model to contain the user instance.

Fortunately, we don’t have to worry about that problem because the plugin provides us with a tag library that does what we need. Instead of code like this

<dd>${session.user.userId}</dd>

our grails-app/views/post/_sidebar.gsp can use a special tag that allows us to print out any field of the user instance:

<dl>
<dt>User</dt>
<dd><g:loggedInUserInfo field="userId">Guest</g:loggedInUserInfo>
</dl>

We can also use this tag as a method, as in this example fragment:

<g:createLink action="following" controller="friend"
id="${loggedInUserInfo(field: 'userId')}"/>

Once we’ve implemented these few changes, Hubbub will come roaring back to life.

While we’re on the subject of GSP tags, we can add the following block to any of our layouts so that users can log out at any time:

<g:isLoggedIn>
<g:link controller="logout" action="index">sign out</g:link>
</g:isLoggedIn>

The isLoggedIn tag is another one provided by the plugin. It only writes out its contents if the user is logged in via Spring Security. In this case, the content is a link to the logout controller created by the plugin earlier (in our application’s grails-app/controllers directory).

The access control is working nicely now. Only authenticated (or remembered) users can access the /post/timeline page, and new posts are correctly associated with the currently logged-in user. We can even provide a link allowing the user to log out. What more do we need?

One problem is that we now have two login pages, so it would be good to get rid of one. Let’s keep the old one that sits on our home page.

10.3.4. Using a custom login page

The process of configuring the plugin to use our home page as its login page is easy—we add these entries to SecurityConfig.groovy:

loginFormUrl = "/"
defaultTargetUrl = "/post/timeline"

The first option makes sure that Spring Security redirects to the home page when authentication is required, and the second tells Spring Security to load the user’s timeline page by default after a successful login. If the user is redirected to the home page to authenticate, Spring Security will then redirect back to the original page.

Unfortunately, that’s not quite all we have to do. Our existing login form won’t work as it is because the fields need to have special names—ones that are recognized by Spring Security. On the bright side, this gives us an opportunity to add a “Remember me” box. Here is the new form in grails-app/views/_sidebar.gsp:

<form action="${resource(file: 'j_spring_security_check')}" method="POST">
<table>
<tr><td>User Id:</td><g:textField name="j_username"/></td></tr>
<tr>
<td>Password:</td>
<td><input name="j_password" type="password"/></td>
</tr>
<tr>
<td>Remember:</td>
<td><input type="checkbox" name="_spring_security_remember_me"/></td>
</tr>
<tr><td colspan="2"><g:submitButton name="login" value="Login"/></td>
</table>
</form>

The critical parts of this code are the form’s action URL and the names of the user ID, password, and remember fields.

Now that everything is working and we have basic access control in place, it’s time to consider how we can test this. We do want to make sure that it’s working properly and that future changes don’t break anything!

10.3.5. Testing access control

Spring Security, like other security frameworks, uses a combination of servlet filters and other types of interceptors to control access to an application. This makes it particularly tricky to test, because there are no classes that you can unit test nor do filters take part in integration tests. Both types of test are redundant when it comes to testing access control. Functional tests are the only game in town.

Figure 10.7 shows the logic that we want to test. It’s not comprehensive, but it does illustrate what we’re trying to achieve with our tests. We want to make sure that all the conditions work and that application pages are displayed when we expect them to be.

Figure 10.7. A simple access-control logic flow that we want to functionally test. The expected behavior depends on the URL of a request and whether the user is logged in or not.

Writing a test to confirm the behavior shown in the diagram is straightforward, and you can see the resulting code in listing 10.2. As in chapter 7, we’re using the Functional Test plugin to access particular URLs, but now some of those URLs are protected.

Listing 10.2. A functional test to verify the access-control behavior

We start by ensuring that users have access to the login or home page . You should also make sure that any other pages that allow anonymous access are checked in this way. We then check the behavior of a protected page, which in this case is the user’s personal timeline. An unauthenticated user should be redirected to the login page , and a failed login attempt should result in the same.

We finish up by checking a successful login and then making sure that the logout URL does log the user out . This serves two purposes: first, we ensure that the logout code works; and second, we make sure that subsequent tests don’t start with an authenticated user. We try to leave the application in the same state as it was at the start of the test.


Note

The code in listing 10.2 demonstrates the usefulness of factoring out code into utility methods, such as login(). These can also be collected into a base class so that all your functional tests can benefit from them.


Congratulations! Everything is now working, and we have a system in place that we can grow as we need. And remember, a lot of the work involved has come from using our existing domain classes and views. The process is much simpler and quicker if you accept the defaults that the plugin provides. That said, by doing it the hard way, we’ve explored several facets of Spring Security and the plugin that will stand you in good stead for the future.

In the remainder of the chapter, we’ll look at more advanced techniques that will help you with a variety of security requirements and add some useful refinements to Hubbub.

10.4. Further exploration of Spring Security

Spring Security is a powerful framework with various options for authentication and authorization, many of which the plugin exposes to you. It would be impossible to discuss everything you can do with Spring Security in a single chapter—a book would be more appropriate. So rather than attempt the impossible, we’ll introduce you in this section to some common scenarios that require special treatment. First, we need to fill some gaps in Hubbub’s current access-control setup.

10.4.1. Adding user registration

You may already have spotted a problem with the user management in Hubbub: we don’t have any! Although the BootStrap currently creates a few standard users, Hubbub as an application isn’t much good if we can’t add more.

One option would be to build a user-management UI around the User and Role classes. The plugin even helps you do so by providing a generate-manager command. Hubbub isn’t that kind of application, though. Users won’t want to send emails to a system administrator to get an account set up. The typical solution is to allow users to register, so that’s what we’ll do.

Again, the plugin helps out here by providing a command that will get us started on the road to user registration:

grails generate-registration

This one command will set up the necessary controllers and views, and even download JavaMail and Activation JARs so that the plugin can send confirmation emails. Not only that, but the registration screen includes a captcha to help prevent spam bots from signing up.

That’s almost all we need to do, but the user-registration feature provided by the plugin has a few extra requirements we need to satisfy. First, we need to add these fields to our User class:

class User {
...
String email
String userRealName
boolean emailShow = false
...
static constraints = {
...
email(nullable: true, blank: true)
userRealName(nullable: true, blank: true)
}
...
}

We add the extra constraints because BootStrap is currently not giving the users it creates values for the new fields, so we need to make them optional. It’s a case of expediency. Note that the user domain class generated by the plugin includes these extra fields by default.

One more thing we mustn’t forget is that the user registration adds some extra URLs that need to be accessible to users who aren’t authenticated. We need to add these two rules to the security configuration:

/captcha/**=IS_AUTHENTICATED_ANONYMOUSLY
/register/**=IS_AUTHENTICATED_ANONYMOUSLY

It’s not much good having a screen for registration if the users can’t access it. Remember, these rules should go before the one for /**; otherwise the captcha and registration pages will require an authenticated or remembered user.

With that last change, you can start up Hubbub again and access the userregistration screen at http://localhost:8080/hubbub/register/. You’ll see that the interface is pretty basic, but you can register a new user ID and then log in with it straight away. Also, because the plugin generates the controllers and views in your project directory, you can customize the pages and behavior to your heart’s content.

An extra feature of the user registration that we haven’t mentioned yet is email confirmations. You can configure the plugin to send an email to any user who successfully registers. This feature is disabled by default, but you can enable it via this option in the security configuration:

useMail = true

You then need to configure an SMTP server so that the plugin can send the emails. You’ll find a complete listing of the email options at the URL for SecurityConfig settings (http://www.grails.org/AcegiSecurity+Plugin+-+Customizing+with+SecurityConfig).

Note that the email feature is quite basic and only handles notification messages. It can’t send an email containing a code or link to activate the corresponding user account, so if you want this behavior, you’ll have to implement it yourself. Nonetheless, the user registration does a reasonable job for little effort and gives you a good starting point from which to take it further.

That almost completes the security infrastructure for Hubbub, but there are still a couple of concerns regarding who can do what. It’s also about time you found out what that Role class is for.

10.4.2. Tightening restrictions on access

Spring Security uses the concept of authorities for assigning and determining rights: who can do what. Its implementation is surprisingly powerful, but because the concept of authorities is quite abstract, it’s difficult for people to understand.

The plugin sidesteps this problem by only dealing with named authorities called roles. These are simple—they’re names. A user is assigned any number of said roles, which gives him or her the right to access any URLs restricted to any of those roles. Table 10.2 demonstrates how rule requirements combine with role assignments to determine whether a user has access to a particular URL. If any of the roles the user has match any of the required roles, access is granted. Note that in these examples, ROLE_USER and ROLE_ADMIN are strings. Also, if a user has no role, then he or she can’t even log in.

Table 10.2. How role requirements and role assignments relate to each other

Rule requires

User has

Access granted?

ROLE_USER

ROLE_USER

Yes

ROLE_ADMIN

ROLE_USER

No

ROLE_USER,ROLE_ADMIN

ROLE_USER

Yes

So how are roles assigned? By linking a Role instance to a User instance either programmatically, as we do in BootStrap in the example Hubbub source code, or via a user-management UI. The latter is ideal if you want to assign or revoke user privileges at runtime.

A typical Role instance might have a name of ROLE_USER and a description of “A known, registered user of the system.” You can then make that role a requirement for any given URL by adding it to the corresponding rule:

/profile/**=ROLE_USER

This begs the question, what is the difference between IS_AUTHENTICATED_REMEMBERED, IS_AUTHENTICATED_FULLY, and ROLE_USER?

  • IS_AUTHENTICATED_REMEMBEREDBuilt into Spring Security. Allows any user that’s authenticated or remembered.
  • IS_AUTHENTICATED_FULLYBuilt into Spring Security. Allows any user that’s authenticated. Does not allow remembered users.
  • ROLE_USERUser-defined role that only allows access to users that have been assigned it. Applies whether the user is authenticated or remembered.

Let’s consider a more concrete example. Say you have created a user-management UI using the plugin’s generate-manager command. You don’t want just anybody to have access to it because modifying user information and adding, deleting, or disabling accounts are highly sensitive operations. What do you do?

First, you create a new role, in BootStrap, for example, with the name ROLE_ADMIN, and assign it to a user:

def role = new Role(authority: "ROLE_ADMIN", description: "A super user.")
def admin = new User(userId: "dilbert", ...).save()
role.addToPeople(admin)
role.save()

Then, you restrict access to the user-management URLs to that role:

/user/**=ROLE_ADMIN
/role/**=ROLE_ADMIN
/requestmap/**=ROLE_ADMIN

That’s it! Your user-management UI is now restricted to administrators only.

All straightforward, we think you’ll agree. But there is one fly in the ointment. Imagine that users can edit their profiles. We can limit access to the Edit Profile page by role, but then anyone with the required role can access everyone’s profile—definitely not what we want! This is where we hit the limits of Spring Security and have to implement a solution ourselves.

The easiest way to add this kind of feature is via Grails filters. All we have to do is configure a before interceptor on the profile controller that checks whether the current user is the owner of the requested profile. Listing 10.3 contains such a filter, which goes into grails-app/conf/SecurityFilters.groovy. If the current user’s ID doesn’t match the one given in the request URL, access is blocked.

Listing 10.3. Restricting access using a filter

The filter is surprisingly simple. The first point to make is that we use the authenticate service to get hold of the current user’s information. Inside the filter, we compare the current user’s ID to the userId parameter from the request . If they don’t match, we redirect to the plugin’s standard “access denied” page and return false to prevent Grails from going further with the request. Otherwise we let the request go through. You can’t get much easier than that!

We’ve now finished with the authorization side of things. You have certainly learned enough to cover many of the situations you’re likely to encounter; but for those occasions when you need finer-grained control, you might want to look into Spring Security’s Access Control Lists (ACLs). Although the plugin doesn’t support them directly at the time of writing, it may well do so in the near future. Alternatively, you might consider the JSecurity plugin, which has a large degree of flexibility and power. For more information, visit their home pages on the Grails website.

If we’re done with authorization, what’s left? There are some interesting scenarios regarding authentication that we think you might be interested in.

10.4.3. Other authentication options

The authentication we’ve used so far is based on storing users and their passwords in the database. Although this is one of the most common approaches, it isn’t the only one. Spring Security (and, by extension, the plugin) supports many schemes via what it calls “authentication providers.” You may be surprised to learn that Hubbub is already using three of them:

  • AnonymousAuthenticationProvider
  • RememberMeAuthenticationProvider
  • GrailsDaoAuthenticationProvider

It’s the last of these that uses our User domain class for authentication.

In most cases, enabling a provider is straightforward because it simply involves adding a few entries to the security configuration. We’ll now take a walk through some of the more useful providers. You can find more information about them on the plugin’s website, which includes tutorials as well as reference information.

LDAP

Most commonly used in corporate environments, the Lightweight Directory Access Protocol (LDAP) is an API for accessing any type of hierarchically structured data. One of its most popular uses is for storing user accounts, and it has its own authentication scheme. If your company keeps all its user data in an LDAP server, you probably need to authenticate users of your application against it. Microsoft’s Active Directory implements LDAP, so you can access it in the same way.

OpenID

The holy grail of web application authentication is to allow the user to authenticate once and immediately have access to a vast array of different applications. OpenID is one technology that’s seeking to fulfill that goal. At the moment, user IDs are URLs and are often difficult to remember, but it’s becoming more widely used with support from Yahoo!, Microsoft, Google, and MySpace, to name a few.

When you log into an application with OpenID, you’re authenticating against an OpenID provider, which then redirects you back to the original application. There are already several providers from which to choose.

Facebook Connect

If you haven’t heard of Facebook, where have you been? It takes a similar approach to OpenID except that there’s only one provider: Facebook. It means that you can log into an application with your Facebook account, providing the application with some of the social network information.

Basic Authentication

This is the granddaddy of authentication on the web. It uses HTTP headers and status codes for its implementation, and Spring Security supports it via a filter rather than an authentication provider.

It isn’t often used by websites these days, particularly as the user credentials are passed to the server in clear text. It also adds some overhead because the credentials are sent with every request. In many cases this is unnecessary, but it does make sense for software clients that don’t want to mess around with cookies. In fact, when used over HTTPS, it’s ideal for REST clients when your application requires access control. You’ll find out more about REST in the next chapter.

By default, the plugin and its login controller only support one authentication provider at a time, but you can change this fairly easily. In the security configuration, add an option called providerNames and set its value to a list of the authentication providers you want:

providerNames = ['facebookAuthProvider',
'daoAuthenticationProvider',
'anonymousAuthenticationProvider',
'rememberMeAuthenticationProvider']

All you then have to do is modify your login controller and form to support these multiple authentication types.

As I’m sure you can see, Spring Security provides many options, and we’ve barely scratched the surface in this section. It has even more authentication providers that you can choose from, it supports access control on service methods, and it also has an event mechanism. For more information on all these features, check the online documentation for both the plugin and Spring Security itself.

You can now breathe a sigh of relief—you’ve made it! We’ve covered a lot of material in this chapter, and yet there is even more to the whole subject area. Don’t worry, though; we’ve given you a solid foundation on which to build your knowledge in this area.

10.5. Summary and best practices

Security is a complex subject that often requires the average developer to think in new ways. You have seen several examples of the types of attacks that your Grails applications might face, but the focus has been more on the techniques you should apply, rather than the attacks that they counter. While developing, it’s easier to remember to “validate all your inputs” rather than to “protect against SQL/code/whatever injection attacks.”

Thought also needs to be applied to the access-control rules you set up. A framework like Spring Security can make it easy to add access control to an application, but it’s no more secure than the rules you define. Make sure you understand the application’s specific requirements before implementing its access control.

Another important point to think about is how secure the application needs to be. How sensitive is the information in it? What are the consequences if an attacker manages to masquerade as a genuine user? You can put a lot of security checks in, but are they worth the associated cost in development time and possibly user inconvenience? For example, Hubbub doesn’t contain particularly sensitive information, but it should make it difficult to post messages as other people. On the other hand, a banking application requires far more checks and should make sure that no one can even see user-specific information.

Here are some ideas and guidelines to help you protect your application:

  • Remember the motto: “strength in depth.” If you only have a single layer of security around your application, an attacker who gets through has untrammeled access to the whole application. You should also perform input validation in your controllers and use the query options that auto-escape parameters, for example.
  • Know your trust boundaries. A trust boundary is a point of communication where one side is trusted and the other is not. It’s at these trust boundaries that you must be particularly vigilant, scrubbing data that comes in and making sure data going out is safe.
  • Test, test, test! Make sure that the application isn’t susceptible to common types of attack by using functional tests and automated tools like OWASP’s Scarab.
  • Obfuscation isn’t a substitute for proper security. Hiding or mangling information can be useful—after all, there’s no point in advertising anything that might help an attacker. But if you rely on obfuscation, you run a high risk of compromise. It’s complementary to other techniques, not a substitute.
  • Develop with security in mind. Remember that security is a process and a mindset. In order for your application to be secure, you have to consciously consider the potential effects of the code you write.
  • Perform code reviews. Just as code reviews help weed out coding mistakes and movements in the direction of the “ball of mud” design pattern, they can also pick up security flaws. There’s nothing like a second pair of eyes when it comes to catching these things.
  • Use existing tools and frameworks. No matter how vigilant you are, errors will creep in. Security tools and frameworks are battle tested and in wide use. That means vulnerabilities are quickly found and quashed. Why risk your application by using homegrown solutions?

Lastly, we’d like to reiterate that there are several security frameworks available for. Grails, so if you need one, we think it’s worth a little research to make sure you pick the right one for you.

With all this security knowledge under your belt, you can now consider opening up your applications a bit and allowing access to software clients, and not just human users via their web browsers.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset