Thursday, November 29, 2007

Jetty 6 authentication by configuration XML without web.xml

I spent about a week for porting of NetKernel 3.3 from Jetty 5 to Jetty 6. It is done and I am testing the non-blocking IO (NIO) of Jetty 6 together with asynchronous processing feature of NetKernel. I also figure out how to configure Jetty 6 security in the configuration XML file. From the Jetty document about Realm, the security of an application can be configured in web.xml. However, there is no web.xml in my case, when the request received by Jetty be handled by a specific handler, which will call another handler-like facility for processing. The solution for Jetty 5 does not work for Jetty 6 for this case, since the corresponding API's of org.mortbay.jetty.Server are removed. I got some hint from the document about how to configure security for embedded Jetty. However, it is still about a web application via class WebAppContext. Then I wondered if org.mortbay.jetty.security.SecurityHandler will help (it has an interesting name). Yes, it is. The hack is done with a longer XML file creating a HashUserRealm and a ConstraintMappings. See the details in the following snippet.

<Set name="handler">
<New id="Handlers"
class="org.mortbay.jetty.handler.HandlerCollection">
<Set name="handlers">
<Array type="org.mortbay.jetty.Handler">
<Item>
<New id="BackendSecurity"
class="org.mortbay.jetty.security.SecurityHandler" />
</Item>
<Item>
<New id="BackendNetkernel"
class="org.ten60.transport.jetty.HttpHandler" />
</Item>
</Array>
</Set>
</New>
</Set>
<!-- =========================================================== -->
<!-- Configure BackendSecurity -->
<!-- Add a Realm and a ConstraintMappings to it. See -->
<!-- http://docs.codehaus.org/display/JETTY/How+to+Configure+Security+with+Embedded+Jetty -->
<!-- =========================================================== -->
<Ref id="BackendSecurity">
<Set name="UserRealm">
<New class="org.mortbay.jetty.security.HashUserRealm">
<Set name="name">Test Realm</Set>
<Set name="config">
<SystemProperty name="bootloader.basepath"
default=".." />/etc/realm.properties</Set>
</New>
</Set>
<Set name="AuthMethod">DIGEST</Set>
<Set name="ConstraintMappings">
<Array type="org.mortbay.jetty.security.ConstraintMapping">
<Item>
<New id="BSConstraintMapping"
class="org.mortbay.jetty.security.ConstraintMapping">
<Set name="Constraint">
<New class="org.mortbay.jetty.security.Constraint">
<Set name="Name">allSite</Set>
<Set name="Roles">
<Array type="java.lang.String">
<Item>admin</Item>
</Array>
</Set>
<Set name="Authenticate">true</Set>
</New>
</Set>
<Set name="PathSpec">/</Set>
</New>
</Item>
</Array>
</Set>
</Ref>


Tuesday, November 27, 2007

NetKernel backend securing by using Jetty realm

NetKernel uses Jetty for HTTP transport. By default, it opens two port, one for services, and one for management. The fresh installation does not secure the management port, the backend. However, you can configure it to do that by using HTAccessHandler of Jetty as described in http://www.1060.org/forum/topic/265/2 . I encountered problems when doing like that on Window system. So I tried to using Realm of Jetty to do that, and it works. Here is the configuration file.

<?xml version="1.0" encoding="utf-8"?>
<httpConfig>
<!--
*****************
Jetty HTTP Server
*****************
-->
<Configure class="org.mortbay.jetty.Server">
<!--
***********
Add Listeners
***********
-->
<!--Start addlisteners-->
<!--Add SocketListener with default port 1060-->
<Call name="addListener">
<Arg>
<New class="org.mortbay.http.SocketListener">
<Set name="Port">1060</Set>
<Set name="MinThreads">5</Set>
<Set name="MaxThreads">50</Set>
<Set name="MaxIdleTimeMs">30000</Set>
<Set name="LowResourcePersistTimeMs">5000</Set>
</New>
</Arg>
</Call>
<!--End addlisteners-->
<Call name="addRealm">
<Arg>
<New class="org.mortbay.http.HashUserRealm">
<Arg>Admin Realm</Arg>
<Put name="admin">yourpasshere</Put>
<Call name="addUserToRole">
<Arg>admin</Arg>
<Arg>server-administrator</Arg>
</Call>
</New>
</Arg>
</Call>
<!--
************
Add Server Contexts
************
-->
<!--Default context at root / -->
<Call name="addContext">
<Arg>/</Arg>
<Set name="realmName">Admin Realm</Set>
<Set name="authenticator">
<New class="org.mortbay.http.BasicAuthenticator" />
</Set>
<Call name="addHandler">
<Arg>
<New class="org.mortbay.http.handler.SecurityHandler" />
</Arg>
</Call>
<Call name="addSecurityConstraint">
<Arg>/</Arg>
<Arg>
<New class="org.mortbay.http.SecurityConstraint">
<Arg>Admin</Arg>
<Arg>server-administrator</Arg>
</New>
</Arg>
</Call>
<Call name="addHandler">
<Arg>
<New class="org.ten60.transport.jetty.HttpHandler">
<Set name="Name">BackendHTTPTransport</Set>
</New>
</Arg>
</Call>
</Call>
</Configure>
</httpConfig>

Jetty also provides HashUserRealm that reads a property file in which the user names and passwords can be specified.