Introducing Spring Roo: Part 2 – Security, JMS & Email support

Many of you have taken part in the voting process for the official name of the new Spring productivity solution codenamed ‘Spring Roo’, which was announced during the SpringOne conference in Amsterdam last month. There was a lot of buzz around this project and an encouraging amount of traffic resulted on the Roo name voting application.

While there were quite a number of votes cast during the official voting process (as a result the project is now officially called ‘Spring Roo’), we noticed that there were some access attempts to the administrative back end via the login form. This is of course an issue that many web sites face. Illegal access attempts or even DoS attacks and other security threats should be taken seriously. As a result we have come up with a solution which detects such malicious behavior and notified administrators accordingly. This blog post outlines the solution we have come up with and demonstrates the use of two new add-ons we have included into today’s Spring Roo 1.0.0.M1 release.

Requirements

To receive notification of malicious behavior on the voting application we wanted to receive emails which supply the date and time of the attack if certain criteria were met. One of the challenges of monitoring illegal login attempts and sending emails relates to when this should happen. Specifically, you don’t want the overhead of monitoring illegal login attempts to slow down the user interface front-end. Similarly, you don’t want the overhead of sending an SMTP message (which could potentially involve a remote server) from blocking the main user interface processing.

Spring Framework offers a number of features which help build this solution. It offers a MailTemplate which helps send emails via SMTP and other protocols. It also offers the Spring Scheduling API which provides an abstraction to the Java Timer API, the Quarz scheduler or Spring’s own TaskExecutor API. It also offers JMS integration, and we decided to use JMS for this solution. Using JMS allows the delegation of long running processes (such as sending of emails to a potentially remotely hosted application such as on Amazon EC2 instance) to asynchronous messaging infrastructure. As a result, we are using JMS for loosely coupled distributed communication.

In the next steps I will outline how to enhance the voting application (the Roo command script is included in the Spring Roo 1.0.0.M1 release) by writing a simple Spring Security listener which monitors application backend access attempts and publishes a message to a JMS topic. I will then show how a JMS topic consumer receives these security alert JMS messages and sends off an email (via GMail) to notify the system administrator of the potential attack.

Running the vote script

To install the Spring Roo 1.0.0.M1 release all you need to do is unzip it, and add the bin directory to your path (for Windows users) or create a symbolic link to the roo.sh shell script. Note that this process is even easier than the last alpha release of Spring Roo (which also needed you to setup an environment variable).

Next all you need to do is to create a new directory and run the vote.roo script:

$ mkdir vote
$ cd vote
$ roo
roo> script vote.roo

Note that this will install all necessary artefacts for the fully functional voting application. The artifacts include an embedded Java database which is mapped by JPA, several domain objects, controllers, JSP, Dojo, Spring Security, logging, tests and a number of other features. Take a look at the commands issued and the files created from it to get the full picture.

Now, first you need to tell Spring Security to protect the administrative backend REST URIs by adding the following lines to the applicationContext-security.xml, which is located in the /src/main/resources directory:

<intercept-url pattern="/choice/**" access="ROLE_ADMIN" />
<intercept-url pattern="/vote/**" access="ROLE_ADMIN" />

The above configuration will cause Spring Security to protect the URIs once the ‘Create new Choice’ link is clicked.

JMS & Spring Security

Since the voting application comes with Spring Security already installed, all we need to do is to create a new Java class that will receive security events via Spring’s existing ApplicationEvent infrastructure. Once these ApplicationEvents are received and appropriate business logic to filter the events has been applied, a message may be sent to the JMS topic. Let’s use Roo to create the listener:

roo> new java file -name ~.security.BackendAccessListener

Next, we want to use JMS in our application and make use of it in the BackendAccessListener:

roo> install jms -provider ACTIVEMQ_IN_MEMORY -destinationType TOPIC -destinationName securityAlerts
roo> add field jms template -class ~.security.BackendAccessListener

Notice we’re using Apache ActiveMQ in the installation command. ActiveMQ is a popular open source JMS provider that is used in many large installations and there is commercial support available. If you need JMS, ActiveMQ is definitely worth taking a look at.

Now we should take a look at the BackendAccessListener.java file and customize it a little to implement our business logic:

@Component
public class BackendAccessListener implements ApplicationListener<AuthenticationFailureBadCredentialsEvent>{

	private long lastFailureEventTime;
	private long timeLastWarningJmsSent;

    @Autowired
    private transient JmsTemplate jmsTemplate;

	public void onApplicationEvent(AuthenticationFailureBadCredentialsEvent event) {
		System.out.println("bad credentials notification received: " + event.getTimestamp());

        if (lastFailureEventTime > new Date().getTime() - (1000 * 5)) {
        	// the last failure happened less than 5 seconds ago

        	System.out.println("the last failure happened less than 5 seconds ago");

        	// so we want to send an email out, provided we haven't sent one in the last 5 minutes
        	if ((timeLastWarningJmsSent + 1000 * 60 * 5) < new Date().getTime()) {
        		System.out.println("the last message was less than 5 minutes ago");

            	timeLastWarningJmsSent = new Date().getTime();
            	// someone illegally tried to login
        		System.out.println("Failure event detected at " + event.getTimestamp());
            	jmsTemplate.convertAndSend(new Long(event.getTimestamp()));            }
        }
        lastFailureEventTime = event.getTimestamp();
	}
}

First, we need to make the BackendAccessListener a Spring container managed component so that it will automatically receive messages via Spring’s ApplicationEvent infrastructure. Next we record the time of the current access failure event and compare it to the last. If the time difference is less than 5 seconds and we have not send a notification email within the last 5 minutes, we send out a JMS message to the “securityAlerts” JMS topic.

At this point we have a JMS message appearing in the topic whenever a brute force attack appears to be in progress, but we’ve limited these messages to a maximum of once every 5 minutes. You are free to write a consumer that will monitor the JMS topic and then take whatever action you like, such as logging to a database etc.

In our case we’d like to consume the message from the JMS topic and send an email using SMTP. To this we issue the following command in the Roo shell:

roo> new java jms listener -class ~.security.JmsSecurityTopicListener -destinationName securityAlerts -destinationType TOPIC

This will create a simple Java POJO with an “onMessage” method. Since we know that the message is of type java.lang.Long, we can just autobox it:

 public void onMessage(Long timestamp) {
        System.out.println("JMS security alert message received: " + timestamp);
 }

Now you could deploy and run your application to see JMS in action when you cause a few bad login attempts.

Email add-on integration

Sending and receiving a JMS message decouples our security application logic from the actual voting application nicely. Now we can safely install email support without fear of slowing down the voting application interface:

roo> install email provider -hostServer smtp.gmail.com -protocol SMTP -port 587 -username stsmedia -password yourpassword

Note that the email addon provides quite a number of configuration options such as host, protocol, port, username, password and encoding, but using tab completion on the shell should avoid you having to type most of the command. Roo will offer email protocol support for SMTP, IMAP or POP3 when you try tab completion. The install email command will install the Spring MailTemplate in your application context as well as a email.properties file which allows you to conveniently change your settings later on if desired. Roo actually provides commands for this as well:

roo> property file details -name email.properties -path SRC_MAIN_RESOURCES
email.host = smtp.gmail.com
email.username = stsmedia
email.password = yourpassword
email.port = 587
email.protocol = smtp
roo> property file set -key test -value test -name email.properties -path SRC_MAIN_RESOURCES

Now back to the email integration. We should now install the MailTemplate into the JmsSecurityTopicListener class:

roo> add field email template -class ~.security.JmsSecurityTopicListener

This gives us access to the MailTemplate configured in the application context, as well as the SimpleMailMessage so that we can go ahead and complete the email message before sending it off:

public class JmsSecurityTopicListener {

    @Autowired
    private transient MailSender mailTemplate;

    public void onMessage(Long timestamp) {
        Date dateTime = new Date(timestamp);
        System.out.println("JMS security alert message received: " + dateTime);
        sendMessage("gmailuser@gmail.com", "Possible illegal login detected at " + dateTime, "recipient@email.com", "Failure event detected at " + dateTime);
    }

    public void sendMessage(String mailFrom, String subject, String mailTo, String message) {
        SimpleMailMessage simpleMailMessage = new SimpleMailMessage();
        simpleMailMessage.setFrom(mailFrom);
        simpleMailMessage.setSubject(subject);
        simpleMailMessage.setTo(mailTo);
        simpleMailMessage.setText(message);
        mailTemplate.send(simpleMailMessage);
    }
}

As you can see, the email add-on provides a completely implemented “sendMessage” method which now just needs to be called when we wish to send an email over SMTP.

To test the application simply quit the Roo shell, type “mvn tomcat:run” and go to http://localhost:8080/vote to test the application. There you should try to create a number of authentication failure in quick succession while monitoring the console for messages. Finally, if you have configured email correctly and you have caused the Spring Security listener to send a JMS message, and the JMS consumer to send a SMTP message via your Gmail account.

To monitor ActiveMQ via JMX, the Roo JMS addon enables JMX support by default. This allows you to run up JConsole against the following URI:

$ jconsole service:jmx:rmi:///jndi/rmi://localhost:1099/jmxrmi

Conclusion

In this post I have shown how to extend the Spring Roo name voting application to be aware of brute force attacks against the application backend. This was achieved by implementing a simple security listener. If an event was detected, a message is being sent to a in-memory JMS topic. JMS was chosen to achieve decoupling as it allows for potentially slow running email sending operations as well as outsourcing the email sending part of the application to increase application scalability. It also gives us more flexibility in that alternate JMS consumers could be implemented in a manner that is decoupled from the security listener.

This blog has also demonstrated the use of the new JMS and email add-ons. I’m still working on improving these add-ons, both of which first appeared in Roo 1.0.0.M1. Please feel free to provide suggestions and feedback on your experience using them (or Roo more generally) via the community support forum, Jira issue tracker and our other project resources. You can also read Ben’s blog entry on the Roo 1.0.0.M1 release and how to build a wedding RSVP application, or follow us on Twitter.

  • Share/Bookmark

12 Responses Subscribe to comments


  1. Gabriel Pop

    Hi Stefan,

    Adding

    into appSecurity.xml file under the tag is not enough. I am still able to access the “create new choice” or “create new vote” links and edit pages appear. Am I missing something here ?
    Thank you in advance.
    Gabriel

    Jun 20, 2009 @ 02:23


  2. sschmidt

    Hi Gabriel,

    The pages appear because the form itself is not (yet) protected. If you try submitting it the security login form should be presented. To secure the form as well you have several options:

    1. protect the /vote/form URL via the Spring Security application context.
    2. hide the menu item from unauthorized users (see http://stsmedia.net/spring-finance-part-6-spring-security-3-integration/ for more details)
    3. add security annotations to the form method in the vote/choice controllers

    Hope this helps.

    -Stefan

    Jun 20, 2009 @ 09:42


  3. vennela

    I am tough time with spring security, user managment. how do i make it store in database and create CRUD operations on them…

    Aug 11, 2009 @ 06:53


  4. Stefan Schmidt

    @vennela,

    Well you can easily use Roo to manage your users using the common CRUD conventions. There is also the ‘install security’ command to install Spring Security artifacts. Then in the security application context you could connect to the user table in your db using the jdbc-user-service tag. For details you can check out the Spring Finance Manager example application developed by me: http://bit.ly/2TLZnE

    HTH,
    Stefan

    Aug 11, 2009 @ 19:15


  5. vennela

    Hi Stefan,

    Thanks for pointing me to correct direction.

    Vennela

    Aug 12, 2009 @ 04:45


  6. vennela

    Hi Stefan,

    I came accross following serive objects that will update Authority and Person tables. do we have any commands in ROO to generate service objects.
    AuthorityService.java
    PersonService.java

    Right now i am confused. whether to start working with ROO or use both create some things manually or user ROO.

    Help me!!

    Vennela

    Aug 12, 2009 @ 06:02


  7. Stefan Schmidt

    @vennela,

    Applications generated with Spring Roo and the current FinanceManager application have some differences in their layering. The FinanceManager application uses a service layer and a repository / DAO layer which know from traditional applications. Roo generated applications can live without those layers as the usual CRUD functionalities are woven into the domain objects via aspects. The functionality remains the same in the end.

    You can however, still implement your own service layer in Roo should you feel the need for it via the ‘new java file command’. Then you would need to implement your custom functionality in there since Roo cannot guess what exactly you need.

    HTH
    -Stefan

    Aug 16, 2009 @ 16:42


  8. Bin

    Hi Stefan,

    Could you detail advantages/disadvantages of using “CRUD functionalities are woven into the domain objects via aspects.” versus “service layer and a repository / DAO layer”?

    I want to know in real world if this “wovened” domain objects infrastructure can replace “traditional” service/repository layer seems it is easier/cleaner to code. Any strong suggestion on using “wovened” domain objects without tranditonal layers?

    thanks
    Bin

    Dec 07, 2009 @ 05:15


  9. Mike H

    Hi Stefan,

    This all seems very exciting. However, when following your instructions I’m finding that the command

    new java file -name ~.security.BackendAccessListener

    fails… in fact if I push tab twice (for help) the ‘new’ command isn’t one of the options listed.

    Any ideas what the problem is here please?

    Mike H

    Jan 19, 2010 @ 02:58


  10. Stefan Schmidt

    Hi Mike,

    We have changed the commands shown in this article. All commands now start with the resource they affect. So in your case you should be looking for the ‘class’ command. Please use ‘help’ or tab completion in the Roo shell to learn about available commands.

    The Roo documentation has also extensive information about all commands and their purpose: http://static.springsource.org/spring-roo/reference/html/command-index.html

    HTH,
    Stefan

    Jan 31, 2010 @ 17:21


  11. AK

    Stefan,

    A post explaining how spring security works with gwt in roo will be really appreciated.

    I’m trying to add a field to an entity created using roo that can store a (google) User type object but there is no documentation or sample available anywhere that explains how this can be done.

    Since this is a basic requirement for almost any web application, a basic tutorial will be very useful.

    Nov 05, 2010 @ 13:47


  12. Stefan Schmidt

    This is something that needs to be provided in the Roo documentation rather than here (this article is about Roo + MVC + Security, not GWT). Please raise an improvement ticket in the Roo Jira for GWT + Security docs.

    Nov 05, 2010 @ 18:14

Reply