Stephen Chin is a technical expert in RIA technologies, and Chief Agile Methodologist at GXS. He coauthored the Apress Pro JavaFX Platform title, which is the leading reference for JavaFX, and is lead author of the Pro Android Flash title. In addition, Stephen runs the very successful Silicon Valley JavaFX User Group, which has hundreds of members and tens of thousands of online viewers, and also is co-organizer for the Flash on Devices User Group. Finally, he is a Java Champion, chair of the OSCON Java Conference and an internationally recognized speaker featured at Devoxx, Jazoon and JavaOne, where he received a Rock Star Award. Steve can be followed on twitter @steveonjava and reached via his blog http://steveonjava.com Stephen is a DZone MVB and is not an employee of DZone and has posted 30 posts at DZone. You can read more from them at their website. View Full User Profile

JavaFX in Spring Day 3 – Authentication and Authorization

09.06.2012
| 5439 views |
  • submit to reddit

Welcome to Day 3 of the JavaFX in Spring blog series. In this post we are going to finish off the Customer Data application by taking advantage of the Spring Security APIs on the client.

It took a little bit of hacking, but I got a GitHub project put together with a straightforward JavaFX Maven build (details on this in a future post) to run everything. Please give the full project a view and run it from source so you can experiment with the application as you read this post:

Browse Project on GitHub

For easy reference, you can flip to any of the blogs here:

Since my last post I made it out to two additional user groups in Texas, and had a great time speaking at both:

On the left is the Austin JUG, which is a large, well-established user group and on the right is the Houston JUG, which had a unique venue with personal monitors for all the attendees (this would be a great setup for a lab in the future!)  I posted the talks on Hacking JavaFX with Groovy, Clojure, Scala, and Visage and JavaFX 2 – A Java Developer’s Guide to SlideShare so they can grab the full presentation decks.

Getting back to the JavaFX in Spring example, in the last blog we covered Spring configuration of a JavaFX app to modularize the screens. As a simple example we did an error dialog to show how FXML ties in, but now let’s create a login page to demonstrate using Spring Security for Authentication.

The login dialog was created visually in SceneBuilder and the final version ended up looking like this:

(Since the first post I added in a few convenience hyperlinks for logging in as an employee or a manager)

And the controller code is as follows:

public class LoginController implements DialogController {
    @Autowired
    private AuthenticationManager authenticationManager;
    @Autowired
    private ScreensConfiguration screens;
    private AutowireFXMLDialog dialog;
 
    public void setDialog(AutowireFXMLDialog dialog) {
        this.dialog = dialog;
    }
 
    @FXML
    Label header;
    @FXML
    TextField username;
    @FXML
    TextField password;
 
    @FXML
    public void login() {
        Authentication authToken = new UsernamePasswordAuthenticationToken(username.getText(), password.getText());
        try {
            authToken = authenticationManager.authenticate(authToken);
            SecurityContextHolder.getContext().setAuthentication(authToken);
        } catch (AuthenticationException e) {
            header.setText("Login failure, please try again:");
            header.setTextFill(Color.DARKRED);
            return;
        }
        dialog.close();
        screens.showScreen(screens.customerDataScreen());
    }
 
    @FXML
    public void employee() {
        username.setText("employee");
        password.setText("lol");
    }
 
    @FXML
    public void manager() {
        username.setText("manager");
        password.setText("password");
    }
}

The important part for authentication is taken care of in the login method. This grabs the username and password from the respective fields and creates a new UsernamePasswordAuthenticationToken. To force authentication to take place immediately, we get autowire a reference to the Spring AuthenticationManager and call the authenticate method. If the user exists in our credential store the method will succeed, otherwise it will throw an AuthenticationError we catch in the enclosing try block.

For the purpose of this example we are using a local authentication store in the Spring XML config. You could easily hook up to an LDAP server or your chioce of authentication engines, but this makes the sample app we are building self contained. Here is the Spring config XML:

<?xml version="1.0" encoding="UTF-8"?>
 
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:security="http://www.springframework.org/schema/security"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
             http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd">
    <security:global-method-security secured-annotations="enabled"/>
    <security:authentication-manager>
        <security:authentication-provider>
            <security:password-encoder hash="plaintext"/>
            <security:user-service>
                <security:user name="manager" password="password" authorities="ROLE_MANAGER"/>
                <security:user name="employee" password="lol" authorities="ROLE_EMPLOYEE"/>
            </security:user-service>
        </security:authentication-provider>
    </security:authentication-manager>
</beans>

This sets up two different users and two roles. One is our manager who will have full access to the system and a laughably weak password, and the second is the employee who will only only have access to create new customers, but not delete. We are going to take advantage of these roles to secure the customer creation and deletion routines using annotation-based authorization.

Now that annotations-based configuration is setup, you can secure methods in your application by simply adding an appropriate annotation to it as shown in this code snippet from CustomerModel:

@Secured("ROLE_MANAGER")
public void remove(Customer customer) {
    restTemplate.delete("http://localhost:8080/crm/customer/" + customer.getId());
    customers.remove(customer);
}

Any time this method is called, you will get an exception thrown that will prevent that method from getting executed and can be caught to give good user feedback, such as an error dialog:

To finish off the example, here is a screenshot of the completed example that includes a JavaFX Table for displaying elements that are pulled back from the server using the Spring RestTemplate API:

And again, you can find the full code available for download here:
Browse Project on GitHub

Now that I have shown you how you can take advantage of Spring in your JavaFX applications, it is only fair to point out some of the shortcomings you may encounter:

  • Jar Explosion – I tried to be minimalistic in my inclusion of dependencies, but still ended up with dozens of jar files for this example application. This may be an issue if you are deploying to resource constrained devices or over a thin network pipe, but for packaged applications should not be an issue.
  • All Permissions Required – Since Spring makes heavy use of aspect-oriented programming (AOP) libraries that manipulate bytecode, you won’t be able to run this application in the Java sandbox. The best approach is to request all permissions and code sign your application so the end user just gets prompted once.
  • AOP Glitches – In your own applications you will trip across various little quirks with AOP and bytecode manipulation that can make client programming quite hazardous. For example, if you put an @Secured annotation in a UI class file loaded in the main thread, you will get a ClassCastException on the proxy. It is possible to get the target class out like this, but it is nefarious enough that it bit me in a live-coding presentation.

Hopefully you have learned a little bit through this tour of JavaFX and Spring integration. I would love to hear what other folks have been doing to integrate these technologies in the comments section below.

 

 

 

 

 

Published at DZone with permission of Stephen Chin, author and DZone MVB. (source)

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)