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 property
needs to be set:
<ejbContainer startEJBsAtAppStart="true"/>
Note: If
the previous elements are not set, the complete security constraint information might not be
propagated to the third-party JACC provider upon starting the server. As a result, the correct
authorization decision might 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. The
getPolicy
method, which the Liberty run time invokes to retrieve an instance
of your Policy class that implements thejava.security.Policy
abstract class. Also,
the getPolicyConfigFactory
method, which the Liberty 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>