Oracle GlassFish Server Application Development Guide Release 3.1.2 Part Number E24930-01 |
|
|
View PDF |
This chapter describes how to write secure Java EE applications, which contain components that perform user authentication and access authorization for the business logic of Java EE components.
For information about administrative security for the Oracle GlassFish Server, see the Oracle GlassFish Server Security Guide.
For general information about Java EE security, see "Security" in The Java EE 6 Tutorial.
The following topics are addressed here:
Note:
The Web Profile of the GlassFish Server supports the EJB 3.1 Lite specification, which allows enterprise beans within web applications, among other features. The full GlassFish Server supports the entire EJB 3.1 specification. For details, see JSR 318.
In an enterprise computing environment, there are many security risks. The goal of the GlassFish Server is to provide highly secure, interoperable, and distributed component computing based on the Java EE security model. Security goals include:
Full compliance with the Java EE security model. This includes EJB and servlet role-based authorization.
Support for single sign-on across all GlassFish Server applications within a single security domain.
Support for web services message security.
Security support for application clients.
Support for several underlying authentication realms, such as simple file and Lightweight Directory Access Protocol (LDAP). Certificate authentication is also supported for Secure Socket Layer (SSL) client authentication. For Solaris, OS platform authentication is supported in addition to these.
Support for declarative security through GlassFish Server specific XML-based role mapping.
Support for Java Authorization Contract for Containers (JACC) pluggable authorization as included in the Java EE specification and defined by Java Specification Request (JSR) 115.
Support for Java Authentication Service Provider Interface for Containers as included in the Java EE specification and defined by JSR 196.
Support for Web Services Interoperability Technologies (WSIT) as described in Metro Users Guide.
The GlassFish Server supports the Java EE security model, as well as the following features which are specific to the GlassFish Server:
Message security; see Configuring Message Security for Web Services
Single sign-on across all GlassFish Server applications within a single security domain; see User Authentication for Single Sign-on
Programmatic login; see Programmatic Login
The component containers are responsible for providing Java EE application security. The container provides two security forms:
Annotations (also called metadata) enable a declarative style of programming, and so encompass both the declarative and programmatic security concepts. Users can specify information about security within a class file using annotations. When the application is deployed, this information can either be used by or overridden by the application or module deployment descriptor.
Declarative security means that the security mechanism for an application is declared and handled externally to the application. Deployment descriptors describe the Java EE application's security structure, including security roles, access control, and authentication requirements.
The GlassFish Server supports the deployment descriptors specified by Java EE and has additional security elements included in its own deployment descriptors. Declarative security is the application deployer's responsibility. For more information about GlassFish Server deployment descriptors, see the Oracle GlassFish Server Application Deployment Guide.
There are two levels of declarative security, as follows:
For an application, roles used by any application must be defined in @DeclareRoles
annotations in the code or role-name
elements in the application deployment descriptor (application.xml
). Those role names are scoped to the EJB XML deployment descriptors (ejb-jar.xml
and glassfish-ejb-jar.xml
files) and to the servlet XML deployment descriptors (web.xml
and glassfish-web.xml
files). For an individually deployed web or EJB module, you define roles using @DeclareRoles
annotations or role-name
elements in the Java EE deployment descriptor files web.xml
or ejb-jar.xml
.
To map roles to principals and groups, define matching security-role-mapping
elements in the glassfish-application.xml
, glassfish-ejb-jar.xml
, or glassfish-web.xml
file for each role-name
used by the application. For more information, see Roles, Principals, and Principal to Role Mapping.
Component level security encompasses web components and EJB components.
A secure web container authenticates users and authorizes access to a servlet or JSP by using the security policy laid out in the servlet XML deployment descriptors (web.xml
and glassfish-web.xml
files).
The EJB container is responsible for authorizing access to a bean method by using the security policy laid out in the EJB XML deployment descriptors (ejb-jar.xml
and glassfish-ejb-jar.xml
files).
Programmatic security involves an EJB component or servlet using method calls to the security API, as specified by the Java EE security model, to make business logic decisions based on the caller or remote user's security role. Programmatic security should only be used when declarative security alone is insufficient to meet the application's security model.
The Java EE specification defines programmatic security as consisting of two methods of the EJB EJBContext interface and two methods of the servlet HttpServletRequest interface. The GlassFish Server supports these interfaces as specified in the specification.
For more information on programmatic security, see the following:
The Java EE Specification
For applications, you define roles in @DeclareRoles
annotations or the Java EE deployment descriptor file application.xml
. You define the corresponding role mappings in the GlassFish Server deployment descriptor file glassfish-application.xml
. For individually deployed web or EJB modules, you define roles in @DeclareRoles
annotations or the Java EE deployment descriptor files web.xml
or ejb-jar.xml
. You define the corresponding role mappings in the GlassFish Server deployment descriptor files glassfish-web.xml
or glassfish-ejb-jar.xml
.
For more information regarding Java EE deployment descriptors, see the Java EE Specification. For more information regarding GlassFish Server deployment descriptors, see "Elements of the GlassFish Server Deployment Descriptors" in Oracle GlassFish Server Application Deployment Guide.
Each security-role-mapping
element in the glassfish-application.xml
, glassfish-web.xml
, or glassfish-ejb-jar.xml
file maps a role name permitted by the application or module to principals and groups. For example, a glassfish-web.xml
file for an individually deployed web module might contain the following:
<glassfish-web-app> <security-role-mapping> <role-name>manager</role-name> <principal-name>jgarcia</principal-name> <principal-name>mwebster</principal-name> <group-name>team-leads</group-name> </security-role-mapping> <security-role-mapping> <role-name>administrator</role-name> <principal-name>dsmith</principal-name> </security-role-mapping> </glassfish-web-app>
A role can be mapped to either specific principals or to groups (or both). The principal or group names used must be valid principals or groups in the realm for the application or module. Note that the role-name
in this example must match the @DeclareRoles
annotations or the role-name
in the security-role
element of the corresponding web.xml
file.
You can also specify a custom principal implementation class. This provides more flexibility in how principals can be assigned to roles. A user's JAAS login module now can authenticate its custom principal, and the authenticated custom principal can further participate in the GlassFish Server authorization process. For example:
<security-role-mapping> <role-name>administrator</role-name> <principal-name class-name="CustomPrincipalImplClass"> dsmith </principal-name> </security-role-mapping>
You can specify a default principal and a default principal to role mapping, each of which applies to the entire GlassFish Server instance. The default principal to role mapping maps group principals to the same named roles. Web modules that omit the run-as
element in web.xml
use the default principal. Applications and modules that omit the security-role-mapping
element use the default principal to role mapping. These defaults are part of the Security Service, which you can access in the following ways:
In the Administration Console, select the Security component under the relevant configuration. For details, click the Help button in the Administration Console.
Use the asadmin set
command. For details, see the Oracle GlassFish Server Reference Manual. For example, you can set the default principal as follows.
asadmin set server-config.security-service.default-principal=dsmith asadmin set server-config.security-service.default-principal-password=secret
You can set the default principal to role mapping as follows.
asadmin set server-config.security-service.activate-default-principal-to-role-mapping=true asadmin set server-config.security-service.mapped-principal-class=CustomPrincipalImplClass
The following topics are addressed here:
The following realms are supported in the current release of the GlassFish Server:
file
- Stores user information in a file. This is the default realm when you first install the GlassFish Server.
ldap
- Stores user information in an LDAP directory.
jdbc
- Stores user information in a database.
In the JDBC realm, the server gets user credentials from a database. The GlassFish Server uses the database information and the enabled JDBC realm option in the configuration file. For digest authentication, a JDBC realm should be created with jdbcDigestRealm
as the JAAS context.
certificate
- Sets up the user identity in the GlassFish Server security context, and populates it with user data obtained from cryptographically verified client certificates.
solaris
- Allows authentication using Solaris username+password
data. This realm is only supported on the Solaris operating system, version 9 and above.
For information about configuring realms, see How to Configure a Realm.
You can configure a realm in one of these ways:
In the Administration Console, open the Security component under the relevant configuration and go to the Realms page. For details, click the Help button in the Administration Console.
Use the asadmin create-auth-realm
command to configure realms on local servers. For details, see the Oracle GlassFish Server Reference Manual.
The following deployment descriptor elements have optional realm
or realm-name
data subelements or attributes that override the domain's default realm:
glassfish-application
element in glassfish-application.xml
web-app
element in web.xml
as-context
element in glassfish-ejb-jar.xml
client-container
element in sun-acc.xml
client-credential
element in sun-acc.xml
If modules within an application specify realms, these are ignored. If present, the realm defined in glassfish-application.xml
is used, otherwise the domain's default realm is used.
For example, a realm is specified in glassfish-application.xml
as follows:
<glassfish-application> ... <realm>ldap</realm> </glassfish-application>
For more information about the deployment descriptor files and elements, see "Elements of the GlassFish Server Deployment Descriptors" in Oracle GlassFish Server Application Deployment Guide.
You can create a custom realm by providing a custom Java Authentication and Authorization Service (JAAS) login module class and a custom realm class. Note that client-side JAAS login modules are not suitable for use with the GlassFish Server.
To activate the custom login modules and realms, place the JAR files in the domain-dir/lib
directory or the class files in the domain-dir/lib/classes
directory. For more information about class loading in the GlassFish Server, see Class Loaders.
JAAS is a set of APIs that enable services to authenticate and enforce access controls upon users. JAAS provides a pluggable and extensible framework for programmatic user authentication and authorization. JAAS is a core API and an underlying technology for Java EE security mechanisms. For more information about JAAS, refer to the JAAS specification for Java SDK, available at http://www.oracle.com/technetwork/java/javase/tech/index-jsp-136007.html
.
For general information about realms and login modules, see "Working with Realms, Users, Groups, and Roles" in The Java EE 6 Tutorial.
For Javadoc tool pages relevant to custom realms, go to http://glassfish.java.net/nonav/docs/v3/api/
and click on the com.sun.appserv.security
package.
Custom login modules must extend the com.sun.appserv.security.AppservPasswordLoginModule
class. This class implements javax.security.auth.spi.LoginModule. Custom login modules must not implement LoginModule directly.
Custom login modules must provide an implementation for one abstract method defined in AppservPasswordLoginModule
:
abstract protected void authenticateUser() throws LoginException
This method performs the actual authentication. The custom login module must not implement any of the other methods, such as login
, logout
, abort
, commit
, or initialize
. Default implementations are provided in AppservPasswordLoginModule
which hook into the GlassFish Server infrastructure.
The custom login module can access the following protected object fields, which it inherits from AppservPasswordLoginModule
. These contain the user name and password of the user to be authenticated:
protected String _username; protected String _password;
The authenticateUser
method must end with the following sequence:
String[] grpList; // populate grpList with the set of groups to which // _username belongs in this realm, if any commitUserAuthentication(grpList);
Custom realms must extend the com.sun.appserv.security.AppservRealm
class and implement the following methods:
public void init(Properties props) throws BadRealmException, NoSuchRealmException
This method is invoked during server startup when the realm is initially loaded. The props
argument contains the properties defined for this realm. The realm can do any initialization it needs in this method. If the method returns without throwing an exception, the GlassFish Server assumes that the realm is ready to service authentication requests. If an exception is thrown, the realm is disabled.
public String getAuthType()
This method returns a descriptive string representing the type of authentication done by this realm.
public abstract Enumeration getGroupNames(String username) throws InvalidOperationException, NoSuchUserException
This method returns an Enumeration
(of String
objects) enumerating the groups (if any) to which the given username
belongs in this realm.
Custom realms that manage users must implement the following additional methods:
public abstract boolean supportsUserManagement();
This method returns true
if the realm supports user management.
public abstract Enumeration getGroupNames() throws BadRealmException;
This method returns an Enumeration
of all group names.
public abstract Enumeration getUserNames() throws BadRealmException;
This method returns an Enumeration
of all user names.
public abstract void refresh() throws BadRealmException;
This method refreshes the realm data so that new users and groups are visible.
public abstract void persist() throws BadRealmException;
This method persists the realm data to permanent storage.
public abstract User getUser(String name) throws NoSuchUserException, BadRealmException;
This method returns the information recorded about a particular named user.
public abstract void addUser(String name, String password, String[] groupList) throws BadRealmException, IASSecurityException;
This method adds a new user, who cannot already exist.
public abstract void removeUser(String name) throws NoSuchUserException, BadRealmException;
This method removes a user, who must exist.
public abstract void updateUser(String name, String newName, String password, String[] groups) throws NoSuchUserException, BadRealmException, IASSecurityException;
This method updates data for a user, who must exist.
Note:
The array passed to the commitUseAuthentication
method should be newly created and otherwise unreferenced. This is because the group name array elements are set to null after authentication as part of cleanup. So the second time your custom realm executes it returns an array with null elements.
Ideally, your custom realm should not return member variables from the authenticate
method. It should return local variables as the default JDBCRealm
does. Your custom realm can create a local String
array in its authenticate
method, copy the values from the member variables, and return the String
array. Or it can use clone
on the member variables.
JACC (Java Authorization Contract for Containers) is part of the Java EE specification and defined by JSR 115. JACC defines an interface for pluggable authorization providers. Specifically, JACC is used to plug in the Java policy provider used by the container to perform Java EE caller access decisions. The Java policy provider performs Java policy decisions during application execution. This provides third parties with a mechanism to develop and plug in modules that are responsible for answering authorization decisions during Java EE application execution. The interfaces and rules used for developing JACC providers are defined in the JACC 1.0 specification.
The GlassFish Server provides a simple file-based JACC-compliant authorization engine as a default JACC provider, named default
. An alternate provider named simple
is also provided. To configure an alternate provider using the Administration Console, open the Security component under the relevant configuration, and select the JACC Providers component. For details, click the Help button in the Administration Console.
Audit modules collect and store information on incoming requests (servlets, EJB components) and outgoing responses. You can create a custom audit module.
The following topics are addressed here:
For additional information about audit modules, see Audit Callbacks.
To configure an audit module, you can perform one of the following tasks:
To specify an audit module using the Administration Console, open the Security component under the relevant configuration, and select the Audit Modules component. For details, click the Help button in the Administration Console.
You can use the asadmin create-audit-module
command to configure an audit module. For details, see the Oracle GlassFish Server Reference Manual.
AuditModule
ClassYou can create a custom audit module by implementing a class that extends com.sun.enterprise.security.audit.AuditModule
.
For Javadoc tool pages relevant to audit modules, go to http://glassfish.java.net/nonav/docs/v3/api/
and click on the com.sun.enterprise.security.audit
package.
The AuditModule
class provides default "no-op" implementations for each of the following methods, which your custom class can override.
public void init(Properties props)
The preceding method is invoked during server startup when the audit module is initially loaded. The props
argument contains the properties defined for this module. The module can do any initialization it needs in this method. If the method returns without throwing an exception, the GlassFish Server assumes the module realm is ready to service audit requests. If an exception is thrown, the module is disabled.
public void authentication(String user, String realm, boolean success)
This method is invoked when an authentication request has been processed by a realm for the given user. The success
flag indicates whether the authorization was granted or denied.
public void webInvocation(String user, HttpServletRequest req, String type, boolean success)
This method is invoked when a web container call has been processed by authorization. The success
flag indicates whether the authorization was granted or denied. The req
object is the standard HttpServletRequest
object for this request. The type
string is one of hasUserDataPermission
or hasResourcePermission
(see JSR 115).
public void ejbInvocation(String user, String ejb, String method, boolean success)
This method is invoked when an EJB container call has been processed by authorization. The success
flag indicates whether the authorization was granted or denied. The ejb
and method
strings describe the EJB component and its method that is being invoked.
public void webServiceInvocation(String uri, String endpoint, boolean success)
This method is invoked during validation of a web service request in which the endpoint is a servlet. The uri
is the URL representation of the web service endpoint. The endpoint
is the name of the endpoint representation. The success
flag indicates whether the authorization was granted or denied.
public void ejbAsWebServiceInvocation(String endpoint, boolean success)
This method is invoked during validation of a web service request in which the endpoint is a stateless session bean. The endpoint
is the name of the endpoint representation. The success
flag indicates whether the authorization was granted or denied.
server.policy
FileEach GlassFish Server domain has its own global J2SE policy file, located in domain-dir/config
. The file is named server.policy
.
The GlassFish Server is a Java EE compliant application server. As such, it follows the requirements of the Java EE specification, including the presence of the security manager (the Java component that enforces the policy) and a limited permission set for Java EE application code.
The following topics are addressed here:
Internal server code is granted all permissions. These are covered by the AllPermission
grant blocks to various parts of the server infrastructure code. Do not modify these entries.
Application permissions are granted in the default grant block. These permissions apply to all code not part of the internal server code listed previously. The GlassFish Server does not distinguish between EJB and web module permissions. All code is granted the minimal set of web component permissions (which is a superset of the EJB minimal set). Do not modify these entries.
A few permissions above the minimal set are also granted in the default server.policy
file. These are necessary due to various internal dependencies of the server implementation. Java EE application developers must not rely on these additional permissions. In some cases, deleting these permissions might be appropriate. For example, one additional permission is granted specifically for using connectors. If connectors are not used in a particular domain, you should remove this permission, because it is not otherwise necessary.
The following predefined system properties, also called variables, are available for use in the server.policy
file. The system property most frequently used in server.policy
is ${com.sun.aas.instanceRoot}
. For more information about system properties, see the asadmin create-system-properties
command in the Oracle GlassFish Server Reference Manual.
Table 4-1 Predefined System Properties
Property | Default | Description |
---|---|---|
|
depends on operating system |
Specifies the directory where the GlassFish Server is installed. |
|
depends on operating system |
Specifies the top level directory for a server instance. |
|
none |
Specifies the name of the host (machine). |
|
depends on operating system |
Specifies the installation directory for the Java runtime. |
|
depends on operating system |
Specifies the library directory for the GlassFish Server Message Queue software. |
|
|
Specifies the name of the configuration used by a server instance. |
|
|
Specifies the name of the server instance. This property is not used in the default configuration, but can be used to customize configuration. |
|
|
Specifies the name of the cluster. This property is only set on clustered server instances. This property is not used in the default configuration, but can be used to customize configuration. |
|
|
Specifies the name of the domain. This property is not used in the default configuration, but can be used to customize configuration. |
The default policy for each domain limits the permissions of Java EE deployed applications to the minimal set of permissions required for these applications to operate correctly. Do not add extra permissions to the default set (the grant block with no codebase, which applies to all code). Instead, add a new grant block with a codebase specific to the applications requiring the extra permissions, and only add the minimally necessary permissions in that block.
If you develop multiple applications that require more than this default set of permissions, you can add the custom permissions that your applications need. The com.sun.aas.instanceRoot
variable refers to the domain-dir. For example:
grant codeBase "file:${com.sun.aas.instanceRoot}/applications/-" { ... }
You can add permissions to stub code with the following grant block:
grant codeBase "file:${com.sun.aas.instanceRoot}/generated/-" { ... }
In general, you should add extra permissions only to the applications or modules that require them, not to all applications deployed to a domain. For example:
grant codeBase "file:${com.sun.aas.instanceRoot}/applications/MyApp/-" { ... }
For a module:
grant codeBase "file:${com.sun.aas.instanceRoot}/applications/MyModule/-" { ... }
Note:
Deployment directories may change between GlassFish Server releases.
An alternative way to add permissions to a specific application or module is to edit the granted.policy
file for that application or module. The granted.policy
file is located in the domain-dir/generated/policy/
app-or-module-name directory. In this case, you add permissions to the default grant block. Do not delete permissions from this file.
When the GlassFish Server policy subsystem determines that a permission should not be granted, it logs a server.policy
message specifying the permission that was not granted and the protection domains, with indicated code source and principals that failed the protection check. For example, here is the first part of a typical message:
[#|2005-12-17T16:16:32.671-0200|INFO|sun-appserver-pe9.1| javax.enterprise.system.core.security|_ThreadID=14;_ThreadName=Thread-31;| JACC Policy Provider: PolicyWrapper.implies, context(null)- permission((java.util.PropertyPermission java.security.manager write)) domain that failed(ProtectionDomain (file:/E:/glassfish/domains/domain1/applications/cejug-clfds/ ... ) ...
Granting the following permission eliminates the message:
grant codeBase "file:${com.sun.aas.instanceRoot}/applications/cejug-clfds/-" { permission java.util.PropertyPermission "java.security.manager", "write"; }
Note:
Do not add java.security.AllPermission
to the server.policy
file for application code. Doing so completely defeats the purpose of the security manager, yet you still get the performance overhead associated with it.
As noted in the Java EE specification, an application should provide documentation of the additional permissions it needs. If an application requires extra permissions but does not document the set it needs, contact the application author for details.
As a last resort, you can iteratively determine the permission set an application needs by observing AccessControlException
occurrences in the server log.
If this is not sufficient, you can add the -Djava.security.debug=failure
JVM option to the domain. Use the following asadmin create-jvm-options
command, then restart the server:
asadmin create-jvm-options -Djava.security.debug=failure
For more information about the asadmin create-jvm-options
command, see the Oracle GlassFish Server Reference Manual.
You can use the J2SE standard policytool
or any text editor to edit the server.policy
file. For more information, see http://download.oracle.com/javase/tutorial/security/tour2/index.html
.
For detailed information about policy file syntax, see http://download.oracle.com/javase/6/docs/technotes/guides/security/PolicyFiles.html
.
For information about using system properties in the server.policy
file, see http://download.oracle.com/javase/6/docs/technotes/guides/security/PolicyFiles.html
.
For detailed information about the permissions you can set in the server.policy
file, see http://download.oracle.com/javase/6/docs/technotes/guides/security/permissions.html
.
The Javadoc for the Permission
class is at http://download.oracle.com/javase/6/docs/api/java/security/Permission.html
.
The security manager is disabled by default.
In a production environment, you may be able to safely disable the security manager if all of the following are true:
Performance is critical
Deployment to the production server is carefully controlled
Only trusted applications are deployed
Applications don't need policy enforcement
Disabling the security manager may improve performance significantly for some types of applications.
To enable the security manager, do one of the following:
To use the Administration Console, open the Security component under the relevant configuration, and check the Security Manager Enabled box. Then restart the server. For details, click the Help button in the Administration Console.
Use the following asadmin create-jvm-options
command, then restart the server:
asadmin create-jvm-options -Djava.security.manager
To disable the security manager, uncheck the Security Manager Enabled box or use the corresponding asadmin delete-jvm-options
command. For more information about create-jvm-options
and delete-jvm-options
, see the Oracle GlassFish Server Reference Manual.
If the security manager is enabled and you are using the Java Persistence API by calling Persistence.createEMF()
, the EclipseLink persistence provider requires that you set the eclipselink.security.usedoprivileged
JVM option to true
as follows:
asadmin create-jvm-options -Declipselink.security.usedoprivileged=true
If the security manager is enabled and you are using the Java Persistence API by injecting or looking up an entity manager or entity manager factory, the EJB container sets this JVM option for you.
In message security, security information is applied at the message layer and travels along with the web services message. Web Services Security (WSS) is the use of XML Encryption and XML Digital Signatures to secure messages. WSS profiles the use of various security tokens including X.509 certificates, Security Assertion Markup Language (SAML) assertions, and username/password tokens to achieve this.
Message layer security differs from transport layer security in that it can be used to decouple message protection from message transport so that messages remain protected after transmission, regardless of how many hops they travel.
Note:
Message security (JSR 196) is supported only in the full GlassFish Server, not in the Web Profile.
Note:
In this release of the GlassFish Server, message layer annotations are not supported.
For more information about web services, see Developing Web Services.
For more information about message security, see the following:
"Introduction to Security in the Java EE Platform" in The Java EE 6 Tutorial
JSR 196, Java Authentication Service Provider Interface for Containers
The Liberty Alliance Project specifications at http://www.projectliberty.org/resources/specifications.php/?f=resources/specifications.php
The Oasis Web Services Security (WSS) specification at http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0.pdf
The Web Services Interoperability Organization (WS-I) Basic Security Profile (BSP) specification at http://www.ws-i.org/Profiles/BasicSecurityProfile-1.0.html
The XML and Web Services Security page at http://xwss.java.net/
The WSIT page at http://wsit.java.net/
The following topics are addressed here:
When you first install the GlassFish Server, the providers XWS_ClientProvider
and XWS_ServerProvider
are configured but disabled. You can enable them in one of the following ways:
To enable the message security providers using the Administration Console, open the Security component under the relevant configuration, select the Message Security component, and select SOAP. Then select XWS_ServerProvider
from the Default Provider list and XWS_ClientProvider
from the Default Client Provider list. For details, click the Help button in the Administration Console.
You can enable the message security providers using the following commands.
asadmin set server-config.security-service.message-security-config.SOAP.default_provider=XWS_ServerProvider asadmin set server-config.security-service.message-security-config.SOAP.default_client_provider=XWS_ClientProvider
For more information about the asadmin set
command, see the Oracle GlassFish Server Reference Manual.
The example described in Understanding and Running the Sample Application uses the ClientProvider
and ServerProvider
providers, which are enabled when the Ant targets are run. You don't need to enable these on the GlassFish Server prior to running the example.
If you install the OpenSSO, you have these additional provider choices:
AMClientProvider
and AMServerProvider
- These providers secure web services and Simple Object Access Protocol (SOAP) messages using either WS-I BSP or Liberty ID-WSF tokens. These providers are used automatically if they are configured as the default providers. If you wish to override any provider settings, you can configure these providers in message-security-binding
elements in the glassfish-web.xml
, glassfish-ejb-jar.xml
, and glassfish-application-client.xml
deployment descriptor files.
AMHttpProvider
- This provider handles the initial end user authentication for securing web services using Liberty ID-WSF tokens and redirects requests to the OpenSSO for single sign-on. To use this provider, specify it in the httpservlet-security-provider
attribute of the glassfish-web-app
element in the glassfish-web.xml
file.
Liberty specifications can be viewed at http://www.projectliberty.org/resources/specifications.php/?f=resources/specifications.php
. The WS-I BSP specification can be viewed at http://www.ws-i.org/Profiles/BasicSecurityProfile-1.0.html
.
For more information about the GlassFish Server deployment descriptor files, see the Oracle GlassFish Server Application Deployment Guide.
For information about configuring these providers in the GlassFish Server, see the Oracle GlassFish Server Security Guide. For additional information about overriding provider settings, see Application-Specific Message Protection.
You can create new message security providers in one of the following ways:
To create a message security provider using the Administration Console, open the Security component under the relevant configuration, and select the Message Security component. For details, click the Help button in the Administration Console.
You can use the asadmin create-message-security-provider
command to create a message security provider. For details, see the Oracle GlassFish Server Reference Manual.
In addition, you can set a few optional provider properties using the asadmin set
command. For example:
asadmin set server-config.security-service.message-security-config.provider-config.property.debug=true
The following table describes these message security provider properties.
Table 4-2 Message Security Provider Properties
Property | Default | Description |
---|---|---|
|
domain-dir |
Specifies the location of the message security configuration file. To point to a configuration file in the domain-dir
See System Properties. |
|
|
If |
|
|
If |
|
|
Specifies the encryption key used by the provider. The key is identified by its |
|
|
Specifies the signature key used by the provider. The key is identified by its |
In the GlassFish Server, the system administrator and application deployer roles are expected to take primary responsibility for configuring message security. In some situations, the application developer may also contribute, although in the typical case either of the other roles may secure an existing application without changing its implementation and without involving the developer.
The following topics are addressed here:
The application developer can turn on message security, but is not responsible for doing so. Message security can be set up by the system administrator so that all web services are secured, or set up by the application deployer when the provider or protection policy bound to the application must be different from that bound to the container.
The application developer is responsible for the following:
Determining if an application-specific message protection policy is required by the application. If so, ensuring that the required policy is specified at application assembly which may be accomplished by communicating with the application deployer.
Determining if message security is necessary at the GlassFish Server level. If so, ensuring that this need is communicated to the system administrator, or taking care of implementing message security at the GlassFish Server level.
The application deployer is responsible for the following:
Specifying (at application assembly) any required application-specific message protection policies if such policies have not already been specified by upstream roles (the developer or assembler)
Modifying GlassFish Server deployment descriptors to specify application-specific message protection policies information (message-security-binding elements) to web service endpoint and service references
These security tasks are discussed in Application-Specific Message Protection. A sample application using message security is discussed in Understanding and Running the Sample Application.
The system administrator is responsible for the following:
Configuring message security providers on the GlassFish Server.
Managing user databases.
Managing keystore and truststore files.
Installing the sample. This is only done if the xms
sample application is used to demonstrate the use of message layer web services security.
A system administrator uses the Administration Console to manage server security settings and uses a command line tool to manage certificate databases. Certificates and private keys are stored in key stores and are managed with keytool
. If Network Security Services (NSS) is installed, certificates and private keys are stored in an NSS database, where they are managed using certutil
. System administrator tasks are discussed in the Oracle GlassFish Server Security Guide.
When the GlassFish Server provided configuration is insufficient for your security needs, and you want to override the default protection, you can apply application-specific message security to a web service.
Application-specific security is implemented by adding the message security binding to the web service endpoint, whether it is an EJB or servlet web service endpoint. Modify GlassFish Server XML files to add the message binding information.
Message security can also be specified using a WSIT security policy in the WSDL file. For details, see the WSIT page at http://wsit.java.net/
.
For more information about message security providers, see Message Security Providers.
For more details on message security binding for EJB web services, servlet web services, and clients, see the XML file descriptions in "Elements of the GlassFish Server Deployment Descriptors" in Oracle GlassFish Server Application Deployment Guide.
For glassfish-ejb-jar.xml
, see "The glassfish-ejb-jar.xml File" in Oracle GlassFish Server Application Deployment Guide.
For glassfish-web.xml
, see "The glassfish-web.xml File" in Oracle GlassFish Server Application Deployment Guide.
For glassfish-application-client.xml
, see "The glassfish-application-client.xml file" in Oracle GlassFish Server Application Deployment Guide.
The following topics are addressed here:
Using a Signature to Enable Message Protection for All Methods
Configuring Message Protection for a Specific Method Based on Digital Signatures
To enable message protection for all methods using digital signature, update the message-security-binding
element for the EJB web service endpoint in the application's glassfish-ejb-jar.xml
file. In this file, add request-protection
and response-protection
elements, which are analogous to the request-policy
and response-policy
elements discussed in the Oracle GlassFish Server Security Guide. To apply the same protection mechanisms for all methods, leave the method-name element blank. Configuring Message Protection for a Specific Method Based on Digital Signatures discusses listing specific methods or using wildcard characters.
This section uses the sample application discussed in Understanding and Running the Sample Application to apply application-level message security to show only the differences necessary for protecting web services using various mechanisms.
Follow this procedure.
In a text editor, open the application's glassfish-ejb-jar.xml
file.
For the xms
example, this file is located in the directory app-dir/xms-ejb/src/conf
, where app-dir is defined in To Set Up the Sample Application.
Modify the glassfish-ejb-jar.xml
file by adding the message-security-binding
element as shown:
<glassfish-ejb-jar> <enterprise-beans> <unique-id>1</unique-id> <ejb> <ejb-name>HelloWorld</ejb-name> <jndi-name>HelloWorld</jndi-name> <webservice-endpoint> <port-component-name>HelloIF</port-component-name> <endpoint-address-uri>service/HelloWorld</endpoint-address-uri> <message-security-binding auth-layer="SOAP"> <message-security> <request-protection auth-source="content" /> <response-protection auth-source="content"/> </message-security> </message-security-binding> </webservice-endpoint> </ejb> </enterprise-beans> </glassfish-ejb-jar>
Compile, deploy, and run the application as described in To Run the Sample Application.
To enable message protection for a specific method, or for a set of methods that can be identified using a wildcard value, follow these steps. As in the example discussed in Using a Signature to Enable Message Protection for All Methods, to enable message protection for a specific method, update the message-security-binding
element for the EJB web service endpoint in the application's glassfish-ejb-jar.xml
file. To this file, add request-protection
and response-protection
elements, which are analogous to the request-policy
and response-policy
elements discussed in the Oracle GlassFish Server Security Guide. The administration guide includes a table listing the set and order of security operations for different request and response policy configurations.
This section uses the sample application discussed in Understanding and Running the Sample Application to apply application-level message security to show only the differences necessary for protecting web services using various mechanisms.
Follow this procedure.
In a text editor, open the application's glassfish-ejb-jar.xml
file.
For the xms
example, this file is located in the directory app-dir/xms-ejb/src/conf
, where app-dir is defined in To Set Up the Sample Application.
Modify the glassfish-ejb-jar.xml
file by adding the message-security-binding
element as shown:
<glassfish-ejb-jar> <enterprise-beans> <unique-id>1</unique-id> <ejb> <ejb-name>HelloWorld</ejb-name> <jndi-name>HelloWorld</jndi-name> <webservice-endpoint> <port-component-name>HelloIF</port-component-name> <endpoint-address-uri>service/HelloWorld</endpoint-address-uri> <message-security-binding auth-layer="SOAP"> <message-security> <message> <java-method> <method-name>ejbCreate</method-name> </java-method> </message> <message> <java-method> <method-name>sayHello</method-name> </java-method> </message> <request-protection auth-source="content" /> <response-protection auth-source="content"/> </message-security> </message-security-binding> </webservice-endpoint> </ejb> </enterprise-beans> </glassfish-ejb-jar>
Compile, deploy, and run the application as described in To Run the Sample Application.
This section discusses the WSS sample application. This sample application is installed on your system only if you installed the J2EE 1.4 samples. If you have not installed these samples, see To Set Up the Sample Application.
The objective of this sample application is to demonstrate how a web service can be secured with WSS. The web service in the xms
example is a simple web service implemented using a Java EE EJB endpoint and a web service endpoint implemented using a servlet. In this example, a service endpoint interface is defined with one operation, sayHello
, which takes a string then sends a response with Hello
prefixed to the given string. You can view the WSDL file for the service endpoint interface at app-dir/xms-ejb/src/
conf/HelloWorld.wsdl
, where app-dir is defined in To Set Up the Sample Application.
In this application, the client looks up the service using the JNDI name java:comp/env/service/HelloWorld
and gets the port information using a static stub to invoke the operation using a given name. For the name Duke, the client gets the response Hello Duke!
This example shows how to use message security for web services at the GlassFish Server level. For information about using message security at the application level, see Application-Specific Message Protection. The WSS message security mechanisms implement message-level authentication (for example, XML digital signature and encryption) of SOAP web services invocations using the X.509 and username/password profiles of the OASIS WS-Security standard, which can be viewed from the following URL: http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0.pdf
.
The following topics are addressed here:
To have access to this sample application, you must have previously installed the J2EE 1.4 samples. If the samples are not installed, follow the steps in the following section.
After you follow these steps, the sample application is located in the directory as-install/j2ee14-samples/samples/webservices/security/ejb/apps/xms/
or in a directory of your choice. For easy reference throughout the rest of this section, this directory is referred to as simply app-dir.
Go to the J2EE 1.4 download URL in your browser.
Click on the Download button for the Samples Bundle.
Click on Accept License Agreement.
Click on the J2EE SDK Samples link.
Choose a location for the j2eesdk-1_4_03-samples.zip
file.
Saving the file to as-install is recommended.
Unzip the file.
Unzipping to the as-install/j2ee14-samples
directory is recommended. For example, you can use the following command.
unzip j2eesdk-1_4_03-samples.zip -d j2ee14-samples
Make sure that the GlassFish Server is running.
Message security providers are set up when the Ant targets are run, so you do not need to configure these on the GlassFish Server prior to running this example.
If you are not running HTTP on the default port of 8080, change the WSDL file for the example to reflect the change, and change the common.properties
file to reflect the change as well.
The WSDL file for this example is located at app-dir/xms-ejb/
src/conf/HelloWorld.wsdl
. The port number is in the following section:
<service name="HelloWorld"> <port name="HelloIFPort" binding="tns:HelloIFBinding"> <soap:address location="http://localhost:8080/service/HelloWorld"/> </port> </service>
Verify that the properties in the as-install/samples/common.properties
file are set properly for your installation and environment. If you need a more detailed description of this file, refer to the "Configuration" section for the web services security applications at as-install/j2ee14-samples/samples/webservices/security/docs/common.html#Logging
.
Change to the app-dir directory.
Run the following Ant targets to compile, deploy, and run the example application:
To compile samples:
ant
To deploy samples:
ant deploy
To run samples:
ant run
If the sample has compiled and deployed properly, you see the following response on your screen after the application has run:
run:[echo] Running the xms program:[exec] Established message level security : Hello Duke!
To undeploy the sample, run the following Ant target:
ant undeploy
All of the web services security examples use the same web service name (HelloWorld
) and web service ports. These examples show only the differences necessary for protecting web services using various mechanisms. Make sure to undeploy an application when you have completed running it. If you do not, you receive an Already in Use
error and deployment failures when you try to deploy another web services example application.
Programmatic login allows a deployed Java EE application or module to invoke a login method. If the login is successful, a SecurityContext
is established as if the client had authenticated using any of the conventional Java EE mechanisms. Programmatic login is supported for servlet and EJB components on the server side, and for stand-alone or application clients on the client side. Programmatic login is useful for an application having special needs that cannot be accommodated by any of the Java EE standard authentication mechanisms.
Note:
Programmatic login is specific to the GlassFish Server and not portable to other application servers.
The following topics are addressed here:
The GlassFish Server is not involved in how the login information (user
, password
) is obtained by the deployed application. Programmatic login places the burden on the application developer with respect to assuring that the resulting system meets security requirements. If the application code reads the authentication information across the network, the application determines whether to trust the user.
Programmatic login allows the application developer to bypass the GlassFish Server-supported authentication mechanisms and feed authentication data directly to the security service. While flexible, this capability should not be used without some understanding of security issues.
Since this mechanism bypasses the container-managed authentication process and sequence, the application developer must be very careful in making sure that authentication is established before accessing any restricted resources or methods. It is also the application developer's responsibility to verify the status of the login attempt and to alter the behavior of the application accordingly.
The programmatic login state does not necessarily persist in sessions or participate in single sign-on.
Lazy authentication is not supported for programmatic login. If an access check is reached and the deployed application has not properly authenticated using the programmatic login method, access is denied immediately and the application might fail if not coded to account for this occurrence. One way to account for this occurrence is to catch the access control or security exception, perform a programmatic login, and repeat the request.
The ProgrammaticLoginPermission
permission is required to invoke the programmatic login mechanism for an application if the security manager is enabled. For information about the security manager, see The server.policy
File. This permission is not granted by default to deployed applications because this is not a standard Java EE mechanism.
To grant the required permission to the application, add the following to the domain-dir/config/server.policy
file:
grant codeBase "file:jar-file-path" {
permission com.sun.appserv.security.ProgrammaticLoginPermission
"login";
};
The jar-file-path is the path to the application's JAR file.
ProgrammaticLogin
ClassThe com.sun.appserv.security.ProgrammaticLogin
class enables a user to perform login programmatically.
For Javadoc tool pages relevant to programmatic login, go to http://glassfish.java.net/nonav/docs/v3/api/
and click on the com.sun.appserv.security
package.
The ProgrammaticLogin
class has four login
methods, two for servlets or JSP files and two for EJB components.
The login methods for servlets or JSP files have the following signatures:
public java.lang.Boolean login(String user, String password, javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) public java.lang.Boolean login(String user, String password, String realm, javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response, boolean errors) throws java.lang.Exception
The login methods for EJB components have the following signatures:
public java.lang.Boolean login(String user, String password) public java.lang.Boolean login(String user, String password, String realm, boolean errors) throws java.lang.Exception
All of these login
methods accomplish the following:
Perform the authentication
Return true
if login succeeded, false
if login failed
The login occurs on the realm specified unless it is null, in which case the domain's default realm is used. The methods with no realm parameter use the domain's default realm.
If the errors flag is set to true
, any exceptions encountered during the login are propagated to the caller. If set to false
, exceptions are thrown.
On the client side, realm and errors parameters are ignored and the actual login does not occur until a resource requiring a login is accessed. A java.rmi.AccessException
with COBRA NO_PERMISSION
occurs if the actual login fails.
The logout methods for servlets or JSP files have the following signatures:
public java.lang.Boolean logout(HttpServletRequest request, HttpServletResponse response) public java.lang.Boolean logout(HttpServletRequest request, HttpServletResponse response, boolean errors) throws java.lang.Exception
The logout methods for EJB components have the following signatures:
public java.lang.Boolean logout() public java.lang.Boolean logout(boolean errors) throws java.lang.Exception
All of these logout
methods return true
if logout succeeded, false
if logout failed.
If the errors flag is set to true
, any exceptions encountered during the logout are propagated to the caller. If set to false
, exceptions are thrown.
The single sign-on feature of the GlassFish Server allows multiple web applications deployed to the same virtual server to share the user authentication state. With single sign-on enabled, users who log in to one web application become implicitly logged into other web applications on the same virtual server that require the same authentication information. Otherwise, users would have to log in separately to each web application whose protected resources they tried to access.
A sample application using the single sign-on scenario could be a consolidated airline booking service that searches all airlines and provides links to different airline web sites. After the user signs on to the consolidated booking service, the user information can be used by each individual airline site without requiring another sign-on.
Single sign-on operates according to the following rules:
Single sign-on applies to web applications configured for the same realm and virtual server. The realm is defined by the realm-name
element in the web.xml
file. For information about virtual servers, see "Administering Internet Connectivity" in Oracle GlassFish Server Administration Guide.
As long as users access only unprotected resources in any of the web applications on a virtual server, they are not challenged to authenticate themselves.
As soon as a user accesses a protected resource in any web application associated with a virtual server, the user is challenged to authenticate himself or herself, using the login method defined for the web application currently being accessed.
After authentication, the roles associated with this user are used for access control decisions across all associated web applications, without challenging the user to authenticate to each application individually.
When the user logs out of one web application (for example, by invalidating the corresponding session), the user's sessions in all web applications are invalidated. Any subsequent attempt to access a protected resource in any application requires the user to authenticate again.
The single sign-on feature utilizes HTTP cookies to transmit a token that associates each request with the saved user identity, so it can only be used in client environments that support cookies.
To configure single sign-on, set the following virtual server properties:
sso-enabled
- If false
, single sign-on is disabled for this virtual server, and users must authenticate separately to every application on the virtual server. The default is false
.
sso-max-inactive-seconds
- Specifies the time after which a user's single sign-on record becomes eligible for purging if no client activity is received. Since single sign-on applies across several applications on the same virtual server, access to any of the applications keeps the single sign-on record active. The default value is 5 minutes (300
seconds). Higher values provide longer single sign-on persistence for the users at the expense of more memory use on the server.
sso-reap-interval-seconds
- Specifies the interval between purges of expired single sign-on records. The default value is 60
.
Here are example asadmin set
commands with default values:
asadmin set server-config.http-service.virtual-server.vsrv1.property.sso-enabled="true" asadmin set server-config.http-service.virtual-server.vsrv1.property.sso-max-inactive-seconds="300" asadmin set server-config.http-service.virtual-server.vsrv1.property.sso-reap-interval-seconds="60"
For more information about the asadmin set
command, see the Oracle GlassFish Server Reference Manual.
You can use JSR 196 in the web tier to facilitate the injection of pluggable authentication modules within the servlet constraint processing engine. The GlassFish Server includes implementations of a number of HTTP layer authentication mechanisms such as basic, form, and digest authentication. You can add alternative implementations of the included mechanisms or implementations of new mechanisms such as HTTP Negotiate/SPNEGO, OpenID, or CAS.
The following topics are addressed here:
The GlassFish Server implements the Servlet Container Profile of JSR 196, Java Authentication Service Provider Interface for Containers. JSR 196 defines a standard service provider interface (SPI) that extends the concepts of the Java Authentication and Authorization Service (JAAS) to enable pluggability of message authentication modules in message processing runtimes. The JSR 196 standard defines profiles that establish contracts for the use of the SPI in specific contexts. The Servlet Container Profile of JSR 196 defines the use of the SPI by a Servlet container such that:
The resulting container can be configured with new authentication mechanisms.
The container employs the configured mechanisms in its enforcement of the declarative servlet security model (declared in a web.xml
file using security-constraint
elements).
The JSR 196 specification defines a simple message processing model composed of four interaction points:
secureRequest
on the client
validateRequest
on the server
secureResponse
on the server
validateResponse
on the client
A message processing runtime uses the SPI at these interaction points to delegate the corresponding message security processing to authentication providers, also called authentication modules, integrated into the runtime by way of the SPI.
A compatible server-side message processing runtime, such as the GlassFish Server servlet container, supports the validateRequest
and secureResponse
interaction points of the message processing model. The servlet container uses the SPI at these interaction points to delegate the corresponding message security processing to a server authentication module (SAM), integrated by the SPI into the container.
A key step in adding an authentication mechanism to a compatible server-side message processing runtime such as the GlassFish Server servlet container is acquiring a SAM that implements the desired authentication mechanism. One way to do that is to write the SAM yourself.
A SAM implements the javax.security.auth.message.module.ServerAuthModule interface as defined by JSR 196. A SAM is invoked indirectly by the message processing runtime at the validateRequest
and secureResponse
interaction points. A SAM must implement the five methods of the ServerAuthModule interface:
getSupportedMessageTypes
— An array of Class
objects where each element defines a message type supported by the SAM. For a SAM to be compatible with the Servlet Container Profile, the returned array must include the HttpServletRequest.class
and HttpServletResponse.class
objects.
initialize(MessagePolicy requestPolicy, MessagePolicy responsePolicy, CallbackHandler Map options)
— The container calls this method to provide the SAM with configuration values and with a CallbackHandler
. The configuration values are returned in the policy arguments and in the options Map
. The SAM uses CallbackHandler
to access services, such as password validation, provided by the container.
AuthStatus validateRequest(MessageInfo messageInfo, Subject clientSubject, Subject serviceSubject)
— The container calls this method to process each received HttpServletRequest
. The request and its associated HttpServletResponse
are passed by the container to the SAM in the messageInfo
argument. The SAM processes the request and may establish the response to be returned by the container. The SAM uses the provided Subject
arguments to convey its authentication results. The SAM returns different status values to control the container's invocation processing. The status values and the circumstances under which they are returned are as follows:
AuthStatus.SUCCESS
is returned when the application request message is successfully validated. The container responds to this status value by using the returned client Subject
to invoke the target of the request. When this value is returned, the SAM (provided a custom AuthConfigProvider
is not being used) must use its CallbackHandler
to handle a CallerPrincipalCallback
using the clientSubject
as an argument to the callback.
AuthStatus.SEND_CONTINUE
indicates that message validation is incomplete and that the SAM has established a preliminary response as the response message in messageInfo
. The container responds to this status value by sending the response to the client.
AuthStatus.SEND_FAILURE
indicates that message validation failed and that the SAM has established an appropriate failure response message in messageInfo
. The container responds to this status value by sending the response to the client.
AuthStatus.SEND_SUCCESS
is not typically returned. This status value indicates the end of a multi-message security dialog originating after the service interaction and during the processing of the application response. The container responds to this status value by sending the response to the client.
The validateRequest
method may also throw an AuthException
to indicate that the message processing by the SAM failed without establishing a failure response message in messageInfo
.
secureResponse(MessageInfo messageInfo, Subject serviceSubject)
— The container calls this method before sending a response, resulting from an application invocation, to the client. The response is passed to the SAM in the messageInfo
argument. In most cases, this method should just return the SEND_SUCCESS
status.
cleanSubject(MessageInfo messageInfo, Subject subject)
— This method removes the mechanism-specific principals, credentials, or both from the subject. This method is not currently called by the container. A legitimate implementation could remove all the principals from the argument subject.
See the Servlet Container Profile section in the JSR 196 specification for additional background and details.
The class MySam.java
is a sample SAM implementation. Notice that the sample implements the five methods of the ServerAuthModule interface. This SAM implements an approximation of HTTP basic authentication.
package tip.sam; import java.io.IOException; import java.util.Map; import javax.security.auth.Subject; import javax.security.auth.callback.Callback; import javax.security.auth.callback.CallbackHandler; import javax.security.auth.callback.UnsupportedCallbackException; import javax.security.auth.message.AuthException; import javax.security.auth.message.AuthStatus; import javax.security.auth.message.MessageInfo; import javax.security.auth.message.MessagePolicy; import javax.security.auth.message.callback.CallerPrincipalCallback; import javax.security.auth.message.callback.GroupPrincipalCallback; import javax.security.auth.message.callback.PasswordValidationCallback; import javax.security.auth.message.module.ServerAuthModule; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.catalina.util.Base64; public class MySam implements ServerAuthModule { protected static final Class[] supportedMessageTypes = new Class[]{ HttpServletRequest.class, HttpServletResponse.class }; private MessagePolicy requestPolicy; private MessagePolicy responsePolicy; private CallbackHandler handler; private Map options; private String realmName = null; private String defaultGroup[] = null; privte static final String REALM_PROPERTY_NAME = "realm.name"; private static final String GROUP_PROPERTY_NAME = "group.name"; private static final String BASIC = "Basic"; static final String AUTHORIZATION_HEADER = "authorization"; static final String AUTHENTICATION_HEADER = "WWW-Authenticate"; public void initialize(MessagePolicy reqPolicy, MessagePolicy resPolicy, CallbackHandler cBH, Map opts) throws AuthException { requestPolicy = reqPolicy; responsePolicy = resPolicy; handler = cBH; options = opts; if (options != null) { realmName = (String) options.get(REALM_PROPERTY_NAME); if (options.containsKey(GROUP_PROPERTY_NAME)) { defaultGroup = new String[]{(String) options.get(GROUP_PROPERTY_NAME)}; } } } public Class[] getSupportedMessageTypes() { return supportedMessageTypes; } public AuthStatus validateRequest( MessageInfo msgInfo, Subject client, Subject server) throws AuthException { try { String username = processAuthorizationToken(msgInfo, client); if (username == null && requestPolicy.isMandatory()) { return sendAuthenticateChallenge(msgInfo); } setAuthenticationResult( username, client, msgInfo); return AuthStatus.SUCCESS; } catch (Exception e) { AuthException ae = new AuthException(); ae.initCause(e); throw ae; } } private String processAuthorizationToken( MessageInfo msgInfo, Subject s) throws AuthException { HttpServletRequest request = (HttpServletRequest) msgInfo.getRequestMessage(); String token = request.getHeader(AUTHORIZATION_HEADER); if (token != null && token.startsWith(BASIC + " ")) { token = token.substring(6).trim(); // Decode and parse the authorization token String decoded = new String(Base64.decode(token.getBytes())); int colon = decoded.indexOf(':'); if (colon <= 0 || colon == decoded.length() - 1) { return (null); } String username = decoded.substring(0, colon); // use the callback to ask the container to // validate the password PasswordValidationCallback pVC = new PasswordValidationCallback(s, username, decoded.substring(colon + 1).toCharArray()); try { handler.handle(new Callback[]{pVC}); pVC.clearPassword(); } catch (Exception e) { AuthException ae = new AuthException(); ae.initCause(e); throw ae; } if (pVC.getResult()) { return username; } } return null; } private AuthStatus sendAuthenticateChallenge( MessageInfo msgInfo) { String realm = realmName; // if the realm property is set use it, // otherwise use the name of the server // as the realm name. if (realm == null) { HttpServletRequest request = (HttpServletRequest) msgInfo.getRequestMessage(); realm = request.getServerName(); } HttpServletResponse response = (HttpServletResponse) msgInfo.getResponseMessage(); String header = BASIC + " realm=\"" + realm + "\""; response.setHeader(AUTHENTICATION_HEADER, header); response.setStatus( HttpServletResponse.SC_UNAUTHORIZED); return AuthStatus.SEND_CONTINUE; } public AuthStatus secureResponse( MessageInfo msgInfo, Subject service) throws AuthException { return AuthStatus.SEND_SUCCESS; } public void cleanSubject(MessageInfo msgInfo, Subject subject) throws AuthException { if (subject != null) { subject.getPrincipals().clear(); } } private static final String AUTH_TYPE_INFO_KEY = "javax.servlet.http.authType"; // distinguish the caller principal // and assign default groups private void setAuthenticationResult(String name, Subject s, MessageInfo m) throws IOException, UnsupportedCallbackException { handler.handle(new Callback[]{ new CallerPrincipalCallback(s, name) }); if (name != null) { // add the default group if the property is set if (defaultGroup != null) { handler.handle(new Callback[]{ new GroupPrincipalCallback(s, defaultGroup) }); } m.getMap().put(AUTH_TYPE_INFO_KEY, ""MySAM"); } } }
Note that the initialize
method looks for the group.name
and realm.name
properties. The group.name
property configures the default group assigned as a result of any successful authentication. The realm.name
property defines the realm value sent back to the browser in the WWW-Authenticate
challenge.
Before you can use the sample SAM, you need to compile, install, and configure it. Then you can bind it to an application.
To compile the SAM, include the SPI in your classpath. When the GlassFish Server is installed, the JAR file containing the SPI, jmac-api.jar
, is installed in the as-install/lib
directory. After you compile the SAM, install it by copying a JAR file containing the compiled SAM to the as-install/lib
directory.
You can configure a SAM in one of these ways:
In the Administration Console, open the Security component under the relevant configuration and go to the Message Security page. Set the following options:
Authentication Layer — HttpServlet
Provider Type — server
or client-server
Provider ID — Specify a unique name for the SAM, for example MySAM
Class Name — Specify the fully qualified class name, for example tip.sam.MySam
Additional Property — Name: group-name
Value: user
Additional Property — Name: realm-name
Value: Sam
For details, click the Help button in the Administration Console.
Use the asadmin create-message-security-provider
command to configure a SAM. Set the following options:
--layer HttpServlet
--providertype server
or --providertype client-server
--classname tip.sam.MySam
--property group-name=user:realm-name=Sam
Provider name operand — Specify a unique name for the SAM, for example MySAM
For details, see the Oracle GlassFish Server Reference Manual.
After you install and configure the SAM, you can bind it for use by the container on behalf of one or more of your applications. You have two options in how you bind the SAM, depending on whether you are willing to repackage and redeploy your application:
If you are willing to repackage and redeploy, you can bind the SAM using the glassfish-web.xml
file. Set the value of the httpservlet-security-provider
attribute of the glassfish-web-app
element to the SAM's configured provider ID, for example, MySAM
. For more information about the glassfish-web.xml
file, see the Oracle GlassFish Server Application Deployment Guide. This option leverages the native AuthConfigProvider
implementation that ships with the GlassFish Server.
Another approach is to develop your own AuthConfigProvider
and register it with the GlassFish Server AuthConfigFactory
for use on behalf of your applications. For example, a simple AuthConfigProvider
can obtain, through its initialization properties, the classname of a SAM to configure on behalf of the applications for which the provider is registered. You can find a description of the functionality of an AuthConfigProvider
and of the registration facilities provided by an AuthConfigFactory
in the JSR 196 specification.