Writing the MBean implementation

Every Authentication Provider must implement the weblogic.security.spi.AuthenticationProviderV2 interface, which is the real contract between WebLogic's Security Services and our implementation, as shown in the following code snippet:

public class PacktAuthProviderImpl implements AuthenticationProviderV2

{
    private static final Logger LOGGER = Logger.getLogger(PacktAuthProviderImpl.class.getSimpleName());

    @Override
    public void initialize(ProviderMBean mbean, SecurityServices services) {
        LOGGER.info("PacktAuthProviderImpl.initialize");
    }

    @Override
    public String getDescription() {
        return null;
    }

    @Override
    public void shutdown() {
        LOGGER.info("PacktAuthProviderImpl.shutdown");
    }

    @Override
    public AppConfigurationEntry getLoginModuleConfiguration() {
        return null;
    }

    @Override
    public AppConfigurationEntry getAssertionModuleConfiguration() {
        return null;
    }

    @Override
    public PrincipalValidator getPrincipalValidator() {
        return null;
    }

    @Override
    public IdentityAsserterV2 getIdentityAsserter() {
        return null;
    }
}

And yes, now you can install and configure the provider in your domain; you will see the following single line of log:

net.lucamasini.security.PacktAuthProviderImpl initialize
INFO: PacktAuthProviderImpl.initialize

It's not much, but it means that our configuration and infrastructure is working fine. From now on, finally, we will really code there, giving behavior to the PacktAuthProviderImpl class that WebLogic now knows is a custom provider.

Initializing the provider

Every framework has its own lifecycle, and every lifecycle has a start and an end. For AuthenticationProviderV2 these are the callback methods initialize and shutdown, where we can not only eventually instantiate our custom objects but also grab configuration from the MBean that wraps our class and communicates with the console. In this simple implementation, we don't need to do anything inside shutdown, so we'll leave the current one that logs a line when it is called.

Instead, a lot must be done inside the initialize method, where we receive the MBean instance and the Security Service, which is our actual container. The first thing we need to do is cast the generic ProviderMBean to our custom MBean so that we can use our specific attributes, as follows:

PacktSiteUsersAuthenticationMBean myMBean = (PacktSiteUsersAuthenticationMBean) mbean;

Now that we have our specific instance, we can save the configuration for later use using the following code snippet:

description = myMBean.getDescription() + "
" + myMBean.getVersion();
url = myMBean.getURL();

Here description and url are two instance string fields. We also need to save an instance of AppConfigurationEntry.LoginModuleControlFlag, which is a JAAS version of an enum type (old style Java) that tells us if our Security Provider is mandatory or not. This can be done as follows:

String flag = myMBean.getControlFlag();
try {
controlFlag =(AppConfigurationEntry.LoginModuleControlFlag) 
AppConfigurationEntry.LoginModuleControlFlag.class.getField(flag).get(null);
} catch (Exception e) {
   throw new IllegalArgumentException("invalid flag value" + flag,e);
}

In this first stage, we can print the configuration output on WebLogic's Server log so that we can be sure that we call the correct parameter and our simple parsing code is working fine. Use the following code:

LOGGER.info("ControlFlag: "+controlFlag);
LOGGER.info("Description: "+description);
LOGGER.info("URL: "+url);

We should see something like the following:

INFO: ControlFlag: LoginModuleControlFlag: optional
INFO: Description: WebLogic Packt Authentication Provider
1.0
INFO: URL: http://external-user.intra.net/checkUserLogin

Implementation of the provider

Our implementation is almost finished; we now need to implement the remaining method, getDescription. This is quite straightforward, as shown in the following code:

@Override
public String getDescription() {
  return description;
}

While getIdentityAsserter will continue to return null (as we are coding an Authentication Provider), we still need to implement the Principal Validator, and for that we can use a built-in validator that comes with WebLogic, as shown in the following code snippet:

@Override
public PrincipalValidator getPrincipalValidator() {
  return new 
    weblogic.security.provider.PrincipalValidatorImpl();
}

Finally, the configuration of JAAS LoginModule, which will actually do the authentication. We will not use any standard LoginModule, rather we will use our own:

@Override
public AppConfigurationEntry getLoginModuleConfiguration() {
  return new AppConfigurationEntry(
     "net.lucamasini.security.PacktLoginModuleImpl",
   	controlFlag,
     new HashMap<String, Object>() {{
   	  put("url", url);
     }}
   );
}

@Override
public AppConfigurationEntry getAssertionModuleConfiguration() {
  return getLoginModuleConfiguration();
}

We can now install and start WebLogic. Strangely, it will not complain about the fact that the PacktLoginModuleImpl class is missing; it will merely ignore this Authentication Provider during the login process. This can be seen as an error, but it is a good and conservative practice and in case we want/need to check if our configuration has been read correctly, we can always enable the atn debug flag by going to weblogic.security.atn in the console or start up script and look for PacktLoginModuleImpl.

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

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