caucho
Resin
FAQ
Reference Guide
Demo
Tutorial

Getting Started
Configuration
IDE
Topics
JSP
XML/XSLT

Basic Config
Directory
Servlets
Filters
Resources
Databases
Messaging
Security Config
Log Config
Taglib Config
Misc resin.conf
Host resin.conf
Port resin.conf
App resin.conf
Summary
Glossary
Index

JSSE
 Security Configuration

Messaging
Configuration
JSSE

  1. Overview
  2. Authentication
    1. XmlAuthenticator
    2. JdbcAuthenticator
    3. PasswordDigest
  3. Authorization (security-constraint)
    1. security-constraint
    2. web-resource-collection
    3. auth-constraint
    4. ip-constraint
    5. user-data-constraint
    6. transport-guarantee
    7. constraint
    8. Custom Security Constraints
  4. Encryption (SSL)
    1. OpenSSL
  5. Security Manager

Overview

Security in Resin consists of four separate functions:

By using Resin's login support, applications can add security without writing an entire authentication library. If the predefined authentication methods, XML and database user lookup, are inadequate, Resin provides an API to write custom authentication code.

The easiest authenticator to understand is the XmlAuthenticator. It lets you put users and passwords directly in the configuration file. The following example uses "Basic" authentication for login. Basic authentication asks the browser to pop open a window prompting for a username and password. (Basic authentication is discouraged because it is not secure unless you use it with SSL, but it's the easiest example.) The only user defined here is "Harry Potter" and he has the password "quidditch". He also plays the "user" role.

Using the XmlAuthenticator
<web-app>
<login-config auth-method='basic'>
  <authenticator>
    <class-name>com.caucho.http.security.XmlAuthenticator</class-name>
    <init-param user='Harry Potter:quidditch:user'/>
  </authenticator>
</login-config>
<security-constraint url-pattern='/users-only/*' role-name='user'/>
</web-app>

In the above example, the <security-constraint> checks for authorization. Only users playing the "user" role can access the /users-only directory.

Authentication

login-config

auth-method

Selects the authentication method.

auth-method values
auth-methodMeaning
basicHTTP Basic authentication
digestHTTP Digest authentication
formForm-based authentication

form-login-config

Configures authentication for forms. The login form has specific parameters that the servlet engine's login form processing understands. If the login succeeds, the user will see the original page. If it fails, she will see the error page.

form-login-pageThe page to be used to prompt the user loginnone
form-error-pageThe error page for unsuccessful loginnone
internal-forwardUse an internal redirect on success or a sendRedirectfalse
form-uri-priorityIf true, the form's j_uri will override a stored URIfalse

The form itself must have the action j_security_check. It must also have the parameters j_username and j_password. Optionally, it can also have j_uri and j_use_cookie_auth. j_uri gives the next page to display when login succeeds. j_use_cookie_auth allows Resin to send a persistent cookie to the user to make following login easier.

j_use_cookie_auth gives control to the user whether to generate a persistent cookie. It lets you implement the "remember me" button. By default, the authentication only lasts for a single session.

j_security_check Parameters
ParameterMeaning)
j_usernameThe user name
j_passwordThe password
j_uriResin extension for the successful display page (Optional).
j_use_cookie_authResin extension to allow cookie login (Optional).

The following is an example of a servlet-standard login page:

<form action='j_security_check' method='POST'>
<table>
<tr><td>User:<td><input name='j_username'>
<tr><td>Password:<td><input name='j_password'>
<tr><td colspan=2>hint: the password is 'quidditch'
<tr><td><input type=submit>
</table>
</form>

authenticator

Specifies a class to authenticate users. This Resin-specific option lets you control your authentication. You can either create your own custom authenticator, or use Resin's JdbcAuthenticator.

The authenticator is responsible for taking the username and password and returning a UserPrincipal if the username and password match.

Users wanting to implement an authenticator should look at the JavaDoc for com.caucho.http.security.ServletAuthenticator and com.caucho.http.security.AbstractAuthenticator. To protect your application from API changes, you should extend AbstractAuthenticator rather than implementing Authenticator directly.

XmlAuthenticator

The XmlAuthenticator (com.caucho.http.security.XmlAuthenticator), stores the authentication in either an xml file or in the configuration itself.

When configuring the XmlAuthenticator in the resin.conf (or web.xml), each init-param user adds a new configured user. The value contains the username, password, and the roles the user plays.

XmlAuthenticator in resin.conf
<authenticator>
  <class-name>com.caucho.http.security.XmlAuthenticator</class-name>
  <init-param user='Harry Potter:quidditch:user,gryffindor'/>
  <init-param user='Draco Malfoy:pureblood:user,slytherin'/>
</authenticator>

Because the plain text passwords in the example above are a serious security issue, most sites will use the password-digest attribute described below to protect the passwords.

attributemeaning
userspecifies an allowed user. May be repeated.
password-digestselects the signature method to protect the password
pathspecifies a path to an XML file containing the users and passwords.
logout-on-session-timeoutIf true, the user will be logged out when the session times outtrue

The passwords can be specified in a separate *.xml file. The password file looks like:

password.xml
<authenticator>
  <user name='Harry Potter' password='quidditch' role='gryffindor'/>
  <user name='Draco Malfoy' password='pureblood' role='slytherin'/>
</authenticator>

Sites should use password-digest to protect the passwords.

JdbcAuthenticator

The JdbcAuthenticator (com.caucho.http.security.JdbcAuthenticator), asks a backend database for the password matching the user's name. It uses the DataSource specified by the pool-name option, or the JNDI java:comp/env/jdbc/db-pool by default. pool-name refers to a DataSource configured with resource-ref.

The following are the attributes for the JdbcAuthenticator:

attributemeaning
pool-nameThe database pool. Looks in the application attributes first, then in the global database pools.
password-queryA SQL query to get the user's password. The default query is given below.
cookie-auth-queryA SQL query to authenticate the user by a persistent cookie.
cookie-auth-updateA SQL update to match a persistent cookie to a user.
role-queryA SQL query to determine the user's role. By default, all users are in role "user", but no others.
password-digestSpecifies the digest algorithm and format (Resin 2.0.4)
logout-on-session-timeoutIf true, the user will be logged out when the session times out (Resin 2.0.6)true

<!-- Resin-specific JdbcAuthenticator -->
<authenticator id='com.caucho.http.security.JdbcAuthenticator'>
  <pool-name>test</pool-name>
  <password-query>
    SELECT password FROM LOGIN WHERE username=?
  </password-query>
  <cookie-auth-query>
    SELECT username FROM LOGIN WHERE cookie=?
  </cookie-auth-query>
  <cookie-auth-update>
    UPDATE LOGIN SET cookie=? WHERE username=?
  </cookie-auth-update>
  <role-query>
    SELECT role FROM LOGIN WHERE username=?
  </role-query>
</authenticator>

PasswordDigest

Resin 2.0.4 adds the capability to store the digest of a password instead of the password itself. By using the password digest, the application can avoid storing the password in a form that someone can read.

Setting password-digest of any authenticator extending AbstractAuthenticator will create a digest of the password. The password-digest has two parts: the digest algorithm and the encoding format. "MD5-base64" is a typical digest format.

The authenticator will create a digest of the username and password. Since that digest is a byte array, it is then converted to a string.

MD5(username:password)
Using password-digest with XmlAuthenticator
<authenticator>
  <class-name>com.caucho.http.security.XmlAuthenticator</class-name>
  <init-param password-digest='MD5-base64'/>
  <init-param user='harry:Syvian7bcPDKI261QvH9Cw:user'/>
</authenticator>

Of course, storing the digest password take a bit more work. When the user registers, the application needs to compute the digest to store it. You can use the PasswordDigest class to do that.

import com.caucho.http.security.PasswordDigest;

...
PasswordDigest digest = new PasswordDigest();
digest.setAlgorithm("MD5");
digest.setFormat("base64");

String password = digest.getPasswordDigest("harry", "quidditch");

Authorization (security-constraint)

security-constraint

Selects protected areas of the web site. Sites using authentication as an optional personalization feature will typically not use any security constraints.

Security constraints can also be custom classes.

Protecting all pages for logged-in users
<security-constraint>
  <web-resource-collection>
    <url-pattern>/*</url-pattern>
  </web-resource-collection>
  <auth-constraint role-name='user'/>
</security-constraint>

web-resource-collection

Specifies a collection os areas of the web site.

url-patternurl patterns describing the resource
methodHTTP methods to be restricted.

auth-constraint

Requires that authenticated users fill the specified role. In Resin's JdbcAuthenticator, normal users are in the "user" role. Think of a role as a group of users.

role-nameRoles which are allowed to access the resource.
Protecting webdav for webdav users
<security-constraint>
  <auth-constraint role-name='webdav'/>

  <web-resource-collection>
    <url-pattern>/webdav/*</url-pattern>
  </web-resource-collection>
</security-constraint>

ip-constraint

Requires that the remote address is in an IP network. ip-constraint is very useful for protecting administration resources to an internal network.

Admin pages allowed in 192.168.17.0/24
<security-constraint>
  <ip-constraint>192.168.17.0/24</ip-constraint>

  <web-resource-collection>
    <url-pattern>/admin/*</url-pattern>
  </web-resource-collection>
</security-constraint>

user-data-constraint

Restricts access to secure transports, i.e. SSL.

transport-guaranteeRequired transport properties. NONE, INTEGRAL, and CONFIDENTIAL are allowed values.

<security-constraint>
  <user-data-constraint>
    <transport-guarantee>CONFIDENTIAL</transport-guarantee>
  </user-data-constraint>

  <web-resource-collection>
    <url-pattern>/*</url-pattern>
  </web-resource-collection>
</security-constraint>

transport-guarantee

Restricts access to secure transports, i.e. SSL.

constraint

Defines a custom constraint. The custom constraint specifies a <class-name> which extends com.caucho.http.security.AbstractConstraint. Any init-param elements use Bean introspection to initialize the constraint.

...
<security-constraint>
  <constraint>
    <class-name>qa.CustomSecurity</class-name>
    <init-param foo='ok'/>
  </constraint>
  <web-resource-collection url-pattern='/*'/>
</security-constraint>
...

Custom Security Constraints

Any custom security constraint is checked after any authentication (login) but before any filters or servlets are applied. The security constraint will return true if the request is allowed and false if it's forbidden. If the request is forbidden, it's the constraint's responsibility to return an error page.

package qa;

import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import com.caucho.http.security.*;

public class CustomSecurity extends AbstractConstraint {
  private String foo = "false";

  public void setFoo(String foo)
  {
    this.foo = foo;
  }

  public boolean isAuthorized(HttpServletRequest request,
                              HttpServletResponse response,
                              ServletContext application)
    throws ServletException, IOException
  {
    if (foo.equals(request.getParameter("test")))
      return true;

    response.sendError(response.SC_FORBIDDEN);

    return false;
  }
}

Encryption (SSL)

OpenSSL

The easiest way to add SSL support is to compile the JNI libraries and use OpenSSL (not available on Windows.) OpenSSL is the same SSL implementation that Apache's mod_ssl uses.

The OpenSSL configuration has two tags <certificate-file> and <certificate-key-file>. These correspond exactly to mod_ssl's SSLCertificateFile and SSLCertificateKeyFile. So you can use the same certificates (and documentation) from mod_ssl.

The full set of parameters is in the port configuration.

  1. Create a private key for the server:

    unix> openssl genrsa -des3 -out gryffindor.key 1024
    

  2. Create a request for the the certificate to be signed:

    unix> openssl req -new -key gryffindor.key -out gryffindor.csr
    

  3. Send the CSR to a certificate signer (CA). You'll use the instructions for Apache because the certificates are identical. Some commercial signers include:
  4. You'll receive a gryffindor.crt file.
  5. Configure Resin to use the files:

    ...
    <http port='443'>
      <ssl/>
      <certificate-file>/opt/ssl/keys/gryffindor.crt</certificate-file>
      <certificate-key-file>/opt/ssl/keys/gryffindor.key</certificate-key-file>
      <key-store-password>password</key-store-password>
    </http>
    

Security Manager

In ISP environments, it's important that each user have restricted permissions to use the server. Normally, the web server will be run as a non-root user so the users can't read system files, but that user will still have read access.

Don't use a security manager if you're not in an ISP environment. There's no need for it and the security manager does slow the server down somewhat.

Adding a Java security manager puts each web-app into a "sandbox" where Java limits their abilities.

The security manager is enabled by adding a security-manager tag in the resin.conf.

Sun's documentation is available at http://java.sun.com/j2se/1.4/docs/guide/security/index.html. In particular, the policy permissions and policy file syntax files are useful.

Each web-app automatically has permissions to read, write and delete any file under the web-app's directory, including WEB-INF. It also has read permission for the classpath, including <classpath> from the <host> and <http-server> contexts.

sample java.policy
#
# Permissions allowed for everyone.
#
grant {
  permission java.util.PropertyPermission "*", "read";
  permission java.lang.RuntimePermission "accessClassInPackage.*";
  permission java.net.SocketPermission "mysql.myhost.com:3306" "connect";
  permission java.io.FilePermission "/opt/resin/xsl/*", "read";
};

#
# Give the system and Resin classes all permissions
#
grant codeBase "file:${resin.home}/lib/-" {
	permission java.security.AllPermission;
};

grant codeBase "file:${java.home}/lib/-" {
	permission java.security.AllPermission;
};

grant codeBase "file:${java.home}/jre/lib/-" {
	permission java.security.AllPermission;
};

#
# Give a specific web-app additional permissions.
#
grant codeBase "file:/opt/web/webapps/ejb/WEB-INF/-" {
	permission java.io.FilePermission "/opt/web/doc/*", "read";
};

Messaging
Configuration
JSSE
Copyright © 1998-2002 Caucho Technology, Inc. All rights reserved.
Resin® is a registered trademark, and HardCoretm and Quercustm are trademarks of Caucho Technology, Inc.