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)到這裏基本上就已經實現了,如果你的有問題可以留言一起討論。效果如下:


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章