You can develop a JACC provider to have custom authorization
decisions for Java™ Platform,
Enterprise Edition (J2EE) applications by implementing the com.ibm.wsspi.security.authorization.jacc.ProviderService interface
that is provided in the Liberty server.
Before you begin
By default, the application module loading is deferred
until the request to the application is being processed, however the
security constraint of the entire module in the application needs
to be processed before the application is ready to be processed. The
deferred module loading needs to be disabled. The following shows
you how to disable it:
- For the WebContainer:
In the
server.xml file,
the following element needs to be set:
<webContainer deferServletLoad="false"/>
- For the EJBContainer:
In the
server.xml file,
the following element needs to be set:
<ejbContainer startEJBsAtAppStart="true"/>
Note: If the previous elements are not set, the complete
security constraint information may not be propagated to the third
party JACC provider upon starting the server. As a result, the correct
authorization decision may not be enforced by the third party JACC
provider.
About this task
The Java Authorization
Contract for Containers specification, JSR 115, defines an interface for authorization
providers. In the Liberty server, you must package your JACC
provider as a user feature. Your feature must implement the com.ibm.wsspi.security.authorization.jacc.ProviderService interface.
Procedure
- Create an OSGi component that provides a service that implements
the com.ibm.wsspi.security.authorization.jacc.ProviderService interface.
The ProviderService interface defines two
methods, getPolicy, which the Liberty server run
time invokes to retrieve an instance of your Policy class that implements
thejava.security.Policy abstract class, and getPolicyConfigFactory,
which the Liberty server run time invokes to retrieve an instance
of your PolicyConfigurationFactory class that implements
the javax.security.jacc.PolicyConfigurationFactory abstract
class.
The following example uses OSGi declarative services
annotations:
package com.mycompany.jacc;
import com.mycompany.jacc.MyAuthConfigProvider;
import com.ibm.wsspi.security.authorization.jacc.ProviderService;
import java.security.Policy;
import java.util.Map;
import javax.security.jacc.PolicyConfigurationFactory;
import org.osgi.service.component.ComponentContext;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Deactivate;
// The property value of javax.security.jacc.policy.provider which defines the implementation class of Policy and
// javax.security.jacc.PolicyConfigurationFactory.provider which defines the implementation class of PolicyConfigurationFactory, are required for propagating the properties to the Liberty runtime.
@Component(service = ProviderService.class,
immediate = true,
property = {
"javax.security.jacc.policy.provider=com.myco.jacc.MyPolicy",
"javax.security.jacc.PolicyConfigurationFactory.provider="
+ "com.myco.jacc.MyFactoryImpl"
}
)
public class MyJaccProviderService implements ProviderService {
Map<String, String> configProps;
// This method called by the Liberty runtime
// to get an instance of Policy class
@Override
public Policy getPolicy() {
return new myPolicy();
}
// This method called by the Liberty runtime
// to get an instance of PolicyConfigurationFactory class
@Override
public PolicyConfigurationFactory getPolicyConfigurationFactory() {
ClassLoader cl = null;
PolicyConfigurationFactory pcf = null;
System.setProperty(
"javax.security.jacc.PolicyConfigurationFactory.provider",
"com.myco.jacc.MyFactoryImpl");
try {
cl = Thread.currentThread().getContextClassLoader();
Thread.currentThread().setContextClassLoader(
this.getClass().getClassLoader());
pcf = PolicyConfigurationFactory.getPolicyConfigurationFactory();
} catch (Exception e) {
return null;
} finally {
Thread.currentThread().setContextClassLoader(cl);
}
return pcf;
}
@Activate
protected void activate(ComponentContext cc) {
// Read provider config properties here if needed,
// then pass them to the Provider ctor.
// This example reads the properties from the OSGi
// component definition.
configProps = (Map<String, String>) cc.getProperties();
}
@Deactivate
protected void deactivate(ComponentContext cc) {}
}
- Package the component into an OSGi bundle that is part
of your user feature, along with your JACC provider.
- Ensure that your feature includes the OSGi subsystem content:
com.ibm.ws.javaee.jacc.1.5; version="[1,1.0.100)"; location:="dev/api/spec/".
- After the feature is installed into the user product extension
location, configure the server.xml file with
the feature name. For example:
<featureManager>
...
<feature>usr:myJaccProvider</feature>
</featureManager>