CAS默認的登陸頁面樣式以下,只有用戶名與密碼兩項驗證項目。css
如今須要爲首頁登陸加上驗證碼功能。html
第一步:首頁對默認登陸頁面的樣式進行了調整,使其看上去還算美觀。java
在頁面上加上了驗證碼項目。web
第二步:導入驗證碼生成工具包及生成驗證碼配置express
pom.xml中加入以下配置服務器
<dependency> <groupId>com.google.code.kaptcha</groupId> <artifactId>kaptcha</artifactId> <version>2.3.2</version> </dependency>
web.xml中加入以下配置(只配置了寬高度等其餘默認)session
<servlet> <servlet-name>captchacode</servlet-name> <servlet-class>com.google.code.kaptcha.servlet.KaptchaServlet</servlet-class> <init-param> <description>邊框粗細度。必須是一個大於0的值</description> <param-name>kaptcha.border.thickness</param-name> <param-value>1</param-value> </init-param> <init-param> <description>圖片的寬度</description> <param-name>kaptcha.image.width</param-name> <param-value>140</param-value> </init-param> <init-param> <description>圖片的高度</description> <param-name>kaptcha.image.height</param-name> <param-value>55</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>captchacode</servlet-name> <url-pattern>/captchacode</url-pattern> </servlet-mapping>
登陸頁jsp中app
<form:input cssClass="required" cssErrorClass="error" id="imgverifycode" path="imgverifycode" htmlEscape="true" autocomplete="off" placeholder="輸入驗證碼" /> <img id="cimg" src="${base_path}/captchacode" onclick="refreshcaptchacode(this)" title="看不清?點擊更換另外一個。"/>
JavaScript:jsp
function refreshcaptchacode(obj) { obj.setAttribute("src", base_path+ "/captchacode?date=" + new Date()); }
第三步:CAS源碼須要作哪些修改?maven
1.首先將新增項目imgverifycode綁定到表單
打開login-webflow.xml,找到這一段
<view-state id="viewLoginForm" view="casLoginView" model="credentials"> <binder> <binding property="username" /> <binding property="password" /> </binder> <on-entry> <set name="viewScope.commandName" value="'credentials'" /> </on-entry> <transition on="submit" bind="true" validate="true" to="realSubmit"> <evaluate expression="authenticationViaFormAction.doBind(flowRequestContext, flowScope.credentials)" /> </transition> </view-state>
修改成(注意紅色加大部分):
<view-state id="viewLoginForm" view="casLoginView" model="credentials"> <binder> <binding property="username" /> <binding property="password" /> <binding property="imgverifycode" /> </binder> <on-entry> <set name="viewScope.commandName" value="'credentials'" /> </on-entry> <transition on="submit" bind="true" validate="true" to="imgverifycodeValidate"> <evaluate expression="authenticationViaFormAction.doBind(flowRequestContext, flowScope.credentials)" /> </transition> </view-state> <!-- 並增長了下面這一段代碼 --> <action-state id="imgverifycodeValidate"> <evaluate expression="authenticationViaFormAction.validatorCode(flowRequestContext, flowScope.credentials, messageContext)" /> <transition on="error" to="generateLoginTicket" /> <transition on="success" to="realSubmit" /> </action-state>
主要是在登陸的工做流中加上了 驗證碼提交綁定以及驗證碼驗證處理。
其次,在UsernamePasswordCredentials.java中添加驗證碼字段。
/** The imgverifycode. */ @NotNull @Size(min = 1, message = "required.imgverifycode") private String imgverifycode;
對於的修改一下equals,hascode方法。
@Override public boolean equals(final Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; UsernamePasswordCredentials that = (UsernamePasswordCredentials) o; if (username != null ? !username.equals(that.username) : that.username != null) return false; if (password != null ? !password.equals(that.password) : that.password != null) return false; if (imgverifycode != null ? !imgverifycode.equals(that.imgverifycode) : that.imgverifycode != null) return false; return true; } @Override public int hashCode() { int result = username != null ? username.hashCode() : 0; result = 31 * result + (password != null ? password.hashCode() : 0); result = 31 * result + (imgverifycode != null ? imgverifycode.hashCode() : 0); return result; }
2.添加驗證邏輯
注意上一段配置加上了一個action-state:imgverifycodeValidate,執行的是AuthenticationViaFormAction.validatorCode(...)方法
打開AuthenticationViaFormAction.java(cas-server-core工程下),添加以下方法
public final String validatorCode(final RequestContext context, final Credentials credentials, final MessageContext messageContext) throws Exception { final HttpServletRequest request = WebUtils.getHttpServletRequest(context); HttpSession session = request.getSession(); UsernamePasswordCredentials upc = (UsernamePasswordCredentials) credentials; String submitAuthcode = upc.getImgverifycode(); if (!StringUtils.hasText(submitAuthcode)) { populateErrorsInstance(new NullImgVerifyCodeAuthenticationException(), messageContext); return "error"; } if (StringUtils.equalsIgnoreCase((String) session.getAttribute(Constants.KAPTCHA_SESSION_KEY), captchacode)) { return "success"; } populateErrorsInstance(new BadImgVerifyCodeAuthenticationException(), messageContext); return "error"; }
其中NullImgVerifyCodeAuthenticationException,BadImgVerifyCodeAuthenticationException是仿照源碼異常類新增的自定義異常類。
NullImgVerifyCodeAuthenticationException.java
/* * Copyright 2007 The JA-SIG Collaborative. All rights reserved. See license * distributed with this file and available online at * http://www.ja-sig.org/products/cas/overview/license/ */ package com.tongxiang.cas.auth.handler; import org.jasig.cas.ticket.TicketException; /** * Generic Bad Credentials Exception. This can be thrown when the system knows * the credentials are not valid specificially because they are bad. Subclasses * can be specific to a certain type of Credentials * (BadUsernamePassowrdCredentials). * * @author Scott Battaglia * @version $Revision$ $Date$ * @since 3.0 */ public class NullImgVerifyCodeAuthenticationException extends TicketException { /** * Static instance of class to prevent cost incurred by creating new * instance. */ public static final NullImgVerifyCodeAuthenticationException ERROR = new NullImgVerifyCodeAuthenticationException(); /** UID for serializable objects. */ private static final long serialVersionUID = 3256719585087797044L; /** * Default constructor that does not allow the chaining of exceptions and * uses the default code as the error code for this exception. */ private static final String CODE = "required.imgverifycode"; /** * Default constructor that does not allow the chaining of exceptions and * uses the default code as the error code for this exception. */ public NullImgVerifyCodeAuthenticationException() { super(CODE); } /** * Constructor to allow for the chaining of exceptions. Constructor defaults * to default code. * * @param throwable the chainable exception. */ public NullImgVerifyCodeAuthenticationException(final Throwable throwable) { super(CODE, throwable); } /** * Constructor method to allow for providing a custom code to associate with * this exception. * * @param code the code to use. */ public NullImgVerifyCodeAuthenticationException(final String code) { super(code); } /** * Constructor to allow for the chaining of exceptions and use of a * non-default code. * * @param code the user-specified code. * @param throwable the chainable exception. */ public NullImgVerifyCodeAuthenticationException(final String code, final Throwable throwable) { super(code, throwable); } }
BadImgVerifyCodeAuthenticationException.java
/* * Copyright 2007 The JA-SIG Collaborative. All rights reserved. See license * distributed with this file and available online at * http://www.ja-sig.org/products/cas/overview/license/ */ package com.tongxiang.cas.auth.handler; import org.jasig.cas.ticket.TicketException; /** * Generic Bad Credentials Exception. This can be thrown when the system knows * the credentials are not valid specificially because they are bad. Subclasses * can be specific to a certain type of Credentials * (BadUsernamePassowrdCredentials). * * @author Scott Battaglia * @version $Revision$ $Date$ * @since 3.0 */ public class BadImgVerifyCodeAuthenticationException extends TicketException { /** * Static instance of class to prevent cost incurred by creating new * instance. */ public static final BadImgVerifyCodeAuthenticationException ERROR = new BadImgVerifyCodeAuthenticationException(); /** UID for serializable objects. */ private static final long serialVersionUID = 3256719585087797044L; /** * Default constructor that does not allow the chaining of exceptions and * uses the default code as the error code for this exception. */ private static final String CODE = "error.authentication.imgverifycode.bad"; /** * Default constructor that does not allow the chaining of exceptions and * uses the default code as the error code for this exception. */ public BadImgVerifyCodeAuthenticationException() { super(CODE); } /** * Constructor to allow for the chaining of exceptions. Constructor defaults * to default code. * * @param throwable the chainable exception. */ public BadImgVerifyCodeAuthenticationException(final Throwable throwable) { super(CODE, throwable); } /** * Constructor method to allow for providing a custom code to associate with * this exception. * * @param code the code to use. */ public BadImgVerifyCodeAuthenticationException(final String code) { super(code); } /** * Constructor to allow for the chaining of exceptions and use of a * non-default code. * * @param code the user-specified code. * @param throwable the chainable exception. */ public BadImgVerifyCodeAuthenticationException(final String code, final Throwable throwable) { super(code, throwable); } }
而且,在messages_zh_CN.properties文件中添加對應上面兩個異常類的兩個異常消息
required.imgverifycode=請輸入驗證碼 error.authentication.imgverifycode.bad=驗證碼錯誤
3.驗證
OK。
單點登陸CAS使用記系列: