【SSO单点系列】(3):CAS4.0 登录页验证码的添加

2016.08.23 更新

注意:这个教程只适合4.0版本的,4.1以及以上的版本的已经不试用了, 后面几篇有人提到过

 

源码网盘链接更新了下 : 链接: http://pan.baidu.com/s/1ntJ7KvR 密码: svhb

2015.8.14更新

有园子 说看不到验证码的错误提示,请参考40楼回复进行修改

附上:

解决方案:
1.把版本升到最新的 v4.0.4
2.然后需要把CnBlogAuthenticationViaFormAction 类中
new MessageBuilder().code(“xxx”).build();
return "error"
改成
new MessageBuilder().error().code(“xxx”).build();
returnnewEvent(ERROR);
依次改就ok了

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

 

这一篇主要是讲解怎么在登录页上添加验证码功能,默认的登录页是只有用户名与密码功能。其他我觉得加验证码没什么用,因为现在我部门做的系统主要是放在内网里,外网是不能访问的。登录页的验证码主要是为了防止进账号进行暴力破解,不过我觉得客户估计也不会没事去搞这玩意。以上只是我自己的个人见解,可能有失偏颇,就当作是对客户的愤怒的一种发泄吧,大家看看就好,最近真是被客户搞得头都大了。不过,如果你的系统放在外网上,那验证码是必须要加上的 。  好了,牢骚发的差不多了,下面进入正题吧!

 

最终效果图

简单做了个页面,一般情况的话都会有美工设计好界面,然后大家进行开发就行了。验证码插件 用的是 kaptcha ,具体用法网上很多,大家google一下就搜到了,用起来蛮简单的。

 

开发

现在开始讲解怎么在单点流程中添加验证码验证码的操作!

 

工程导入

在第一篇 环境的架设中,我们都是直接在tomcat下面操作的,现在我们需要把cas server 导入到我们的eclipse中,才能继续进行操作。

找到我们下载的 cas-server-4.0.0-release.zip  解压,进入子目录找到 cas-server-webapp 工程,因为代码使用maven搭建的,所有导入时选择maven导入。导入完成后,大致的结构如下:

ps:需要注意的是,大家要把第二篇里面修改的内容添加到你导入的工程里,不然会没效果的,大家一定注意。

 

 

 

配置修改

1.打开 login-webflow.xml 文件,大家可能会觉得有点熟悉 。对的,cas有使用Spring Web Flow框架。 找到下面代码:

 

<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>

 

大家看到没,这边有一个form (viewLoginForm),里面有username、password两个属性,没错,这就是对应我们登录页面上的表单。所以我们要在这边加上验证码这个属性。

 

        <binder>
            <binding property="username" />
            <binding property="password" />
             <!-- 新添加 -->
            <binding property="captcha" />
        </binder>    

 

 

 

2.我们只在这边添加一个属性后,够吗?当然不够,因为这个配置实际上有在代码中对应一个java类 UsernamePasswordCredential.java,具体路径为 org.jasig.cas.authentication.UsernamePasswordCredential.java ,查看源码看看,实际上就是一个javabean而已。那么我们就可以继承它,然后加上我们的captcha 属性!完成后的代码如下:

 

public class UsernamePasswordCaptchaCredential extends
        UsernamePasswordCredential {

    /**
     * 
     */
    private static final long serialVersionUID = -864735145551932618L;
    @NotNull
    @Size(min=1,message = "required.captcha")
    private String captcha;
    
    //省略set、get方法
}

 

 

 

 

3.好了,新的javabean诞生了。够了吗?实际还有一个地方要修改,回到 login-webflow.xml 文件,第27行左右,修改如下:

   <!-- 修改后前 -->
    <var name="credential" class="org.jasig.cas.authentication.UsernamePasswordCredential" />
    
    <!-- 修改后 -->
   <!--  <var name="credential" class="org.jasig.cas.authentication.UsernamePasswordCredential" /> -->
    
    <var name="credential" class="org.jasig.cas.authentication.UsernamePasswordCaptchaCredential" />

 

如果大家包名、类名都和原来一样,那么这步可以跳过。

ps:4.0以前的类是  org.jasig.cas.authentication.principal.UsernamePasswordCredentials.java ,4.0以后有变化,大家要注意。

 

4.好了,接下来要添加校验验证码的流程了,还是刚才viewLoginForm 那里,我们把它修改成下面:

    <!-- 修改前 -->
    <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="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="validatorCaptcha"> <evaluate expression="authenticationViaFormAction.doBind(flowRequestContext, flowScope.credential)" /> </transition> </view-state> <!-- 添加一个 validatorCaptcha 校验验证码的操作 --> <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>

 

我们在配置中添加了一个 validatorCaptcha 的操作,同时可以看到 expressionauthenticationViaFormAction.validatorCaptcha(...)

所以我们需要在  authenticationViaFormAction 中添加一个校验验证码的方法 validatorCaptcha()。

authenticationViaFormAction 这个bean是配置在 cas-servlet.xml 中的:

 

  <bean id="authenticationViaFormAction" class="org.jasig.cas.web.flow.AuthenticationViaFormAction"
        p:centralAuthenticationService-ref="centralAuthenticationService"
        p:warnCookieGenerator-ref="warnCookieGenerator"
        p:ticketRegistry-ref="ticketRegistry"/>

 

 

 

我们可以看看 org.jasig.cas.web.flow.AuthenticationViaFormAction 的源代码,里面有一个 submit 方法,这个就是我们提交表单时的方法了。

我们也重写下吧,大概修改成下面的:

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().code("required.captcha").build()); 
                return "error";    
            }  
            if(submitAuthcodeCaptcha.equals(captcha)){    
                return "success";  
            }  
            messageContext.addMessage(new MessageBuilder().code("error.authentication.captcha.bad").build());
            return "error";    
    }
}

 

这边有抛出两个异常,这两个异常信息 required.captchaerror.authentication.captcha.bad 需要在 messages_zh_CN.properties 文件下添加

required.captcha=必须输入验证码。
error.authentication.captcha.bad=您输入的验证码有误。

 

然后把 authenticationViaFormAction 这个Bean路径修改为我们新添加的链接,这个就不贴了,大家照上面改就行了

修改over!

 

总结

这样,添加验证码的操作基本就完成了,大家可以尝试看看 。效果图,已经贴在帖子的最前面了。

 

一个人的我,只能在这 边写博客边祝福大家 平安夜 ,多吃苹果,平平安安。

。。。
打完收工
posted @ 2014-12-25 00:17  icodeit  阅读(12866)  评论(64编辑  收藏  举报