CAS client certificate authentication login
Advertisements
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'] != '' && externalContext.requestParameterMap['gateway'] != null && 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'] != '' && 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
}
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 ...












