CAS client certificate authentication login

sponsored links
Front-end time required to achieve certification within the company network automatically login CAS.

Because of the underlying CAS is not so special about the next study, read the next source.

Here I explain the top-down implementation process.

1.Web Flow


We all know that CAS now using Spring Web Flow,

In the CAS in Spring Web Flow configuration file for the login-webflow.xml

The main configuration inside the login process. The graph to indicate if the use of the words that should be a state diagram,

Some nodes have some check and then have different branches.

Here an increase startX509Authenticate this node, the time when the need to log into the node to verify first, if unsuccessful, then there will verify the login screen to enter general. Is directly responsible for a successful login, or logon failures.

The modified profile is as follows:

<?xml version="1.0" encoding="UTF-8"?>
    <flow xmlns="http://www.springframework.org/schema/webflow"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="
              http://www.springframework.org/schema/webflow
              http://www.springframework.org/schema/webflow/spring-webflow-1.0.xsd">

        <start-state idref="initialFlowSetup"/>

        <action-state>
                <action bean="initialFlowSetupAction" />
                <transition on="success" to="ticketGrantingTicketExistsCheck" />
        </action-state>
        
        <decision-state>
                <if test="${flowScope.ticketGrantingTicketId != null}" then="hasServiceCheck" else="gatewayRequestCheck" />
        </decision-state>
    
        <decision-state>
                <if test="${externalContext.requestParameterMap['gateway'] != '' &amp;&amp; externalContext.requestParameterMap['gateway'] != null &amp;&amp; flowScope.service != null}" then="redirect" else="startX509Authenticate" />
        </decision-state>
        
        <decision-state>
                <if test="${flowScope.service != null}" then="renewRequestCheck" else="viewGenericLoginSuccess" />
        </decision-state>
        
        <decision-state>
                <if test="${externalContext.requestParameterMap['renew'] != '' &amp;&amp; externalContext.requestParameterMap['renew'] != null}" then="startX509Authenticate" else="generateServiceTicket" />
        </decision-state>
        
        <decision-state>
                <if test="${flowScope.warnCookieValue}" then="showWarningView" else="redirect" />
        </decision-state>
        

        <action-state>
                <action bean="x509Check" />
                <transition on="success" to="sendTicketGrantingTicket" />
                <transition on="error" to="viewLoginForm" />
        </action-state>

        <view-state view="casLoginView">
                        <render-actions>
                        <action bean="authenticationViaFormAction" method="setupForm"/>
                        <action bean="authenticationViaFormAction" method="referenceData"/>
                </render-actions>
                <transition on="submit" to="bindAndValidate" />
        </view-state>
        
        <action-state>
                <action bean="authenticationViaFormAction" />
                <transition on="success" to="submit" />
                <transition on="error" to="viewLoginForm" />
        </action-state>
        
        <action-state>
                <action bean="authenticationViaFormAction" method="submit" />
                <transition on="warn" to="warn" />
                <transition on="success" to="sendTicketGrantingTicket" />
                <transition on="error" to="viewLoginForm" />
        </action-state>
        
        <action-state>
                <action bean="sendTicketGrantingTicketAction" />
                <transition on="success" to="serviceCheck" />
        </action-state>

        <decision-state>
                <if test="${flowScope.service != null}" then="generateServiceTicket" else="viewGenericLoginSuccess" />
        </decision-state>
        
        <action-state>
                <action bean="generateServiceTicketAction" />
                <transition on="success" to ="warn" />
                <transition on="error" to="viewLoginForm" />
                <transition on="gateway" to="redirect" />
        </action-state>

        <end-state view="casLoginGenericSuccessView" />
        <end-state view="casLoginConfirmView" />
        <end-state view="bean:alibabaDynamicRedirectViewSelector" />
        <end-state view="viewServiceErrorView" />
        <end-state view="viewServiceSsoErrorView" />

        <global-transitions>
                <transition to="viewServiceErrorView" on-exception="org.springframework.webflow.execution.repository.NoSuchFlowExecutionException" />
        <transition to="viewServiceSsoErrorView" on-exception="org.jasig.cas.services.UnauthorizedSsoServiceException" />
                <transition to="viewServiceErrorView" on-exception="org.jasig.cas.services.UnauthorizedServiceException" />
        </global-transitions>
</flow>


2. Proceed from X509Check


From the above we can see startX509Authenticate configuration file corresponding to this node is x509Check Bean

Then we need to increase such a Bean

We are in the cas-servlet.xml this configuration file to add the class configuration, because the CAS comes with a Certificate of Action

<bean
                p:centralAuthenticationService-ref="centralAuthenticationService"/>

Here is what had inserted in the implementation of the time how is the mechanism.

When a request came after, web flow Action node arrangements should be handled

Action will be carried out through its centralAuthenticationService createTicketGrantingTicket, passing the parameter is the credentials.

centralAuthenticationService, which org.jasig.cas.CentralAuthenticationServiceImpl this class.

Before the issuance of TGT to verify through their own authenticationManager pass over the credentials current legality.

To authenticationManager home, use any credentials to verify it, on a variety of authenticationHandlers the play, and these authenticationHandlers have also been a time when the configuration authenticationManager xml configuration into the. Here would be able to choose a credential of authenticationHandler to address the current validation work (authenticationHandler.supports (credentials)). that is, these processors need to realize supports this approach.

If the verification is successful, we need some of the label information into the cas of the client-side A, there need this information.

So, after verification, credentialsToPrincipalResolvers they play, they could well bring out the need to return to cas client information.

Through the above analysis, we need our own Handler and credentialsToPrincipalResolvers to authenticationManager configuration

  <bean
       >
                <property name="credentialsToPrincipalResolvers">
                        <list>
                                <bean />
                                <bean />
                                <bean/>
                        </list>
                </property>
                <property name="authenticationHandlers">
                        <list>
                                <bean
                                        p:httpClient-ref="httpClient" />
                                <ref bean="dynamicAuthenticationHandler" />
                                <ref bean="x509CredentialsAuthenticationHandler"/>
                        </list>
                </property>
        </bean>

x509CredentialsAuthenticationHandler the CAS own, but we need to return to the CAS Client for certificate-mail, but CAS did not provide such a Resolver, so I wrote out a certificate obtained from the X509CertificateCredentialsToDNEmailPrincipalResolver email

Reference to the class here, of course, also need to be configured in the Spring of

   <bean >
        <property name="trustedIssuerDnPattern" value="CN=intranet.+"/>
        </bean>

That will be.

3.Tomcat configuration



Next, we need to CA's certificate to in servlet container TrustStore. And open the client.

   <Connector port="8447" maxHttpHeaderSize="8192"
               maxThreads="150" minSpareThreads="25" maxSpareThreads="75"
               enableLookups="false" disableUploadTimeout="true"
               acceptCount="100" scheme="https" secure="true"
               clientAuth="want" sslProtocol="TLS" 
               keystoreFile="conf/ssl/keystore.jks" keystorePass="changeit"
                           truststoreFile="conf/ssl/keystore.jks" truststorePass="changeit"
    />

clientAuth = "want" does not insist configured want that, if used, configured to true, then it must pass the certificate, or directly back to 404

We here can also be used to go without regular login page, so take the want of this parameter.

Start the CAS, all OK.

-------------------------------------------------- -------------------------------------------

PS: Get Email from the certificate attached to the code

package org.jasig.cas.adaptors.x509.authentication.principal;

import java.security.cert.X509Certificate;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.bouncycastle.asn1.x509.X509NameTokenizer;

public class X509CertificateCredentialsToDNEmailPrincipalResolver extends AbstractX509CertificateCredentialsToPrincipalResolver {

    public static final String EMAIL = "rfc822name";
    public static final String EMAIL1 = "email";
    public static final String EMAIL2 = "EmailAddress";
    public static final String EMAIL3 = "E";
    private static final String[] EMAILIDS = { EMAIL, EMAIL1, EMAIL2, EMAIL3 };
    protected final Log log = LogFactory.getLog(this.getClass());

        @Override
        protected String resolvePrincipalInternal(X509Certificate certificate) {
                String email =  getEmailFromDN(certificate.getSubjectDN().getName());
                dynamicAuthenticationHandler.reload();
                if(email!=null){
                        return email;
                }
                return null;
        }
        


        /**
     * Convenience method for getting an email address from a DN.
     * @param dn the DN
     * @return the found email address, or <code>null</code> if none is found
     */
    public  String getEmailFromDN(String dn) {
        log.info(">getEmailFromDN(" + dn + ")");
        String email = null;
        for (int i = 0; (i < EMAILIDS.length) && (email == null); i++) {
            email = getPartFromDN(dn, EMAILIDS[i]);
        }

        log.error("<getEmailFromDN(" + dn + "): " + email);

        return email;
    }
    
    /**
     * Gets a specified part of a DN. Specifically the first occurrence it the DN contains several
     * instances of a part (i.e. cn=x, cn=y returns x).
     *
     * @param dn String containing DN, The DN string has the format "C=SE, O=xx, OU=yy, CN=zz".
     * @param dnpart String specifying which part of the DN to get, should be "CN" or "OU" etc.
     *
     * @return String containing dnpart or null if dnpart is not present
     */
    public  String getPartFromDN(String dn, String dnpart) {
        log.debug(">getPartFromDN: dn:'" + dn + "', dnpart=" + dnpart);

        String part = null;

        if ((dn != null) && (dnpart != null)) {
            String o;
            dnpart += "="; // we search for 'CN=' etc.

            X509NameTokenizer xt = new X509NameTokenizer(dn);

            while (xt.hasMoreTokens()) {
                o = xt.nextToken();

                //log.debug("checking: "+o.substring(0,dnpart.length()));
                if ((o.length() > dnpart.length()) &&
                    o.substring(0, dnpart.length()).equalsIgnoreCase(dnpart)) {
                    part = o.substring(dnpart.length());

                    break;
                }
            }
        }

        log.debug("<getpartFromDN: resulting DN part=" + part);

        return part;
    } //getPartFromDN

}
  • del.icio.us
  • StumbleUpon
  • Digg
  • TwitThis
  • Mixx
  • Technorati
  • Facebook
  • NewsVine
  • Reddit
  • Google
  • LinkedIn
  • YahooMyWeb

Related Posts of CAS client certificate authentication login

  • Servlet brief introduction

    Servlet brief introduction: Servlet is a small application server Are used to complete the B / S architecture, the client requests the response to treatment Platform independence, performance, able to run thread Servlet API for Servlet provides the s ...

  • can not be represented as java.sql.Timestamp

    Development of procedures for the use of hibernate when, some time there is no need to fill in the fields, but after the hibernate query time reported "Java.sql.SQLException: Value'0000-00-00 'can not be represented as java.sql.Timestamp ...

  • Spring2.0 + hibernate3.1 + log4j + mysql demo

    applicationContext.xml Non-attachment jar package, necessary friends can send an email to todd.liangt @ gmail.com

  • Struts2 + hibernate + spring problem user log in

    dao layer services layer action jsp <tr> <td align="center"> <b> user name: </ b> </ td> <td> <s: textfield name = "czyNumber" cssClass = "textstyle" theme = "simple" size = &q

  • Based on JDBC, JPA Annotation achieve simple CRUD Generic Dao

    The origin of ideas are pretty long history of reasons: [Use iBATIS history] The use of iBATIS has been a long time, the system is to use the CRUD template tool to generate the code, although there are tools to generate, but looked at a lot of CRUD the Sq

  • Hibernate's lazy strategy

    hibernate Lazy strategy can be used in: <class> tag, it can be true / false Tags can <PROPERTY> values true / false type of necessary tools to enhance <set> <list> can tag values true / false / extra <many-to-one> <on ...

blog comments powered by Disqus
Recent
Recent Entries
Tag Cloud
Random Entries