Security Configuration
WebLogic provides several ways to secure a web application:
- You can declaratively configure web authentication for clients that access your web application. You can restrict access to resources in a web application by applying security constraints to a collection of web resources.
- A servlet/JSP can programmatically check whether the client has sufficient privileges before executing a particular piece of code.
- You can programmatically log in a user, bypassing the standard J2EE mechanisms.
2.9.1 Authentication
The login-config element in the standard web.xml deployment descriptor allows you to set up authentication for a web application. You can specify the authentication method using the auth-method element. WebLogic supports the following authentication methods:
HTTP basic authentication (BASIC)
Here the web server authenticates the client against the security realm using the supplied username and password combination.
Form-based authentication (FORM)
Here the client authenticates using a custom HTML form, which resembles:
If you choose form-based authentication, you must specify the locations for the login page that initially will be displayed, and the error page that will be used when the user fails to authenticate himself. Use the form-login-page subelement to specify the login page, and the form-error-page subelement to specify the error page.
Here's a sample configuration for a web application that uses form-based authentication:
FORM foo /login.html /error.html
Client certificates (CLIENT-CERT)
Here the web server authenticates the client using a client certificate or some form of perimeter authentication.
Use the realm-name subelement to specify the name of a security realm used during client authentication.
|
WebLogic also supports a single sign-on mechanism between different web applications, as described earlier in this chapter.
2.9.2 Declarative Security
The J2EE specification defines a standard way to restrict access to resources in a web application. A security constraint is a declarative way of protecting web resources. It is defined in terms of one or more security roles that apply to collections of web resources. A security role maps to one or more principals in the security realm. A principal maps to either users or groups of users. The collection of web resources is specified via a URL pattern. In addition, you can configure whether SSL is required when clients access any resource in the collection.
The following portion from the web.xml descriptor illustrates how to enforce a security constraint to web resources:
Admin Resources security constraints for admin stuff /admin/* POST GET admin NONE
The security-constraint element in the standard web.xml descriptor file ensures that only users in the admin role are granted access to web resources under the admin directory.
The security setup isn't complete. You still need to specify a security role and WebLogic principals that are associated with the role. For this, use the security-role element in the web.xml descriptor file to configure the security role, and use the security-role-assignment element in the weblogic.xml descriptor file to associate one or more WebLogic principals with the role. The role assignment maps actual WebLogic users and groups to the security role. Given the earlier constraint on a resource, you then can set up the following security role assignment:
admin admin jmountjoy achugh
In this case, the WebLogic users achugh and jmountjoy are placed into the admin role, so they will have access to any resources for which this role is authorized. Alternatively, you can indicate that the role actually maps to a security role that already has been configured within WebLogic's security realm using the Administration Console. In this case, you need to use the global-role element to refer to the security role:
admin
You must now use the Administration Console to configure a security role and assign users and/or groups to this role, and also ensure that it is available to the web application. Chapter 17 explains the global-role element in more detail, and also describes how you can configure WebLogic users, groups, and roles.
Web applications can interact with the declarative security using three methods that can be invoked on the HttpServletRequest object:
getRemoteUser( )
This method returns the username the client used to authenticate itself (null, if the user was not authenticated).
isUserInRole( )
This method returns true if the remote user is in a specified role (false if the user has not been authenticated).
getUserPrincipal( )
This method returns the principal associated with the current user (returns a java.security.Principal object).
In order for WebLogic to determine whether a remote user does belong to a particular role, you need to set up the security role and then assign one or more principals to the role as we have just done.
You also can configure an alias for the security role, which can then be used from within your servlet code. The security-role-ref element within the web.xml descriptor file shows how to define this alias for this security role:
... administrator admin ...
Note that the role-link element maps to the actual name of the security role as defined in the web.xml descriptor. Once you have configured this alias for the role, you can programmatically check whether the user is in a given role:
if (req.isUserInRole("administrator")) { // if user is also an administrator } else { // for non-administrators }
Although we've covered the basics of web security here, WebLogic provides a far richer security API to control every aspect of security in an enterprise deployment. We cover this extensively in Chapter 16 and Chapter 17.
2.9.3 Programmatic Security
In some instances, you may want to implement your own authentication scheme, bypassing the standard basic-, form-, or certificate-based authentication altogether. In this case, you can use the programmatic authentication API supplied by WebLogic, which is available via the weblogic.servlet.security.ServletAuthentication class. You may want to read this in conjunction with the material in Chapter 17 if you are unfamiliar with the terminology being used here.
The ServletAuthentication.runAs( ) method accepts two arguments: an authenticated Subject, and the HTTP request object. When you execute this method, it effectively logs the subject into the web application by associating it with the current session. For all intents and purposes, it is as if the client authenticated itself using traditional web authentication. To create the subject, you need to use another helper method, weblogic.security.services.Authentication.login( ). This method accepts the username and password of the WebLogic user, authenticates the credentials, and returns a Subject populated with all principals associated with the subject. The username and password must be passed in the form of a callback handler.
The following JSP page illustrates these points nicely:
<%@ page import ="javax.security.auth.callback.*,javax.security.auth.*" %> <% out.println("Principal before authentication is " + request.getUserPrincipal( ) + " "); CallbackHandler handler = new weblogic.security.SimpleCallbackHandler("jon", "12341234"); Subject mySubject = weblogic.security.services.Authentication.login(handler); weblogic.servlet.security.ServletAuthentication.runAs(mySubject, request); out.println("Principal after authentication is " + request.getUserPrincipal( ) + " "); %>
When you invoke this JSP page from a browser, you get the following output:
Principal before authentication is null Principal after authentication is jon
If you invoke this page again, you get the following output:
Principal before authentication is jon Principal after authentication is jon
This is to be expected because once the client has been authenticated, the credentials are associated for the duration of the client's session. In Chapter 3, we look at how to enforce the single sign-on mechanism, in which case the client's authenticated subject persists across all web applications available on a web server or virtual host.
2.9.4 Securing Servlet Initialization and Destruction
Some users need to run a servlet's init( ) and destroy( ) methods under a different principal, generally because of access to some protected resource. You can configure this in WebLogic by modifying the weblogic.xml descriptor and including something such as the following for each servlet:
MyServletName system systeminit systeminit
2.9.5 Authenticated Dispatching
WebLogic provides servlet request dispatching in the standard way. For instance, the following code sample shows how to forward a servlet request to another JSP page, page.jsp, within the same web application:
// Perform some processing, perhaps writing some output ServletContext sc = getServletConfig( ).getServletContext( ); RequestDispatcher rd = sc.getRequestDispatcher("page.jsp"); rd.forward(request,response);
Similarly, a JSP page also can forward a request to another servlet in the web application:
By default, a web application isn't required to authenticate on requests forwarded to another web resource. However, you can force WebLogic to reauthenticate the client whenever a request is forwarded. If you specify the check-auth-on-forward element in the weblogic.xml descriptor file for the web application, any client request forwarded to a protected resource will require the client to reauthenticate itself:
Ordinarily, once a client has authenticated itself to WebLogic, the web application will continue to use the same security context when any request is forwarded to another web resource. The check-auth-on-forward element lets you deviate from this standard behavior by enforcing an extra authentication check when client requests are forwarded to a protected resource.