cas4.2.4 登添加验证码

看了很多添加验证码的博文,唯独没有4.24的 重点看第3条,其余的和别人博文大致相同

1.首先在cas工程的web.xml增加验证码功能的支持

<!-- 验证码功能 -->  
    <servlet>  
        <servlet-name>Kaptcha</servlet-name>  
        <servlet-class>com.google.code.kaptcha.servlet.KaptchaServlet</servlet-class>  
        <init-param>  
            <param-name>kaptcha.border</param-name>  
            <param-value>no</param-value>  
        </init-param>  
        <init-param>  
            <param-name>kaptcha.textproducer.char.space</param-name>  
            <param-value>5</param-value>  
        </init-param>  
        <init-param>  
            <param-name>kaptcha.textproducer.char.length</param-name>  
            <param-value>5</param-value>  
        </init-param>  
    </servlet>  
      
    <servlet-mapping>  
        <servlet-name>Kaptcha</servlet-name>  
        <url-pattern>/captcha.jpg</url-pattern>  
    </servlet-mapping>  
    
2.新建一个类UsernamePasswordCredentialWithAuthCode,该类继承了

org.jasig.cas.authentication.UsernamePasswordCredential,添加一个验证码字段,

并且重写equals和hashCode方法,添加关于验证码比较的信息

package org.jasig.cas.web.flow;

import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;

import org.apache.commons.lang3.builder.HashCodeBuilder;
import org.jasig.cas.authentication.UsernamePasswordCredential;

public class UsernamePasswordCredentialWithAuthCode extends  
        UsernamePasswordCredential {  
    /** 
     * 带验证码的登录界面 
     */  
    private static final long serialVersionUID = 1L;  
    /** 验证码*/  
    @NotNull  
    @Size(min = 1, message = "required.authcode")  
    private String authcode;  
  
    /** 
     *  
     * @return 
     */  
    public final String getAuthcode() {  
        return authcode;  
    }  
  
    /** 
     *  
     * @param authcode 
     */  
    public final void setAuthcode(String authcode) {  
        this.authcode = authcode;  
    }  
  
    
    public UsernamePasswordCredentialWithAuthCode() {
        super();
    }

public UsernamePasswordCredentialWithAuthCode(String userName,
            String password) {
        super(userName, password);
    }

@Override  
    public boolean equals(final Object o) {  
        if (this == o) {  
            return true;  
        }  
        if (o == null || getClass() != o.getClass()) {  
            return false;  
        }  
  
        final UsernamePasswordCredentialWithAuthCode that = (UsernamePasswordCredentialWithAuthCode) o;  
  
        if (getPassword() != null ? !getPassword().equals(that.getPassword())  
                : that.getPassword() != null) {  
            return false;  
        }  
  
        if (getPassword() != null ? !getPassword().equals(that.getPassword())  
                : that.getPassword() != null) {  
            return false;  
        }  
        if (authcode != null ? !authcode.equals(that.authcode)  
                : that.authcode != null)  
            return false;  
  
        return true;  
    }  
  
    @Override  
    public int hashCode() {  
        return new HashCodeBuilder().append(getUsername())  
                .append(getPassword()).append(authcode).toHashCode();  
    }  
  
}

3.新建一个类AuthenticationViaFormAction类,必须写在org.jasig.cas.web.flow包中,原因我是修改源码,红色为添加代码:这样做的原因是因为我实在无法找到去哪里配置bean,看他源码是注解,我配上注解也不管用,也懒得去研究,就这样弄吧!

package org.jasig.cas.web.flow;

import org.apache.commons.lang3.StringUtils;
import org.jasig.cas.CasProtocolConstants;
import org.jasig.cas.CentralAuthenticationService;
import org.jasig.cas.authentication.AuthenticationContext;
import org.jasig.cas.authentication.AuthenticationContextBuilder;
import org.jasig.cas.authentication.AuthenticationException;
import org.jasig.cas.authentication.AuthenticationSystemSupport;
import org.jasig.cas.authentication.AuthenticationTransaction;
import org.jasig.cas.authentication.Credential;
import org.jasig.cas.authentication.DefaultAuthenticationContextBuilder;
import org.jasig.cas.authentication.DefaultAuthenticationSystemSupport;
import org.jasig.cas.authentication.HandlerResult;
import org.jasig.cas.authentication.MessageDescriptor;
import org.jasig.cas.authentication.RootCasException;
import org.jasig.cas.authentication.principal.Service;
import org.jasig.cas.ticket.AbstractTicketException;
import org.jasig.cas.ticket.ServiceTicket;
import org.jasig.cas.ticket.TicketCreationException;
import org.jasig.cas.ticket.TicketGrantingTicket;
import org.jasig.cas.web.support.WebUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.binding.message.MessageBuilder;
import org.springframework.binding.message.MessageContext;
import org.springframework.stereotype.Component;
import org.springframework.web.util.CookieGenerator;
import org.springframework.webflow.core.collection.LocalAttributeMap;
import org.springframework.webflow.execution.Event;
import org.springframework.webflow.execution.RequestContext;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import javax.validation.constraints.NotNull;

import Java.util.Map;

/**
 * Action to authenticate credential and retrieve a TicketGrantingTicket for
 * those credential. If there is a request for renew, then it also generates
 * the Service Ticket required.
 *
 * @author Scott Battaglia
 * @since 3.0.0
 */
@Component("authenticationViaFormAction")
public class AuthenticationViaFormAction {

/** Authentication succeeded with warnings from authn subsystem that should be displayed to user. */
    public static final String SUCCESS_WITH_WARNINGS = "successWithWarnings";

/** Authentication failure result. */
    public static final String AUTHENTICATION_FAILURE = "authenticationFailure";

/** Flow scope attribute that determines if authn is happening at a public workstation. */
    public static final String PUBLIC_WORKSTATION_ATTRIBUTE = "publicWorkstation";

/** Logger instance. **/
    protected final transient Logger logger = LoggerFactory.getLogger(getClass());

/** Core we delegate to for handling all ticket related tasks. */
    @NotNull
    @Autowired
    @Qualifier("centralAuthenticationService")
    private CentralAuthenticationService centralAuthenticationService;

@NotNull
    @Autowired
    @Qualifier("warnCookieGenerator")
    private CookieGenerator warnCookieGenerator;

@NotNull
    @Autowired(required=false)
    @Qualifier("defaultAuthenticationSystemSupport")
    private AuthenticationSystemSupport authenticationSystemSupport = new DefaultAuthenticationSystemSupport();

/**
     * Handle the submission of credentials from the post.
     *
     * @param context the context
     * @param credential the credential
     * @param messageContext the message context
     * @return the event
     * @since 4.1.0
     */
    public final Event submit(final RequestContext context, final Credential credential,
                              final MessageContext messageContext)  {
        if (isRequestAskingForServiceTicket(context)) {
            return grantServiceTicket(context, credential);
        }

return createTicketGrantingTicket(context, credential, messageContext);
    }

/**
     * Is request asking for service ticket?
     *
     * @param context the context
     * @return true, if both service and tgt are found, and the request is not asking to renew.
     * @since 4.1.0
     */
    protected boolean isRequestAskingForServiceTicket(final RequestContext context) {
        final String ticketGrantingTicketId = WebUtils.getTicketGrantingTicketId(context);
        final Service service = WebUtils.getService(context);
        return (StringUtils.isNotBlank(context.getRequestParameters().get(CasProtocolConstants.PARAMETER_RENEW))
                && ticketGrantingTicketId != null
                && service != null);
    }

/**
     * Grant service ticket for the given credential based on the service and tgt
     * that are found in the request context.
     *
     * @param context the context
     * @param credential the credential
     * @return the resulting event. Warning, authentication failure or error.
     * @since 4.1.0
     */
    protected Event grantServiceTicket(final RequestContext context, final Credential credential) {
        final String ticketGrantingTicketId = WebUtils.getTicketGrantingTicketId(context);
        try {
            final Service service = WebUtils.getService(context);
            final AuthenticationContextBuilder builder = new DefaultAuthenticationContextBuilder(
                    this.authenticationSystemSupport.getPrincipalElectionStrategy());
            final AuthenticationTransaction transaction =
                    AuthenticationTransaction.wrap(credential);
            this.authenticationSystemSupport.getAuthenticationTransactionManager().handle(transaction,  builder);
            final AuthenticationContext authenticationContext = builder.build(service);

final ServiceTicket serviceTicketId = this.centralAuthenticationService.grantServiceTicket(
                    ticketGrantingTicketId, service, authenticationContext);
            WebUtils.putServiceTicketInRequestScope(context, serviceTicketId);
            WebUtils.putWarnCookieIfRequestParameterPresent(this.warnCookieGenerator, context);
            return newEvent(AbstractCasWebflowConfigurer.TRANSITION_ID_WARN);

} catch (final AuthenticationException e) {
            return newEvent(AUTHENTICATION_FAILURE, e);
        } catch (final TicketCreationException e) {
            logger.warn("Invalid attempt to access service using renew=true with different credential. Ending SSO session.");
            this.centralAuthenticationService.destroyTicketGrantingTicket(ticketGrantingTicketId);
        } catch (final AbstractTicketException e) {
            return newEvent(AbstractCasWebflowConfigurer.TRANSITION_ID_ERROR, e);
        }
        return newEvent(AbstractCasWebflowConfigurer.TRANSITION_ID_ERROR);

}
    /**
     * Create ticket granting ticket for the given credentials.
     * Adds all warnings into the message context.
     *
     * @param context the context
     * @param credential the credential
     * @param messageContext the message context
     * @return the resulting event.
     * @since 4.1.0
     */
    protected Event createTicketGrantingTicket(final RequestContext context, final Credential credential,
                                               final MessageContext messageContext) {
        try {
            final Service service = WebUtils.getService(context);
            final AuthenticationContextBuilder builder = new DefaultAuthenticationContextBuilder(
                    this.authenticationSystemSupport.getPrincipalElectionStrategy());
            final AuthenticationTransaction transaction =
                    AuthenticationTransaction.wrap(credential);
            this.authenticationSystemSupport.getAuthenticationTransactionManager().handle(transaction,  builder);
            final AuthenticationContext authenticationContext = builder.build(service);

final TicketGrantingTicket tgt = this.centralAuthenticationService.createTicketGrantingTicket(authenticationContext);
            WebUtils.putTicketGrantingTicketInScopes(context, tgt);
            WebUtils.putWarnCookieIfRequestParameterPresent(this.warnCookieGenerator, context);
            putPublicWorkstationToFlowIfRequestParameterPresent(context);
            if (addWarningMessagesToMessageContextIfNeeded(tgt, messageContext)) {
                return newEvent(SUCCESS_WITH_WARNINGS);
            }
            return newEvent(AbstractCasWebflowConfigurer.TRANSITION_ID_SUCCESS);

} catch (final AuthenticationException e) {
            logger.debug(e.getMessage(), e);
            return newEvent(AUTHENTICATION_FAILURE, e);
        } catch (final Exception e) {
            logger.debug(e.getMessage(), e);
            return newEvent(AbstractCasWebflowConfigurer.TRANSITION_ID_ERROR, e);
        }
    }

/**
     * Add warning messages to message context if needed.
     *
     * @param tgtId the tgt id
     * @param messageContext the message context
     * @return true if warnings were found and added, false otherwise.
     * @since 4.1.0
     */
    protected boolean addWarningMessagesToMessageContextIfNeeded(final TicketGrantingTicket tgtId, final MessageContext messageContext) {
        boolean foundAndAddedWarnings = false;
        for (final Map.Entry<String, HandlerResult> entry : tgtId.getAuthentication().getSuccesses().entrySet()) {
            for (final MessageDescriptor message : entry.getValue().getWarnings()) {
                addWarningToContext(messageContext, message);
                foundAndAddedWarnings = true;
            }
        }
        return foundAndAddedWarnings;

}

/**
     * Put public workstation into the flow if request parameter present.
     *
     * @param context the context
     */
    private static void putPublicWorkstationToFlowIfRequestParameterPresent(final RequestContext context) {
        if (StringUtils.isNotBlank(context.getExternalContext()
                .getRequestParameterMap().get(PUBLIC_WORKSTATION_ATTRIBUTE))) {
            context.getFlowScope().put(PUBLIC_WORKSTATION_ATTRIBUTE, Boolean.TRUE);
        }
    }

/**
     * New event based on the given id.
     *
     * @param id the id
     * @return the event
     */
    private Event newEvent(final String id) {
        return new Event(this, id);
    }

/**
     * New event based on the id, which contains an error attribute referring to the exception occurred.
     *
     * @param id the id
     * @param error the error
     * @return the event
     */
    private Event newEvent(final String id, final Exception error) {
        return new Event(this, id, new LocalAttributeMap("error", error));
    }

/**
     * Adds a warning message to the message context.
     *
     * @param context Message context.
     * @param warning Warning message.
     */
    private static void addWarningToContext(final MessageContext context, final MessageDescriptor warning) {
        final MessageBuilder builder = new MessageBuilder()
                .warning()
                .code(warning.getCode())
                .defaultText(warning.getDefaultMessage())
                .args(warning.getParams());
        context.addMessage(builder.build());
    }

public void setCentralAuthenticationService(final CentralAuthenticationService centralAuthenticationService) {
        this.centralAuthenticationService = centralAuthenticationService;
    }

public void setWarnCookieGenerator(final CookieGenerator warnCookieGenerator) {
        this.warnCookieGenerator = warnCookieGenerator;
    }

public void setAuthenticationSystemSupport(final AuthenticationSystemSupport authenticationSystemSupport) {
        this.authenticationSystemSupport = authenticationSystemSupport;
    }
    
    
    public final String validatorCode(final RequestContext context,
            final Credential credentials, final MessageContext messageContext)
            throws Exception {
        final HttpServletRequest request = WebUtils
                .getHttpServletRequest(context);
        HttpSession session = request.getSession();
        //生成的验证码
        String authcode = (String) session
                .getAttribute(com.google.code.kaptcha.Constants.KAPTCHA_SESSION_KEY);
        session.removeAttribute(com.google.code.kaptcha.Constants.KAPTCHA_SESSION_KEY);

UsernamePasswordCredentialWithAuthCode upc = (UsernamePasswordCredentialWithAuthCode) credentials;
        //用户 输入的验证码
        String submitAuthcode = upc.getAuthcode();
        if (StringUtils.isEmpty(submitAuthcode)
                || StringUtils.isEmpty(authcode)) {
            populateErrorsInstance(new NullAuthcodeAuthenticationException(),
                    messageContext);
            return "error";
        }
        if (submitAuthcode.equalsIgnoreCase(authcode)) {
            return "success";
        }
        populateErrorsInstance(new BadAuthcodeAuthenticationException(),
                messageContext);
        return "error";
    }

private void populateErrorsInstance(final RootCasException e,
            final MessageContext messageContext) {

try {
            messageContext.addMessage(new MessageBuilder().error()
                    .code(e.getCode()).defaultText(e.getCode()).build());
        } catch (final Exception fe) {
            logger.error(fe.getMessage(), fe);
        }
    }
    
    
}

4.定义异常类NullAuthcodeAuthenticationException和BadAuthcodeAuthenticationException:

package org.jasig.cas.web.flow;

import org.jasig.cas.authentication.RootCasException;

public class NullAuthcodeAuthenticationException extends RootCasException {

/** Serializable ID for unique id. */
    private static final long serialVersionUID = 5501212207531289993L;

/** Code description. */
    public static final String CODE = "required.authcode";

/**
     * Constructs a TicketCreationException with the default exception code.
     */
    public NullAuthcodeAuthenticationException() {
        super(CODE);
    }

/**
     * Constructs a TicketCreationException with the default exception code and
     * the original exception that was thrown.
     * 
     * @param throwable
     *            the chained exception
     */
    public NullAuthcodeAuthenticationException(final Throwable throwable) {
        super(CODE, throwable);
    }
}

----------------------------------------------------------------------------------------------------------------------------------

package org.jasig.cas.web.flow;

import org.jasig.cas.authentication.RootCasException;

public class BadAuthcodeAuthenticationException extends RootCasException {

/** Serializable ID for unique id. */
    private static final long serialVersionUID = 5501212207531289993L;

/** Code description. */
    public static final String CODE = "error.authentication.authcode.bad";

/**
     * Constructs a TicketCreationException with the default exception code.
     */
    public BadAuthcodeAuthenticationException() {
        super(CODE);
    }

/**
     * Constructs a TicketCreationException with the default exception code and
     * the original exception that was thrown.
     * 
     * @param throwable
     *            the chained exception
     */
    public BadAuthcodeAuthenticationException(final Throwable throwable) {
        super(CODE, throwable);
    }
}

5、在login_webflow.xml修改登录验证流程:

修改UsernamePasswordCredentialWithAuthCode你自己定义的路劲

验证码校验:

<transition on="submit" bind="true" validate="true"
            to="validatorCode" />
        <!-- <transition on="submit" bind="true" validate="true" to="realSubmit" 
            /> -->
    </view-state>

<!-- 新添加的校验验证码 -->

<action-state id="validatorCode">
<evaluate
expression="authenticationViaFormAction.validatorCode(flowRequestContext, flowScope.credential, messageContext)" />
<transition on="error" to="generateLoginTicket"/>
<transition on="success" to="realSubmit" />
</action-state>

6、messages_zh_CN.properties增加国际化显示信息:

screen.welcome.label.authcode=\u9A8C\u8BC1\u7801:

screen.welcome.label.authcode.accesskey=a

required.authcode=\u5FC5\u987B\u5F55\u5165\u9A8C\u8BC1\u7801\u3002

error.authentication.authcode.bad=\u9A8C\u8BC1\u7801\u8F93\u5165\u6709\u8BEF\u3002

7.登录页面casLoginView.jsp添加验证码输入框:

<!-- 验证码 -->
            <spring:message code="screen.welcome.label.authcode" />
            <img onclick="this.src=‘captcha.jpg?‘+Math.random()" width="93"
                height="30" src="captcha.jpg">
          
            <div class="login-ic">
                <i class="icys"></i>
                <form:input cssClass="required" cssErrorClass="error" id="authcode"
                    size="10" tabindex="2" path="authcode"
                    accesskey="${authcodeAccessKey}" htmlEscape="true"
                    autocomplete="off" />
                <div class="clear"></div>

</div>

8、如果要默认中文页面显示,修改cas-servlet.xml 下的local Resolver默认值为zh_CN:

<bean id="localeResolver" class="org.springframework.web.servlet.i18n.CookieLocaleResolver" p:defaultLocale="zh_CN" />

时间: 2024-11-10 16:05:35

cas4.2.4 登添加验证码的相关文章

【试水CAS-4.0.3】第03节_CAS服务端登录页添加验证码

/** * @see ------------------------------------------------------------------------------------------------------------------------ * @see CAS登录页添加验证码 * @see 0.这年头验证码一般用来防止帐号被暴力破解,如果我们的系统是走专线的,也就是说放在内网,那完全没必要搞验证码 * @see 1.由于CAS使用了Spring Web Flow框架,所以

yii2中添加验证码的实现方法

本文实例讲述了yii2中添加验证码的实现方法.分享给大家供大家参考,具体如下: 首先,在模型中添加验证码字段: ? 1 2 3 public function rules(){ return ['verifyCode', 'captcha'], } 其次,可以在函数attributeLabels中添加前台页面中验证码的字段名称: ? 1 2 3 public function atrributeLabels(){ return ['verifyCode'=>'Verification Code'

前后端分离之后添加验证码

转载自:http://www.cnblogs.com/liminjun88/p/6556493.html#commentform 1.背景介绍 团队开发的项目,前端基于Bootstrap+AngularJS,后端Spring MVC以RESTful接口给前端调用.开发和部署都是前后端分离.项目简单部署图如下,因为后台同时采用微服务的方式,所以后台不止3个,画图示意.终极方案是采用Docker,在前端和后台调用中间添加一层:API Gateway. 因为考虑到和其他系统集成的可能性,所以在登录这一

PHPCMS v9 自定义表单添加验证码验证

1. 在 \phpcms\templates\default\formguide\show.html 中添加验证码显示 <input type="text" id="code" name="code" size="8" class="input-text">{form::checkcode('code_img', '4', '14', 84, 24)} 2. 在 \phpcms\modules\

PHPCMS v9 自定义表单添加验证码

1.  在 \phpcms\templates\default\formguide\show.html 中添加验证码显示 <input type="text" id="code" name="code" size="8" class="input-text">{form::checkcode('code_img', '4', '14', 84, 24)} 2. 在 \phpcms\modules

Membership添加验证码登录

1.在公共类ImageHelper中编写公共方法,产生随机验证码 /// <summary> /// 产生随机验证码 /// </summary> /// <returns></returns> public string GetString() { string randString = ""; Random random = new Random(); do { //使用DateTime.Now.Millisecond作为生成随机数的

WordPress优化:给后台登录添加验证码以及登录限制

为了防止后台被某些黑客进行密码爆破,添加验证码以及登录限制是很有必要的.这里我分享两个插件,分别是:SI CAPTCHA Anti-Spam 和 Limit Login Attempts .一个是验证码,另一个是限制登录尝试.这两个插件直接在网站后台搜索安装就可以了 开启两个插件后,后台登录效果如下: 好了,有兴趣的小伙伴可以试试O(∩_∩)O~

CAS添加验证码功能

1.  cas.war 下面的web-inf/web.xml  lib添加  kaptcha.jar kaptcha.jar通过maven获取 <dependency> <groupId>com.github.axet</groupId> <artifactId>kaptcha</artifactId> <version>0.0.9</version> </dependency> 这个maven 包含两个 ja

yii登陆中添加验证码

1.在SiteController中添加如下代码: Php代码   /** * Declares class-based actions. */ public function actions() { return array( // captcha action renders the CAPTCHA image displayed on the contact page 'captcha' => array( 'class' => 'CCaptchaAction', 'backColor'