cas(五)之验证码
既然是登录,那么少不了的验证码,所以本篇主要说的是验证码的集成。
- 新建cas-captcha项目(maven的java项目),整理各个项目之间的关系
cas-captcha项目的pom文件如下,增加了github上的验证码开源包
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <parent> <artifactId>cas</artifactId> <groupId>com.fzhsh</groupId> <version>1.0-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>cas-captcha</artifactId> <properties> <version.kcaptcha>0.0.9</version.kcaptcha> </properties> <dependencies> <dependency> <groupId>com.github.axet</groupId> <artifactId>kaptcha</artifactId> <version>${version.kcaptcha}</version> </dependency> <dependency> <groupId>org.jasig.cas</groupId> <artifactId>cas-server-core</artifactId> <version>${cas.version}</version> </dependency> <dependency> <groupId>jstl</groupId> <artifactId>jstl</artifactId> <version>1.2</version> <scope>provided</scope> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>servlet-api</artifactId> <version>2.5</version> <scope>provided</scope> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>jstl</artifactId> <version>1.1.2</version> <type>jar</type> <scope>provided</scope> </dependency> </dependencies> </project>
需要项目父pom里面新增子项目模块
<modules> <module>cas-server</module> <module>cas-captcha</module> <module>cas-common</module> </modules>
然后在cas-server项目中新增cas-captcha的依赖
<dependency> <groupId>com.fzhsh</groupId> <artifactId>cas-captcha</artifactId> <version>1.0</version> </dependency>
- 在cas-captcha编写基于spring-web-flow的规则(cas-server登录的流程是基于spring-web-flow的),需要提供一个验证码凭证,还要需要验证验证码的正确性
验证码凭证类
public class UsernamePasswordCaptchaCredential extends UsernamePasswordCredentials { private String captcha; public String getCaptcha() { return captcha; } public void setCaptcha(String captcha) { this.captcha = captcha; } @Override public String toString() { return this.getUsername(); } }
验证规则类
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"; private static final String USER_NAME = "username"; private static final String PASSWORD = "password"; private static final String CAPTCHA = "captcha"; 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); String username = request.getParameter(USER_NAME); String password = request.getParameter(PASSWORD); String submitCaptcha = request.getParameter(CAPTCHA); //检查用户名是否为空 if (!StringUtils.hasText(username)) { messageContext.addMessage(new MessageBuilder().error().code("required.username").build()); return ERROR; } //检查密码是否为空 if (!StringUtils.hasText(password)) { messageContext.addMessage(new MessageBuilder().error().code("required.password").build()); return ERROR; } if(ignoerCaptcha){ return SUCCESS; } //检查是否生成验证码 if(!StringUtils.hasText(captcha)){ messageContext.addMessage(new MessageBuilder().error().code("session.captcha.error").build()); return ERROR; } //检查验证码是否为空 if (!StringUtils.hasText(submitCaptcha) || !StringUtils.hasText(captcha)) { messageContext.addMessage(new MessageBuilder().error().code("required.captcha").build()); return ERROR; } if (submitCaptcha.toLowerCase().equals(captcha.toLowerCase())) { return SUCCESS; } messageContext.addMessage(new MessageBuilder().error().code("error.authentication.captcha.bad").build()); return ERROR; } }
至此,cas-captcha项目开发结束,下面把验证码逻辑加入cas-server。
- 配置cas-server,增加验证码逻辑
在web.xml加上对captcha.jpg的url映射
<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>
在cas-servlet.xml加入CaptchaValidateAction的定义
<bean id="captchaValidateAction" class="com.fzhsh.cas.captcha.CaptchaValidateAction"></bean>
在login-webflow.xml增加验证码的流程
1,将UsernamePasswordCredentials替换成自定义的凭证
<!--<var name="credentials" class="org.jasig.cas.authentication.principal.UsernamePasswordCredentials" />--> <var name="credentials" class="com.fzhsh.cas.captcha.UsernamePasswordCaptchaCredential" />
2,在viewLoginForm中增加验证码,并且转向验证码验证流程
<view-state id="viewLoginForm" view="casLoginView" model="credentials"> <binder> <binding property="username" /> <binding property="password" /> <!-- add --> <binding property="captcha" /> </binder> <on-entry> <set name="viewScope.commandName" value="'credentials'" /> </on-entry> <transition on="submit" bind="true" validate="true" to="captchaValidate"> <evaluate expression="authenticationViaFormAction.doBind(flowRequestContext, flowScope.credentials)" /> </transition> </view-state>
3,增加验证码验证流程
<!-- 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 -->
4,i18n国际化properties文件处理,当前只支持英语,在src/main/resources文件夹下拷贝一份messages_en.properties,加入CaptchaValidateAction国际化需要的内容
# captcha screen.welcome.label.captcha=validate code: screen.welcome.label.captcha.accesskey=accesskey required.captcha=captcha is a required field error.authentication.captcha.bad=error validate code
在casLoginView.jsp里面找到<div class="row check">,然后在前面增加验证码输入框
<section class="row fl-controls-left"> <label for="authcode"><spring:message code="screen.welcome.label.authcode" /></label> <spring:message code="screen.welcome.label.authcode.accesskey" var="authcodeAccessKey" /> <table> <tr> <td> <form:input cssClass="required" cssErrorClass="error" id="authcode" size="10" tabindex="2" path="authcode" accesskey="${authcodeAccessKey}" htmlEscape="true" autocomplete="off" /> </td> <td style="vertical-align: bottom;"> <img onclick="this.src='captcha.jpg?'+Math.random()" width="93" height="30" src="captcha.jpg"> </td> </tr> </table> </section>
- 至此结束,所有不存在的文件,请去源码拷贝一份,按照目录对应关系加入到cas-server项目里面来

浙公网安备 33010602011771号