5.CAS增加验证码

CAS增加验证码


1.1开始增加验证码

第一部分:

      (1)在WEB-INF下找到并打开login-webflow.xml,找到:<var name="credential" class="org.jasig.cas.authentication.UsernamePasswordCredential" />,

该配置的作用是,在登录时收集用户名密码信息的。所以我们需要扩展增加验证码字段的收集。新建包:org.chengli.cas.credential,

新建类:CustomUsernamePasswordCredential并继承org.jasig.cas.authentication.UsernamePasswordCredential类,增加验证码字段,代码如下:

package org.chengli.cas.credential;

import org.jasig.cas.authentication.UsernamePasswordCredential;

public class CustomUsernamePasswordCredential extends
		UsernamePasswordCredential {
	private static final long serialVersionUID = 5034129937759981063L;

	private String captcha;

	public String getCaptcha() {
		return captcha;
	}

	public void setCaptcha(String captcha) {
		this.captcha = captcha;
	}

}

      (2)更改login-webflow.xml配置
修改前:
<var name="credential" class="org.jasig.cas.authentication.UsernamePasswordCredential" />
修改后:
<var name="credential" class="org.chengli.cas.credential.CustomUsernamePasswordCredential" />

修改前:
<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>
修改后:
<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="customValidator">
            <evaluate expression="authenticationViaFormAction.doBind(flowRequestContext, flowScope.credential)" />
        </transition>
	</view-state>

      (3)在login-webflow.xm增加l配置
<action-state id="customValidator">
        <evaluate expression="authenticationViaFormAction.customValidator(flowRequestContext, flowScope.credential, messageContext)"></evaluate>
        <transition on="error" to="generateLoginTicket" />
        <transition on="success" to="realSubmit" />
    </action-state>

      (4)在这里我们增加了自定义的认证处理器customValidator,在表达式中指定了使用authenticationViaFormAction 类中的customValidator方法,

但是CAS提供的authenticationViaFormAction类根本就没有customValidator方法,所以我们需要实现该方法,authenticationViaFormAction  Bean定义

在WEB-INF->cas-servlet.xml中,打开cas-servlet.xml,找到bean id为authenticationViaFormAction的定义,修改改定义类。如下:

修改前:
<bean id="authenticationViaFormAction" class="org.jasig.cas.web.flow.AuthenticationViaFormAction"
        p:centralAuthenticationService-ref="centralAuthenticationService"
        p:warnCookieGenerator-ref="warnCookieGenerator"
        p:ticketRegistry-ref="ticketRegistry"/>
修改后:
<bean id="authenticationViaFormAction" class="org.chengli.cas.validator.CustomAuthenticationViaFormAction"
        p:centralAuthenticationService-ref="centralAuthenticationService"
        p:warnCookieGenerator-ref="warnCookieGenerator"
        p:ticketRegistry-ref="ticketRegistry"/>

      (5)新建包:org.chengli.cas.validator,新建类:CustomAuthenticationViaFormAction并继承AuthenticationViaFormAction,增加方法:customValidator,

验证码使用的是GOOGLE的kaptcha,在pom.xml增加依赖,如下:
<dependency>
    <groupId>com.google.code.kaptcha</groupId>
    <artifactId>kaptcha</artifactId>
    <version>2.3.2</version>
</dependency>

CustomAuthenticationViaFormAction类代码如下:
package org.chengli.cas.validator;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.chengli.cas.credential.CustomUsernamePasswordCredential;
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.Event;
import org.springframework.webflow.execution.RequestContext;

import com.google.code.kaptcha.Constants;

public class CustomAuthenticationViaFormAction extends
		AuthenticationViaFormAction {
	
	public final Event customValidator(RequestContext context,
			Credential credential, MessageContext messageContext) {

		HttpServletRequest request = WebUtils.getHttpServletRequest(context);
		HttpSession session = request.getSession();
		
		String captcha = (String) session.getAttribute(Constants.KAPTCHA_SESSION_KEY);
		session.removeAttribute(Constants.KAPTCHA_SESSION_KEY);

		CustomUsernamePasswordCredential cuCredential = (CustomUsernamePasswordCredential) credential;
		String submitCaptcha= cuCredential.getCaptcha();

		if (!StringUtils.hasText(submitCaptcha)) {
			messageContext.addMessage(new MessageBuilder().error().code("login.required.captcha").build());
			return new Event(this, ERROR);
		}
		if (submitCaptcha.equals(captcha)) {
			return new Event(this, SUCCESS);
		}
		messageContext.addMessage(new MessageBuilder().error().code("login.captcha.error").build());
		
		return new Event(this, ERROR);
	}
}

      (6)CAS实现了国际化支持,错误信息都放在国际化文件中,在messages.properties、messages_zh_CN.properties加入以下内容:
               login.required.captcha=请输入验证码
               login.captcha.error=验证码错误
              如果需要实现更多语言只需要在相应的国际化文件中加入即可。

      (7)打开web.xml加入以下代码:
<servlet>
		<servlet-name>Kaptcha</servlet-name>
		<servlet-class>com.google.code.kaptcha.servlet.KaptchaServlet</servlet-class>
		<init-param>
			<param-name>kaptcha.image.width</param-name>
			<param-value>200</param-value>
		</init-param>
		<init-param>
			<param-name>kaptcha.image.height</param-name>
			<param-value>50</param-value>
		</init-param>
		<init-param>
			<param-name>kaptcha.textproducer.char.length</param-name>
			<param-value>4</param-value>
		</init-param>
		<init-param>
			<param-name>kaptcha.noise.impl</param-name>
			<param-value>com.google.code.kaptcha.impl.NoNoise</param-value>
		</init-param>
	</servlet>
	<servlet-mapping>
		<servlet-name>Kaptcha</servlet-name>
		<url-pattern>/kaptcha.jpg</url-pattern>
	</servlet-mapping> 

      (8)在登录页面form中加入以下代码:
<input id="captcha" type="text" name="captcha" placeholder="请输入验证码"/>
<img class="security-code-img" src="kaptcha.jpg" >

      (9)到这里就OK啦,启动TOMCAT试试看吧,效果图如下。。。

第二部分:

      可能还有的需求,在用户打开浏览器第一次登录的时候不需要输入验证码,如果登录用户名或者密码错了之后,再进行登录就需要验证码,

那么接下来,将说说怎么弄,只是个人实现的方法,如果有更好的方法欢迎大家探讨。

      (1)创建包:org.chengli.cas.constans,创建类:CustomConstants。代码如下:

package org.chengli.cas.constans;

public interface CustomConstants {
	String LOGIN_FIRST = "LOGIN_FIRST";

	String FIRST = "FIRST";

	String NOTFIRST = "NOTFIRST";
}

      (2)在CustomAuthenticationViaFormAction类中customValidator方法HttpSession session = request.getSession();下面 加入以下代码:
Object loginObject = session.getAttribute(CustomConstants.LOGIN_FIRST);
		if(loginObject == null || CustomConstants.FIRST.equals(String.valueOf(loginObject))){
			session.setAttribute(CustomConstants.LOGIN_FIRST, CustomConstants.NOTFIRST);
			return new Event(this, SUCCESS);
		}

       注:我使用的session中存储,也就是说你输入密码错误后,需要你输入验证码,但是你关闭浏览器后在打开还是不需要你输入的。你也可以

基于cookie实现哦,原理一样。

      (3)在登录页面中,对验证码加上以下判断:
<c:if test="${sessionScope.LOGIN_FIRST == 'NOTFIRST'}">
这里放验证码的代码哦
</c:if>

      (4)到这里基本上就已经实现了,如果你的有问题可以留言一起讨论。效果如下:


  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值