Resin Documentationapp server |
resin security
Resin has a comprehensive security framework for application authentication, authorization and transport level SSL based security. Authentication capabilities include built-in support for security data stored in XML files, the database, JAAS, LDAP or properties files, HTTP basic authentication, form based authentication and HTTP password digests. The authorization features include traditional role based security as well as robust conditionals based-on cookies, HTTP headers, locale, IP address and the like. The security framework also supports single sign-on shared across multiple web applications. Resin includes a comprehensive security framework for application authentication, authorization and transport level SSL based security. Authentication capabilities include built-in support for security data stored in XML files, the database, JAAS, LDAP or properties files, HTTP basic authentication, form based authentication and password digests. The authorization features include traditional role based security as well as robust conditionals based-on cookies, HTTP headers, locale, IP address and the like. The security framework also supports single sign-on shared across multiple web applications. This document covers Resin's authentication and authorization capabilities while Resin's SSL support is described in detail here. The basic structure of the Resin security framework can be demonstrated through a simple example: <web-app xmlns="http://caucho.com/ns/resin" xmlns:resin="urn:java:com.caucho.resin"> <!-- The authentication method --> <resin:BasicLogin/> <!-- Authorization --> <resin:Allow url-pattern="/foo/*"> <resin:IfUserInRole role="user"/> </resin:Allow> <!-- Authentication provider --> <resin:XmlAuthenticator password-digest="none"> <resin:user name="Harry Potter" password="quidditch" group="user,gryffindor"/> <resin:user name="Draco Malfoy" password="pureblood" group="user,slytherin"/> </resin:XmlAuthenticator> </web-app> Most usages of the Resin security framework will follow the general outline of the example above. In the example, the <resin:Allow> tag enables authorization whereas the <resin:IfUserInRole> applies role-based authorization. Users actually enter login/authentication information through HTTP basic authentication in the example above. The authentication information that the user enters is checked against an authentication provider. In the example, the authentication information, including user name, password and groups, are stored in XML (the passwords above are simple text, but they need not and should not be). Note, authentication can sometimes be entirely unnecessary, especially while using conditional authorization rules not specific to a user - such as a condition allowing or denying a set of IP addresses from accessing a URL. Authentication is the process of verifying that a user is who they say they are. The most common way of verifying the identity of a user is through user name and password. As demonstrated in the example, Resin uses authenticators to verify user credentials. Authenticators look for authentication data matching a login in a back-end resource such as a database or LDAP directory. The following are the authenticators Resin currently supports:
Each authenticator is described in detail here, including example code that you could use as a starting point for your application. The built-in authenticators should satisfy a large number of common cases, but you can easily create your own custom authenticator when needed. Resin supports single sign-on in the form of authenticators at the server or virtual host level shared across multiple web applications. This described in detail with authenticators if this is functionality you need for your application.
The Resin security framework and the authenticators above are intended for application
security. However, Resin resources such as The <resin:AdminAuthenticator> tag is used to secure all Resin resources such as /resin-admin. The admin authenticator is defined only once in the resin.xml file. The authenticator uses the exact same syntax as the XmlAuthenticator. Resin's top-level <resin:AdminAuthenticator> tag is essentially a static, XML-based authentication context. The authenticator is automatically shared for all hosts and web-apps, so simple sites can even use this authenticator configuration for their site-wide authentication. Here is a basic example of the Resin admin authenticator: <resin xmlns="http://caucho.com/ns/resin" xmlns:resin="urn:java:com.caucho.resin"> ... <resin:AdminAuthenticator> <user name="admin" password="MD5HASH=="/> ... </resin:AdminAuthenticator> ... </resin> Passwords in clear-text form are a major security vulnerability. Such passwords can be stolen during transmission or storage and used malicicously (such as in order to gain unauthorized access to back-end resources). The transmission vulnerability is caused by the fact that passwords are sent across the network to the server from the browser in plain text when HTTP basic authentication or form-based authentication is used. This vulnerability can be addressed by either using HTTP digest authentication (covered here) or by using transport layer SSL security (covered here).
You can secure passwords in storage by using the password digest feature built-into Resin
authenticators (see the
A digest of a clear-text password is calculated when it is passed through a
one-way hashing function that consistently produces another series of characters,
Resin's authenticators use "MD5-base64" and a realm "resin" to digest passwords by default. indicates that the MD5 hashing algorithm is used. is an encoding format to apply to the binary result of MD5. You can create an MD5/Base64 digest yourself with a simple PHP script like this:<?php $username = "harry"; $password = "quidditch"; $realm = "resin"; echo base64_encode(md5("$username:$realm:$password", true)); ?> The following are some examples of passwords digested by Resin:
In the above examples the digest of "harry/quidditch" is different than the
digest of "hpotter/quidditch" because even though the password is the same, the
username has changed. The Resin digest is calculated with
Calculating a Digest
While using password digests with Resin authenticators, it may occationally be necessary to
calculate digests yourself. You can do this in a number of different ways. You could use
the PHP script example above. The import com.caucho.security.PasswordDigest; ... String username = ...; String password = ...; String realm = "resin"; PasswordDigest passwordDigest = PasswordDigest(); String digest = passwordDigest.getPasswordDigest(username, password, realm); Unix users can quickly calculate a digest with this script: echo -n "user:resin:password" | openssl dgst -md5 -binary | uuencode -m - Disabling the Use of password-digest
Using password digests is so important that all Resin authenticators use it by default.
Although it is really not advised, Resin's authenticators can be also be configured to use
passwords that are not in digest form. You can do this by specifying
<web-app xmlns="http://caucho.com/ns/resin" xmlns:resin="urn:java:com.caucho.resin"> ... <resin:XmlAuthenticator</type> <resin:password-digest>none</resin:password-digest> <resin:user name="harry" password="quidditch" group="user"/> </resin:XmlAuthenticator> ... </web-app> This technique can come in handy for development, testing, etc where password security is not critical. Setting Password Digest RealmThe realm for Resin authenticators such as the DatabaseAuthenticator and the XmlAuthenticator defaults to "resin". However, if you want, you can explicitly specify the realm to be used for digesting like this: <web-app xmlns="http://caucho.com/ns/resin" xmlns:resin="urn:java:com.caucho.resin"> ... <resin:DatabaseAuthenticator> <resin:password-digest-realm>hogwarts</resin:password-digest-realm> ... </resin:DatabaseAuthenticator> ... </web-app> Single sign-on refers to allowing for a single login for more than one context, for example, logging into all web-apps in a server at once without having to re-enter authentication information. Resin allows single sign-on by allowing you to place an authenticator at the host or server/cluster level instead of at the web-app level. The shared authenticator then applies to all the web applications under the host or server. Once you authenticate, the login will last for all the web-apps in that environment/scope. For example, to configure an XML authenticator for all the web-apps in foo.com, you might configure as follows: <resin xmlns="http://caucho.com/ns/resin" xmlns:resin="urn:java:com.caucho.resin"> <cluster id="app-tier> <http port="8080"/> <host id="foo.com"> <root-directory>/opt/foo.com</root-directory> <!-- Shared across the host --> <resin:XmlAuthenticator"> <!-- password: quidditch --> <resin:user name="harry" password="uTOZTGaB6pooMDvqvl2LBu" group="user,gryffindor"/> <!-- password: pureblood --> <resin:user name="dmalfoy" password="yI2uN1l97Rv5E6mdRnDFDB" group="user,slytherin"/> </resin:XmlAuthenticator> <web-app-deploy path="webapps" expand-preserve-fileset="WEB-INF/work/**"/> </host> </cluster> </resin> Any .war in the webapps directory will share the same login across the host. Note, you will still need to implement a login-config for each web-app in addition to login managers/authorization.
The value of reuse-session-id must be
Single Sign-on for Virtual HostsThe basis for establishing client identity is the standard JSESSIONID session cookie. If single sign-on is desired for virtual hosts, Resin must be configured to notify the browser of the proper domain name for the cookie so that the same JSESSIONID cookie is submitted by the browser to each virtual host. In this case, an authenticator is placed at the cluster level so that it is common to all virtual hosts. The cookie-domain is placed in a web-app-default at the cluster level so that it is applied as the default for all webapps in all virtual hosts. The following example shows how you can configure single sign-on for two different sub-domains: <resin xmlns="http://caucho.com/ns/resin" xmlns:resin="urn:java:com.caucho.resin"> <cluster id="app-tier> <http port="8080"/> <!-- Shared across all hosts --> <resin:XmlAuthenticator"> <user name="Harry" password="..."/> </resin:XmlAuthenticator> <web-app-default> <session-config> <cookie-domain>.hogwarts.com</cookie-domain> </session-config> </web-app-default> <host id="gryffindor.hogwarts.com"> ... </host> <host id="slytherin.hogwarts.com"> ... </host> </cluster> </resin> Because of the way that browsers are restricted by the HTTP specification from submitting cookies to servers, it is not possible to have a single sign-on for virtual hosts that do not share some portion of their domain name. For example, "gryffindor.com" and "slytherin.com" cannot share a common authentication. Authenticators manage how authentication data is stored, how the user-provided login information is matched to the stored authentication information and how an authenticated principal is constructed. A login manager, on the other hand, controls how the login information is actually collected. HTTP basic authentication is the simplest authentication method (the variety that causes a login/password prompt to appear on the browser when you access a URL). The following are the login managers Resin currently supports:
Each login manager is described in detail here, including example code that you could use as a starting point for your application. The built-in login managers should satisfy a large number of common cases, but you can easily create your own custom login manager when needed. Authorization is the process of verifying that an authenticated user has the appropriate privileges to access a secure resource. The typical authorization process verifies that a user has the right set of permissions to access a URL or is assigned to the correct role/group. Resin has a very robust set of built-in authorization rules including conditionals, role-based security and combining/chaining rules. Authorization rules are based on a basic URL pattern based top level <resin:Allow>/<resin:Deny> tag set. Any conditionals, if applicable, are nested within these top level tags:
The allow/deny high-level directives can be qualified through a set of conditionals that include the most common case of role-based security (shown in the initial example):
These conditionals can also be combined/chained as needed using the following tags:
Each authorization tag is described in detail here, including example code that you could use as a starting point for your application as well as common usage patterns. The built-in rules should satisfy a large number of common cases, but you can easily create your own custom predicate when needed.
|