Recently, I mentioned how I had just started working with the JBoss Seam application framework.
The more I have worked with it, the more impressed I have become at how
it makes things that are typically difficult using standard Java EE
much simpler and more streamlined. One of the areas in which Seam
really shines is security. While Java EE defines JAAS
for use in securing applications, it is left up to the developer to
ingrain this security down to each facet of the application. With Seam,
it is easy to define security constraints at all levels of an
application, simply through using annotations. In addition, the
complexity of authenticating users with JAAS is reduced through Seam's authenticator mechanism. This article will give an introduction to Seam authentication, and show how to write your own custom authenticator.
Seam's
authenticator construct hides the complexity of managing a JAAS
configuration, and allows you to implement authentication how you see
fit. Perhaps your organization relies on a simple username/password
combination for authenticating user accounts in LDAP. Maybe you use a
SecureID token, and the accounts are stored in a SQL database. By
writing your own authenticator class, or making use of publicly
available ones, you can control the way authentication is done in your
organization.
To get started with your own authenticator, you must first declare it in the components.xml
file. This file manages much of the configuration for Seam. To add your
authenticator, you simply define the class and method that will be used
for authentication. For example:
- <components xmlns="http://jboss.com/products/seam/components"
- xmlns:core="http://jboss.com/products/seam/core"
- xmlns:security="http://jboss.com/products/seam/security"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation=
- "http://jboss.com/products/seam/components http://jboss.com/products/seam/components-2.0.xsd
- http://jboss.com/products/seam/security http://jboss.com/products/seam/security-2.0.xsd">
-
- <security:identity method="#{authenticator.authenticate}">
-
- </components>
You'll notice the #{} syntax used here. This is JBoss' expression language pointing to a class with the instance name of
authenticator, where the
authenticate
method will be used to login a user. Now that we have declared an
authenticator to Seam, we're ready to implement it. Our example will be
quite simple. If the user enters a username of
admin, with a password of
password, they will be authenticated successfully. In addition, we will assign them to the role of
admin,
so that they can perform some sort of administrative function within
our application. The implementation of our authenticator would look
like this:
- @Name("authenticator")
- public class Authenticator {
-
- private static final String valid_user = "admin";
- private static final String valid_password = "password";
-
- public boolean authenticate() {
- String username = Identity.instance().getUsername();
- String password = Identity.instance().getPassword();
-
- if((username.equals(valid_user)) && (password.equals(valid_password))) {
- return true;
- }
-
- return false;
- }
-
- }
Our
example is rather trivial. However, it gives a slight glimpse into how
Seam authentication works. The first thing that you should notice is
the
@Name
annotation. This annotation prompts Seam to create a bean with the name
specified in the annotation. In this case, the name is
authenticator, which is how we arrive at the value specified in our
components.xml file. Our
authenticate method will return
true if authentication was successful, and
false otherwise.
So how does the authenticate method get the username and password? This is done via the Identity class. The standard
Identity
class that comes with Seam is quite extensive, but basically provides
support for a username/password combination. It is possible to subclass
Identity,
however, to support whatever authentication mechanisms you may need.
You could implement code to support getting a SecureID token value from
a user, or a SPNEGO ticket. All that is needed to make use of the
Identity subclass is to add the following annotations to your implementation:
- @Name("org.jboss.seam.security.identity")
- @Scope(SESSION)
- @Install(precedence = APPLICATION)
- @BypassInterceptors
- @Startup
- public class MyCustomIdentity extends Identity
- { ... }
Your custom
Identity subclass is now ready for use.
Now
that we have our authentication classes in place, we are ready to
create our login form. This is trivial to create using Seam,
particularly because of Seam's use of the JBoss expression language in
forms. Our login form fragment would look like the following:
- <div>
- <h:outputlabel for="name" value="Username">
- <h:inputtext id="name" value="#{identity.username}">
- </div>
-
- <div>
- <h:outputlabel for="password" value="Password">
- <h:inputsecret id="password" value="#{identity.password}">
- </div>
-
- <div>
- <h:commandbutton value="Login" action="#{identity.login}">
- </div>
That's
all there is to it. You are now ready to authenticate users via your
own custom login form and authenticator. While this is an introduction
to the simplified form of authentication in Seam, it should give you a
good foundation to learn and explore on your own.
Next time, we will look at how authentication is used throughout an application, not just at the entry point.