blob: 65bc5cb1537f7a31bfdfde62efe72816504e36bf [file] [log] [blame]
<h1><a name="CAS-IntegratingApacheShirowithCASSSOserver"></a>Integrating Apache Shiro with CAS SSO server</h1>
<table align="right" width="275" style="margin-left: 20px; margin-bottom: 20px; border-style: solid; border-width: 2px; border-color: navy" cellpadding="10px">
<tr>
<td>
<div id="border">
<h2>Related Content</h2>
<h3><a href="web-features.html">Web Apps with Shiro</a></h3>
<p>Learn more about integrating Shiro into web applications. </br><span style="font-size:11"><a href="web-features.html">Read More &gt;&gt;</a></span></p>
</div>
</td>
</tr>
</table>
<p>The <em>shiro-cas</em> module is made to protect a web application with a <a class="external-link" href="http://www.jasig.org/cas" rel="nofollow">Jasig CAS</a> SSO server. It enables a Shiro-enabled application to be a CAS client.</p>
<h2><a name="CAS-BasicunderstandingoftheCASprotocol"></a>Basic understanding of the CAS protocol</h2>
<p>1. If you want to access an application protected by a CAS client and if you are not authenticated in this application, you are redirected by the CAS client to the CAS server login page. A service parameter in the CAS login url defines the application the user wants to login.</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">http:<span class="code-comment">//application.examples.com/<span class="code-keyword">protected</span>/index.jsp &#8594; HTTP 302
</span>&#8594; https:<span class="code-comment">//server.cas.com/login?service=http://application.examples.com/shiro-cas</span></pre>
</div></div>
<p>2. You fill the login and password and authenticate in CAS server which then redirects the user to the application (the service url) with a service ticket in url. The service ticket is a short-lived one-time-use token redeemable at the CAS server for a user identifier (and optionally, user attributes).</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">https:<span class="code-comment">//server.cas.com/login?service=http://application.examples.com/shiro-cas &#8594; HTTP 302
</span>&#8594; http:<span class="code-comment">//application.examples.com/shiro-cas?ticket=ST-4545454542121-cas</span></pre>
</div></div>
<p>3. The application asks directly the CAS server if the service ticket is valid and the CAS server responds by the identity of the authenticated user. Generally, the CAS client forwards the user to the originally called protected page.</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">http:<span class="code-comment">//application.examples.com/shiro-cas?ticket=ST-4545454542121-cas &#8594; HTTP 302
</span>&#8594; http:<span class="code-comment">//application.examples.com/<span class="code-keyword">protected</span>/index.jsp</span></pre>
</div></div>
<h2><a name="CAS-HowtoconfigureshirotoworkwithCASserver%3F"></a>How to configure shiro to work with CAS server ?</h2>
<h3><a name="CAS-Dependency"></a>Dependency</h3>
<p>You need to add the <em>shiro-cas</em> Maven dependency in your application :</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-xml">
<span class="code-tag">&lt;dependency&gt;</span>
<span class="code-tag">&lt;groupId&gt;</span>org.apache.shiro<span class="code-tag">&lt;/groupId&gt;</span>
<span class="code-tag">&lt;artifactId&gt;</span>shiro-cas<span class="code-tag">&lt;/artifactId&gt;</span>
<span class="code-tag">&lt;version&gt;</span>version<span class="code-tag">&lt;/version&gt;</span>
<span class="code-tag">&lt;/dependency&gt;</span></pre>
</div></div>
<p>(<em>version</em> &gt;= 1.2.0).</p>
<h3><a name="CAS-CasFilter"></a>CasFilter</h3>
<p>You have to define the service url of your application (which has to be declared also in the CAS server). This url will be used to receive CAS service ticket. For example&#160;: <a class="external-link" href="http://application.examples.com/shiro-cas" rel="nofollow">http://application.examples.com/shiro-cas</a></p>
<p>In your shiro configuration, you have to define the <tt>CasFilter</tt>&#160;:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">[main]
casFilter = org.apache.shiro.cas.CasFilter
casFilter.failureUrl = /error.jsp</pre>
</div></div>
<p>(the failure url is called when the service ticket validation fails).</p>
<p>And the url on which it is available&#160;:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">[urls]
/shiro-cas = casFilter</pre>
</div></div>
<p>This way, when the user is redirected to the application service url (<em>/shiro-cas</em>) by the CAS server with a valid service ticket (after authentication), this filter receives the service ticket and creates a <tt>CasToken</tt> which can be used by the <tt>CasRealm</tt>.</p>
<h3><a name="CAS-CasRealm"></a>CasRealm</h3>
<p>The <tt>CasRealm</tt> uses the <tt>CasToken</tt> created by the <tt>CasFilter</tt> to authenticate the user by validating the CAS service ticket against the CAS server.</p>
<p>In your shiro configuration, you have to add the <tt>CasRealm</tt>&#160;:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">[main]
casRealm = org.apache.shiro.cas.CasRealm
casRealm.defaultRoles = ROLE_USER
#casRealm.defaultPermissions
#casRealm.roleAttributeNames
#casRealm.permissionAttributeNames
#casRealm.validationProtocol = SAML
casRealm.casServerUrlPrefix =&#160;https:<span class="code-comment">//server.cas.com/
</span>casRealm.casService =&#160;http:<span class="code-comment">//application.examples.com/shiro-cas</span></pre>
</div></div>
<p>The <em>casServerUrlPrefix</em> is the url of the CAS server (for example&#160;: <a class="external-link" href="https://server.cas.com" rel="nofollow">https://server.cas.com</a>).<br clear="none">
The <em>casService</em> is the application service url, the url on wich the application receives CAS service ticket (for example&#160;: <a class="external-link" href="http://application.examples.com/shiro-cas" rel="nofollow">http://application.examples.com/shiro-cas</a>).<br clear="none">
The <em>validationProcol</em> can be SAML or CAS (default)&#160;: attributes and remember me information are only pushed throught the SAML validation procotol (except specific customizations). It depends on the version of the CAS server&#160;: SAML protocol can be used with CAS server version &gt;= 3.1.</p>
<div class="panelMacro"><table class="warningMacro"><colgroup span="1"><col span="1" width="24"><col span="1"></colgroup><tr><td colspan="1" rowspan="1" valign="top"><img align="middle" src="https://cwiki.apache.org/confluence/images/icons/emoticons/forbidden.gif" width="16" height="16" alt="" border="0"></td><td colspan="1" rowspan="1">If you choose SAML validation, you need some more specific dependencies :</td></tr></table></div>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-xml">
<span class="code-tag">&lt;dependency&gt;</span>
<span class="code-tag">&lt;groupId&gt;</span>commons-codec<span class="code-tag">&lt;/groupId&gt;</span>
<span class="code-tag">&lt;artifactId&gt;</span>commons-codec<span class="code-tag">&lt;/artifactId&gt;</span>
<span class="code-tag">&lt;/dependency&gt;</span>
<span class="code-tag">&lt;dependency&gt;</span>
<span class="code-tag">&lt;groupId&gt;</span>org.opensaml<span class="code-tag">&lt;/groupId&gt;</span>
<span class="code-tag">&lt;artifactId&gt;</span>opensaml<span class="code-tag">&lt;/artifactId&gt;</span>
<span class="code-tag">&lt;version&gt;</span>1.1<span class="code-tag">&lt;/version&gt;</span>
<span class="code-tag">&lt;/dependency&gt;</span>
<span class="code-tag">&lt;dependency&gt;</span>
<span class="code-tag">&lt;groupId&gt;</span>org.apache.santuario<span class="code-tag">&lt;/groupId&gt;</span>
<span class="code-tag">&lt;artifactId&gt;</span>xmlsec<span class="code-tag">&lt;/artifactId&gt;</span>
<span class="code-tag">&lt;version&gt;</span>1.4.3<span class="code-tag">&lt;/version&gt;</span>
<span class="code-tag">&lt;/dependency&gt;</span></pre>
</div></div>
<p>The <em>defaultRoles</em> is the default roles given to the authenticated user after CAS authentication success.<br clear="none">
The <em>defaultPermissions</em> is the default permissions given to the authenticated user after CAS authentication success.<br clear="none">
The <em>roleAttributeNames</em> defines the names of the attributes received from CAS response which define roles to give to the authenticated user (the roles are separated by comas).<br clear="none">
The <em>permissionAttributeNames</em> defines the names of the attributes received from CAS response which define permissions to give to the authenticated user (the permissions are separated by comas).</p>
<h3><a name="CAS-CasSubjectFactory"></a>CasSubjectFactory</h3>
<p>In CAS server, you can have "remember me" support. This information is pushed through SAML validation or CAS customized validation.<br clear="none">
To reflect the CAS-remember me status in Shiro, you have to define a specific <tt>CasSubjectFactory</tt> in your Shiro configuration :</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">[main]
casSubjectFactory = org.apache.shiro.cas.CasSubjectFactory
securityManager.subjectFactory = $casSubjectFactory</pre>
</div></div>
<h3><a name="CAS-Security%C2%A0oftheapplication"></a>Security&#160;of the application</h3>
<p>Finally, you have to define the security of your application.</p>
<p>In your Shiro configuration, you have to protect url with roles&#160;(for example) :</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">[urls]
/<span class="code-keyword">protected</span>/** = roles[ROLE_USER]
/** = anon</pre>
</div></div>
<p>And the login url if the user is not authenticated is to be defined on the CAS server with the application service url&#160;:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">[main]
roles.loginUrl = https:<span class="code-comment">//server.cas.com/login?service=http://application.examples.com/shiro-cas</span></pre>
</div></div>
<p>This way, if you are not authenticated and try to acces a <em>/protected/**</em> url, you are redirected to the CAS server for authentication.</p>
<h3><a name="CAS-Completeconfigurationsample"></a>Complete configuration sample</h3>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">[main]
casFilter = org.apache.shiro.cas.CasFilter
casFilter.failureUrl = /error.jsp
casRealm = org.apache.shiro.cas.CasRealm
casRealm.defaultRoles = ROLE_USER
casRealm.casServerUrlPrefix =&#160;https:<span class="code-comment">//server.cas.com/
</span>casRealm.casService =&#160;http:<span class="code-comment">//application.examples.com/shiro-cas
</span>
casSubjectFactory = org.apache.shiro.cas.CasSubjectFactory
securityManager.subjectFactory = $casSubjectFactory
roles.loginUrl = https:<span class="code-comment">//server.cas.com/login?service=http://application.examples.com/shiro-cas
</span>
[urls]
/shiro-cas = casFilter
/<span class="code-keyword">protected</span>/** = roles[ROLE_USER]
/** = anon</pre>
</div></div>
<h2><a name="CAS-History"></a>History</h2>
<p><em>Version 1.2.0</em>&#160;: first release of the <em>shiro-cas</em> module.</p>