【SSO单点系列】:CAS4.0 登录页验证码的添加(03)
一、验证码所需jar包
<!-- https://mvnrepository.com/artifact/com.github.penggle/kaptcha --> <dependency> <groupId>com.github.penggle</groupId> <artifactId>kaptcha</artifactId> <version>2.3.2</version> </dependency>
<!-- https://mvnrepository.com/artifact/com.jhlabs/filters --> <dependency> <groupId>com.jhlabs</groupId> <artifactId>filters</artifactId> <version>2.0.235</version> </dependency>
二、配置修改
1.打开WEB-INF/login-webflow.xml 找到这段代码
<action-state id="generateLoginTicket"> <evaluate expression="generateLoginTicketAction.generate(flowRequestContext)" /> <transition on="generated" to="viewLoginForm" /> </action-state> <view-state id="viewLoginForm" view="casLoginView" model="credential"> <binder> <binding property="username" /> <binding property="password" /> </binder> <on-entry> <set name="viewScope.commandName" value="'credential'" /> </on-entry> <transition on="submit" bind="true" validate="true" to="realSubmit"> <evaluate expression="authenticationViaFormAction.doBind(flowRequestContext, flowScope.credential)" /> </transition> </view-state>
2.username、password两个属性,这就是对应我们登录页面上的表单。所以我们要在这边加上验证码这个属性。
<binder> <binding property="username" /> <binding property="password" /> <!-- 新添加 验证码--> <binding property="captcha" /> </binder>
3. 然而新增的属性在org.jasig.cas.authentication.UsernamePasswordCredential.java文件中并不存在所以,我们需要自己写个java文件去重写掉它,并添加上
captcha这个属性
import javax.validation.constraints.NotNull; import javax.validation.constraints.Size; import org.jasig.cas.authentication.UsernamePasswordCredential; public class UsernamePasswordCaptchaCredential extends UsernamePasswordCredential{ /** * */ private static final long serialVersionUID = -1688519399926023651L; @NotNull @Size(min=1,message = "required.captcha") private String captcha; public String getCaptcha() { return captcha; } public void setCaptcha(String captcha) { this.captcha = captcha; } }
4.这个新增的javabean需要回到 login-webflow.xml中做一些修改,让cas可以找到我们这个javabean
<!-- 修改用户验证javaBean将cas原有的 JavaBean替换成我们的javaBean <var name="credential" class="org.jasig.cas.authentication.UsernamePasswordCredential" /> --> <var name="credential" class="com.nc.cas.authentication.UsernamePasswordCaptchaCredential" />
5.准备工作做完了,接下来就需要添加验证码了,login-webflow.xml中找到这段代码,<transition on="submit" bind="true" validate="true" to="realSubmit">
将Cas原有的realSubmit替换成先去校验验证码的操作validatorCaptcha ,验证码校验成功返回SUCCESS 在去指向将Cas原有的realSubmit校验
<view-state id="viewLoginForm" view="casLoginView" model="credential"> <binder> <binding property="username" /> <binding property="password" /> <!-- 新添加 验证码属性--> <binding property="captcha" /> </binder> <on-entry> <set name="viewScope.commandName" value="'credential'" /> </on-entry> <transition on="submit" bind="true" validate="true" to="validatorCaptcha"> <evaluate expression="authenticationViaFormAction.doBind(flowRequestContext, flowScope.credential)" /> </transition> </view-state> <!-- 新增校验验证码的操作 --> <action-state id="validatorCaptcha"> <evaluate expression="authenticationViaFormAction.validatorCaptcha(flowRequestContext, flowScope.credential, messageContext)"></evaluate> <transition on="error" to="generateLoginTicket" /> <transition on="success" to="realSubmit" /> </action-state>
在校验验证码这段代码中我们可以看到 authenticationViaFormAction.validatorCaptcha()这个方法,所以我们需要去后台在去添加验证码校验的代码
<evaluate expression="authenticationViaFormAction.validatorCaptcha(flowRequestContext, flowScope.credential, messageContext)"></evaluate>
6.后台需要重写下 authenticationViaFormAction.java 添加我们新的验证规则
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; import org.jasig.cas.authentication.Credential; import org.jasig.cas.web.flow.AuthenticationViaFormAction; import org.jasig.cas.web.support.WebUtils; import org.springframework.binding.message.MessageBuilder; import org.springframework.binding.message.MessageContext; import org.springframework.util.StringUtils; import org.springframework.webflow.execution.RequestContext; import com.nc.cas.authentication.UsernamePasswordCaptchaCredential; /** * 验证 * @author Carl * */ public class CnBlogAuthenticationViaFormAction extends AuthenticationViaFormAction{ public final String validatorCaptcha(final RequestContext context, final Credential credential, final MessageContext messageContext){ 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; String submitAuthcodeCaptcha =upc.getCaptcha(); if(!StringUtils.hasText(submitAuthcodeCaptcha) || !StringUtils.hasText(submitAuthcodeCaptcha)){ messageContext.addMessage(new MessageBuilder().error().code("required.captcha").build()); return ERROR; } if(submitAuthcodeCaptcha.equals(captcha)){ return SUCCESS; } messageContext.addMessage(new MessageBuilder().error().code("error.authentication.captcha.bad").build()); return ERROR; } }
这边有抛出两个异常,这两个异常信息 required.captcha、error.authentication.captcha.bad 需要在 messages_zh_CN.properties 文件下添加
required.captcha=请输入验证码
error.authentication.captcha.bad=您输入的验证码有误
三、前台添加验证
1.打开src/cas-theme-default.properties 配置js路径
standard.custom.css.file=/css/cas2.css
javascript.jquery.file=/js/jquery-1.8.2.min.js
2.打开top.jsp引入所需的js,这里的code对应 cas-theme-default.properties中的键
<spring:theme code="javascript.jquery.file" var="jqueryJs" /> <script type="text/javascript" src="<c:url value="${jqueryJs}" />"></script>
3.接来下就可以去添加我们的验证码了 html 代码如下:
<input type="text" class="inputstyle" id="captcha" name="captcha" placeholder="请输入验证码" tabindex="3" type="captcha" style="width: 135px;"> <img align="absmiddle" id="kaptcha" src="kaptcha.jpg" > <a id="changeCaptcha" href="javascript:void(0);">换一张</a>
<script type="text/javascript"> $(function(){ $('#changeCaptcha').click(function() { $("#kaptcha").hide().attr('src','kaptcha.jpg?' + Math.floor(Math.random() * 100)).fadeIn(); }); }); </script>
注:这里input标签 name属性对应的就是后台新增的字段 <binding property="captcha" /> 验证码所需要的html必须写在
<form:form method="post" id="fm1" commandName="${commandName}" htmlEscape="true">标签内
附上验证成功和失败的效果