5.4. Leveraging Spring Security

Spring has a very flexible and robust set of framework components that help implement sophisticated security profiles and constraints, including the most commonly used authentication and authorization patterns. In standard BlazeDS, security is typically delegated to the underlying container in which BlazeDS is deployed.

Spring BlazeDS provides an alternative mechanism for implementing security other than that provided by standard BlazeDS. If Spring is your primary server-side framework, leveraging Spring security with your Flex and Spring application is a good idea.

In the simplest case, you can define a role-based login using in-memory definitions. A configuration for such a simple in-memory definition is:

<authentication-provider>
    <user-service>
        <user name="admin" password="secret" authorities="ROLE_ADMIN,ROLE_USER" />
        <user name="aUser" password="somePassword" authorities="ROLE_USER" />
        <user name="anotherUser" password="someOtherPassword" disabled="true"
        authorities="ROLE_USER" />
    </user-service>
</authentication-provider>

This configuration could be better organized by externalizing the user-service content to a file, say users.properties, that could be located in the WEB-INF/config folder. The configuration would then be as follows:

<authentication-provider>
    <user-service properties="/WEB-INF/config/users.properties" />
</authentication-provider>

Alternatively and more likely in most enterprise applications, the security will be more complicated than a few entries inline or in a file. Also, you may want to restrict access and thereby avoid having any credentials defined in files that are deployed with the application. A possible alternative could be keeping security profiles in the database.

Spring has built-in support for database-based authentication. Spring relies on the following default SQL queries to access the security definition:

SELECT username, password, enabled
FROM users
WHERE username = ?

SELECT username, authority
FROM authorities
WHERE username = ?

If you choose to use database-based authentication, with the default queries as specified previously, do not forget to create the users and authorities tables using the following Data Definition Language (DDL) statements:

CREATE TABLE USERS (
    USERNAME VARCHAR(10) NOT NULL,
    PASSWORD VARCHAR(32) NOT NULL,
    ENABLED SMALLINT,
    PRIMARY KEY (USERNAME)
);

CREATE TABLE AUTHORITIES (
    USERNAME VARCHAR(10) NOT NULL,
    AUTHORITY VARCHAR(10) NOT NULL,
    FOREIGN KEY (USERNAME) REFERENCES USERS
);

To use database-driven authentication in Spring BlazeDS, first configure a data source to connect to your database and then reference that data source as the value of the data-source attribute of the jdbc-user-service element. The jdbc-user-service is the authentication-provider in this case. A configuration for the data source and then the authentication provider are as follows:

<bean id="dataSource"
    class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    <property name="driverClassName"
        value="<Specify the JDBC driver class name here>" />
    <property name="url"
        value="<Specify the database access URL here>" />
    <property name="username" value="<Specify the user name here>" />
    <property name="password" value="<specify the password here>" />
</bean>

<authentication-provider>
    <jdbc-user-service data-source-ref="dataSource" />
</authentication-provider>

To configure an authentication provider with Spring BlazeDS, also configure an HTTP entry point reference as follows:

<http entry-point-ref="preAuthenticatedEntryPoint" />
<beans:bean id="preAuthenticatedEntryPoint"
   class="org.springframework.security.ui.preauth.
   PreAuthenticatedProcessingFilterEntryPoint" />

After this preliminary initial configuration, you are ready to configure security for the BlazeDS MessageBroker. The simplest such definition is:

<flex:message-broker>
    <flex:secured />
</flex:message-broker>

Like other configurations you have seen so far, a single line, <flex:secured>, achieves quite a bit. Again, convention is preferred over configuration and defaults are relied upon. BlazeDS implements authentication using the LoginCommand. Spring BlazeDS with the minimal configuration includes a custom LoginCommand implementation that combines ChannelSet.login and ChannelSet.logout with the Spring security definitions. In addition, it also makes the security definitions available within the Spring BlazeDS configuration elements defined by Spring-flex-1.0.0.xsd.

Standard security constraints can be defined within BlazeDS destinations as usual. When they are configured with Spring security, the underlying Spring BlazeDS LoginCommand is used for authentication.

While this style of authentication is easy to use, it provides less flexibility in terms of access to the response data from the authentication requests. Sometimes, though, programmatic access to authentication data can be used to drive role-based access control within the Flex application. In such cases, you may want to explicitly call the ChannelSet.login method and pass in the login credentials. Such a method is asynchronous, like most methods in Flex. You can set a responder for this call. On response, you can match the user credentials from the authorities and take appropriate action.

Next, I will cover a few examples that illustrate various ways of securing the Spring BlazeDS remoting destination.

5.4.1. Securing Remote Spring Bean Access

There are multiple ways to secure access to Spring BlazeDS destinations. Let's revisit the BookService example from the section on remoting to Spring beans. In that example, the BookService had five methods to support CRUD operations on a books catalog. The five methods were:

  • findAll

  • findById

  • create

  • update

  • remove

If you had to restrict access to these methods based on the logged-in user's role, you could set up a security constraint as follows:

<bean id="bookService" class="problazeds.ch05.BookService">
    <flex:remoting-destination/>
    <security:intercept-methods>
        <security:protect method="find*" access="ROLE_USER" />
        <security:protect method="create" access="ROLE_ADMIN,ROLE_USER" />
        <security:protect method="update" access="ROLE_ADMIN" />
        <security:protect method="remove" access="ROLE_ADMIN" />
    </security:intercept-methods>
</bean>

It's also possible to define such security constraints using annotations instead of XML. As an example, you could secure the remove method and only allow access to ROLE_ADMIN as follows:

@Secured("ROLE_ADMIN")
public boolean remove(Book item);

However, if you wanted to instead provide access to all methods of all classes, defined within the problazeds.ch05 package, then you could rely on a configuration like this:

<global-method-security>
    <protect-pointcut
        expression="execution(* problazeds.ch05.*(..))"
        access="ROLE_USER"/>
</global-method-security>

Spring security is very flexible and is handy for multiple types of security definition implementations. As a case in point, instead of defining security for classes or their methods, you may have a situation where you want to restrict access by channel type. For example, all your remoting destinations may use the my-amf channel, and all your messaging destinations may use the my-polling-amf channel. Now you may allow users who are logged in as ROLE_USER to access all destinations on my-amf but may restrict access to all my-polling-amf to only those users who are logged in as ROLE_ADMIN. One such case may be that the near real-time updates are sending monitoring data that only users with ROLE_ADMIN need to use.

Such a security configuration is:

<flex:message-broker>
    <flex:secured>
        <flex:secured-channel channel="my-amf" access="ROLE_USER" />
        <flex:secured-channel channel="my-polling-amf" access="ROLE_ADMIN" />
    </flex:secured>
</flex:message-broker>

You could also set up Spring security for all channels whose URL matches a particular pattern. This could be configured like so:

<flex:message-broker>
    <flex:secured>
        <flex:secured-endpoint-path
            pattern="**/messagebroker/amf**"
            access="ROLE_USER" />
    </flex:secured>
</flex:message-broker>

So far I have covered a few examples where Spring security provides an extensible and flexible way of defining security. Spring security itself has many more features, but they are not discussed in this chapter. You may benefit from reading more on the Spring framework to better understand its features.

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

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