blob: fb2d7683b2ba6e0a545fcbb7d1caffcdd8bcfd4e [file] [log] [blame]
Title: Remote Object Persistence Tutorial Authentication
<P>You probably don't want everybody in the world to connect to your service and access (and update!) arbitrary data in the database. The first step in securing Cayenne service is implementing client authentication. The easiest way to do it is to delegate the authentication task to the web container that is running the service. HessianConnection used in the previous chapter supports BASIC authentication on the client side, so we'll demonstrate how to set it up here.</P>
<H2><A name="RemoteObjectPersistenceTutorialAuthentication-SecuringROPServerApplication"></A>Securing ROP Server Application</H2>
<P>Open <TT>web.xml</TT> file in the server project and setup security constraints with BASIC authentication for the ROP service:</P>
<DIV class="code panel" style="border-width: 1px;"><DIV class="codeContent panelContent">
<PRE class="code-java">&lt;security-constraint&gt;
&lt;web-resource-collection&gt;
&lt;web-resource-name&gt;CayenneService&lt;/web-resource-name&gt;
&lt;url-pattern&gt;/cayenne-service&lt;/url-pattern&gt;
&lt;/web-resource-collection&gt;
&lt;auth-constraint&gt;
&lt;role-name&gt;cayenne-service-user&lt;/role-name&gt;
&lt;/auth-constraint&gt;
&lt;/security-constraint&gt;
&lt;login-config&gt;
&lt;auth-method&gt;BASIC&lt;/auth-method&gt;
&lt;realm-name&gt;Cayenne Realm&lt;/realm-name&gt;
&lt;/login-config&gt;
&lt;security-role&gt;
&lt;role-name&gt;cayenne-service-user&lt;/role-name&gt;
&lt;/security-role&gt;</PRE>
</DIV></DIV>
<H2><A name="RemoteObjectPersistenceTutorialAuthentication-ConfiguringJettyforBASICAuthentication"></A>Configuring Jetty for BASIC Authentication</H2>
<DIV class="panelMacro"><TABLE class="noteMacro"><COLGROUP><COL width="24"><COL></COLGROUP><TR><TD valign="top"><IMG src="http://cayenne.apache.org/docs/3.0/images/icons/emoticons/warning.gif" width="16" height="16" align="absmiddle" alt="" border="0"></TD><TD>These instructions are specific to Jetty 6. Other containers (and versions of Jetty) will have different mechansims to achieve the same thing.</TD></TR></TABLE></DIV>
<P>Open <TT>pom.xml</TT> in the server project and configure a &quot;userRealm&quot; for the Jetty plugin:</P>
<DIV class="code panel" style="border-width: 1px;"><DIV class="codeContent panelContent">
<PRE class="code-java">&lt;plugin&gt;
&lt;groupId&gt;org.mortbay.jetty&lt;/groupId&gt;
&lt;artifactId&gt;maven-jetty-plugin&lt;/artifactId&gt;
&lt;version&gt;6.1.22&lt;/version&gt;
&lt;!-- adding configuration below: --&gt;
&lt;configuration&gt;
&lt;userRealms&gt;
&lt;userRealm implementation=<SPAN class="code-quote">&quot;org.mortbay.jetty.security.HashUserRealm&quot;</SPAN>&gt;
&lt;!-- <SPAN class="code-keyword">this</SPAN> name must match the realm-name in web.xml --&gt;
&lt;name&gt;Cayenne Realm&lt;/name&gt;
&lt;config&gt;realm.properties&lt;/config&gt;
&lt;/userRealm&gt;
&lt;/userRealms&gt;
&lt;/configuration&gt;
&lt;/plugin&gt;
&lt;/plugins&gt;</PRE>
</DIV></DIV>
<P>Now create a new file called {[&quot;realm.properties&quot;}} <EM>at the root of the server project</EM> and put user login/password in there:</P>
<DIV class="preformatted panel" style="border-width: 1px;"><DIV class="preformattedContent panelContent">
<PRE>cayenne-user: secret,cayenne-service-user</PRE>
</DIV></DIV>
<P>.</P>
<P>Now let's stop the server and start it again. Everything should start as before, but if you go to <A href="http://localhost:8080/tutorial/cayenne-service" class="external-link" rel="nofollow">http://localhost:8080/tutorial/cayenne-service</A>, your browser should pop up authentication dialog. Enter &quot;cayenne-user/secret&quot; for user name / password, and you should see &quot;Hessian Requires POST&quot; message. So the server is now secured.</P>
<H2><A name="RemoteObjectPersistenceTutorialAuthentication-RunningClientwithBasicAuthentication"></A>Running Client with Basic Authentication</H2>
<P>If you run the client without any changes, you'll get the following error:</P>
<DIV class="preformatted panel" style="border-width: 1px;"><DIV class="preformattedContent panelContent">
<PRE>Jan 16, 2010 6:09:03 PM org.apache.cayenne.remote.hessian.HessianConnection connect
INFO: Connecting to [http://localhost:8080/tutorial/cayenne-service] - dedicated session.
Jan 16, 2010 6:09:03 PM org.apache.cayenne.remote.hessian.HessianConnection connect
INFO: Error establishing remote session. URL - http://localhost:8080/tutorial/cayenne-service;
CAUSE - cannot retry due to server authentication, in streaming mode
java.net.HttpRetryException: cannot retry due to server authentication, in streaming mode
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1034)
at java.net.HttpURLConnection.getResponseCode(HttpURLConnection.java:367)
at com.caucho.hessian.client.HessianProxy.invoke(HessianProxy.java:168)
at $Proxy0.establishSession(Unknown Source)
at org.apache.cayenne.remote.hessian.HessianConnection.connect(HessianConnection.java:210)
at org.apache.cayenne.remote.hessian.HessianConnection.getServerEventBridge(HessianConnection.java:114)
at org.apache.cayenne.remote.ClientChannel.setupRemoteChannelListener(ClientChannel.java:256)
at org.apache.cayenne.remote.ClientChannel.&lt;init&gt;(ClientChannel.java:94)
at org.apache.cayenne.remote.ClientChannel.&lt;init&gt;(ClientChannel.java:76)
at org.apache.cayenne.remote.ClientChannel.&lt;init&gt;(ClientChannel.java:71)
at org.apache.cayenne.remote.ClientChannel.&lt;init&gt;(ClientChannel.java:67)
at org.example.cayenne.persistent.client.Main.main(Main.java:25)
Exception in thread &quot;main&quot; org.apache.cayenne.CayenneRuntimeException: [v.3.0RC1 Jan 05 2010 14:44:59] Error
establishing remote session. URL - http://localhost:8080/tutorial/cayenne-service;
CAUSE - cannot retry due to server authentication, in streaming mode
at org.apache.cayenne.remote.hessian.HessianConnection.connect(HessianConnection.java:229)
at org.apache.cayenne.remote.hessian.HessianConnection.getServerEventBridge(HessianConnection.java:114)
at org.apache.cayenne.remote.ClientChannel.setupRemoteChannelListener(ClientChannel.java:256)
at org.apache.cayenne.remote.ClientChannel.&lt;init&gt;(ClientChannel.java:94)
at org.apache.cayenne.remote.ClientChannel.&lt;init&gt;(ClientChannel.java:76)
at org.apache.cayenne.remote.ClientChannel.&lt;init&gt;(ClientChannel.java:71)
at org.apache.cayenne.remote.ClientChannel.&lt;init&gt;(ClientChannel.java:67)
at org.example.cayenne.persistent.client.Main.main(Main.java:25)
Caused by: java.net.HttpRetryException: cannot retry due to server authentication, in streaming mode
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1034)
at java.net.HttpURLConnection.getResponseCode(HttpURLConnection.java:367)
at com.caucho.hessian.client.HessianProxy.invoke(HessianProxy.java:168)
at $Proxy0.establishSession(Unknown Source)
at org.apache.cayenne.remote.hessian.HessianConnection.connect(HessianConnection.java:210)
... 7 more</PRE>
</DIV></DIV>
<P>Which is exactly what you'd expect, as the client is not authenticating itself. So change the line in Main.java where we obtained an ROP connection to this:</P>
<DIV class="code panel" style="border-width: 1px;"><DIV class="codeContent panelContent">
<PRE class="code-java">ClientConnection connection = <SPAN class="code-keyword">new</SPAN> HessianConnection(
<SPAN class="code-quote">&quot;http:<SPAN class="code-comment">//localhost:8080/tutorial/cayenne-service&quot;</SPAN>,
</SPAN> <SPAN class="code-quote">&quot;cayenne-user&quot;</SPAN>, <SPAN class="code-quote">&quot;secret&quot;</SPAN>, <SPAN class="code-keyword">null</SPAN>);</PRE>
</DIV></DIV>
<P>Try running again, and everything should work as before. Obviously in production environment, in addition to authentication you'll need to use HTTPS to access the server to prevent third-party evesdropping on your password and data.</P>
<P>Congratulations, you are done with the ROP tutorial!</P>