第二部分:cas服务器增加登录验证码
(一)验证码配置
1、新增验证码工作流xml
复制login-webflow.xml,重命名为login-webflow-captcha.xml。
cas-servlet.xml:修改id为loginFlowRegistry的loginFlowRegistry,path改为/WEB-INF/login-webflow-captcha.xml
<webflow:flow-registry id="loginFlowRegistry" flow-builder-services="builder">
<!-- <webflow:flow-location path="/WEB-INF/login-webflow.xml" id="login" /> -->
<!-- 增加验证码 -->
<webflow:flow-location path="/WEB-INF/login-webflow-captcha.xml" id="login" />
</webflow:flow-registry>
2、增加依赖
cas-server中pom文件增加kaptcha依赖,cas-server-webapp-support增加kaptcha依赖。
cas-server:
<dependency>
<groupId>com.github.axet</groupId>
<artifactId>kaptcha</artifactId>
<version>${version.kcaptcha}</version>
</dependency>
<version.kcaptcha>0.0.9</version.kcaptcha>
cas-server-webapp-support:
<dependency>
<groupId>com.github.axet</groupId>
<artifactId>kaptcha</artifactId>
</dependency>
3、web.xml增加kaptcha验证码配置
<!-- kaptcha验证码 -->
<servlet>
<servlet-name>kaptcha</servlet-name>
<servlet-class>com.google.code.kaptcha.servlet.KaptchaServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>kaptcha</servlet-name>
<url-pattern>/captcha.jpg</url-pattern>
</servlet-mapping>
4、新增验证码效验Action类
顺便加入了用户名和密码的非空验证。
CaptchaValidateAction类放在cas-server-webapp-support的org.jasig.cas.web.flow包下。
需要在cas-servlet.xml新增配置。
/**
* 用户名密码非空验证,验证码效验Action
*/
public class CaptchaValidateAction {
/** Authentication success result. */
public static final String SUCCESS = "success";
/** Authentication failure result. */
public static final String AUTHENTICATION_FAILURE = "authenticationFailure";
/** Error result. */
public static final String ERROR = "error";
/** Logger instance. **/
protected final Logger logger = LoggerFactory.getLogger(getClass());
public final String submit(final RequestContext context,
final Credential credential, final MessageContext messageContext)
throws Exception {
final HttpServletRequest request = WebUtils
.getHttpServletRequest(context);
HttpSession session = request.getSession();
String captcha = (String) session
.getAttribute(com.google.code.kaptcha.Constants.KAPTCHA_SESSION_KEY);
session.removeAttribute(com.google.code.kaptcha.Constants.KAPTCHA_SESSION_KEY);
UsernamePasswordCaptchaCredential upc = (UsernamePasswordCaptchaCredential) credential;
//检查用户名是否为空
if (!StringUtils.hasText(upc.getUsername())
|| !StringUtils.hasText(captcha)) {
messageContext.addMessage(new MessageBuilder().error().code("username.required").build());
return ERROR;
}
//检查密码是否为空
if (!StringUtils.hasText(upc.getPassword())
|| !StringUtils.hasText(captcha)) {
messageContext.addMessage(new MessageBuilder().error().code("password.required").build());
return ERROR;
}
String submitCaptcha = upc.getCaptcha();
//检查验证码是否为空
if (!StringUtils.hasText(submitCaptcha)
|| !StringUtils.hasText(captcha)) {
messageContext.addMessage(new MessageBuilder().error().code("captcha.required").build());
return ERROR;
}
if (submitCaptcha.equals(captcha)) {
return SUCCESS;
}
messageContext.addMessage(new MessageBuilder().error().code("error.authentication.captcha.bad").build());
return ERROR;
}
}
cas-servlet.xml:
<bean id="captchaValidateAction"
class="org.jasig.cas.web.flow.CaptchaValidateAction"/>
5、新增验证码凭据
cas-server-core中org.jasig.cas.authentication包新增UsernamePasswordCaptchaCredential类,继承原有的UsernamePasswordCredential。
/**
* 自定义的接收登录验证码的实体类
*/
public class UsernamePasswordCaptchaCredential extends UsernamePasswordCredential {
private static final long serialVersionUID = 8317889802836113837L;
private String captcha;
public String getCaptcha() {
return captcha;
}
public void setCaptcha(String captcha) {
this.captcha = captcha;
}
}
6、修改工作流配置文件,增加验证码验证节点
login-webflow-captcha.xml:
修改name=”credential”配置
<var name="credential"
class="org.jasig.cas.authentication.UsernamePasswordCaptchaCredential" />
修改id为viewLoginForm的view-state
<view-state id="viewLoginForm" view="casLoginView" model="credential">
<binder>
<binding property="username" />
<binding property="password" />
<!-- add -->
<binding property="captcha" />
</binder>
<on-entry>
<set name="viewScope.commandName" value="'credential'" />
</on-entry>
<!-- <transition on="submit" bind="true" validate="true" to="realSubmit"> -->
<transition on="submit" bind="true" validate="true" to="captchaValidate">
<evaluate expression="authenticationViaFormAction.doBind(flowRequestContext, flowScope.credential)" />
</transition>
</view-state>
增加验证码效验节点
<!-- add start -->
<action-state id="captchaValidate">
<evaluate expression="captchaValidateAction.submit(flowRequestContext, flowScope.credential, messageContext)" />
<transition on="error" to="generateLoginTicket" />
<transition on="success" to="realSubmit" />
<transition on="authenticationFailure" to="handleAuthenticationFailure" />
</action-state>
<!-- add end -->
7、增加对应的错误提示信息
messages_zh_CN.properties中新增
#add
screen.welcome.label.captcha=\u9A8C\u8BC1\u7801:
screen.welcome.label.captcha.accesskey=c
captcha.required=\u5FC5\u987B\u5F55\u5165\u9A8C\u8BC1\u7801\u3002
error.authentication.captcha.bad=\u9A8C\u8BC1\u7801\u8F93\u5165\u6709\u8BEF\u3002
8、修改登录页面
casLoginView.jsp:在password文本框后面新增验证码。
<div class="row fl-controls-left">
<label for="captcha"><spring:message code="screen.welcome.label.captcha" /></label>
<spring:message code="screen.welcome.label.captcha.accesskey" var="captchaAccessKey" />
<table>
<tr>
<td>
<form:input cssClass="required" cssErrorClass="error" id="captcha" size="10" tabindex="2" path="captcha" accesskey="${captchaAccessKey}" htmlEscape="true" autocomplete="off" />
</td>
<td align="left" valign="bottom" style="vertical-align: bottom;">
<img alt="<spring:message code="captcha.required" />" onclick="this.src='captcha.jpg?'+Math.random()" width="93" height="30" src="captcha.jpg">
</td>
</tr>
</table>
</div>