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" />
cas4.2.4 登添加验证码的更多相关文章
- asp.net添加验证码
1.新建一个aspx页面生成验证码图像 using System; using System.Data; using System.Configuration; using System.Collec ...
- PHPCMS v9 自定义表单添加验证码验证
1. 在 \phpcms\templates\default\formguide\show.html 中添加验证码显示 <input type="text" id=" ...
- Angular企业级开发(9)-前后端分离之后添加验证码
1.背景介绍 团队开发的项目,前端基于Bootstrap+AngularJS,后端Spring MVC以RESTful接口给前端调用.开发和部署都是前后端分离.项目简单部署图如下,因为后台同时采用微服 ...
- PHPCMS v9 自定义表单添加验证码
1. 在 \phpcms\templates\default\formguide\show.html 中添加验证码显示 <input type="text" id=&quo ...
- [phpcms v9]自定义表单添加验证码验证功能
修改 \phpcms\templates\default\formguide\show.html 中添加验证码显示 <input type="text" id=" ...
- 【转】PHPCMS v9 自定义表单添加验证码验证
1. 在 \phpcms\templates\default\formguide\show.html 中添加验证码显示 <input type="text" id=&quo ...
- C# DateTime的11种构造函数 [Abp 源码分析]十五、自动审计记录 .Net 登陆的时候添加验证码 使用Topshelf开发Windows服务、记录日志 日常杂记——C#验证码 c#_生成图片式验证码 C# 利用SharpZipLib生成压缩包 Sql2012如何将远程服务器数据库及表、表结构、表数据导入本地数据库
C# DateTime的11种构造函数 别的也不多说没直接贴代码 using System; using System.Collections.Generic; using System.Glob ...
- cas添加验证码
cas添加验证码,折腾了好久,终于整理好了,很大部分都是借鉴http://binghejinjun.iteye.com/blog/1255293这个的.但是他的有一个很不好的地方就是不能提升验证码错误 ...
- yii登陆中添加验证码
1.在SiteController中添加如下代码: /** * Declares class-based actions. */ public function actions() { return ...
随机推荐
- 【javascript】内存泄露及其解决办法
1.内存泄露:一般由于开发者使用不当导致不用的内存没有被操作系统或者空闲内存池回收释放. 2.造成内存泄露的常见原因: 1) 意外的全局变量引起的内存泄露 2)闭包引起的内存泄露 闭包可以维持函数内局 ...
- Linux服务器安装部署redis
参考地址: redis教程:http://www.runoob.com/redis/redis-tutorial.html redis百度百科:https://baike.baidu.com/item ...
- flask 重定向到上一个页面,referrer、next参数
重定向会上一个页面 在某些场景下,我们需要在用户访问某个url后重定向会上一个页面,比如用户点击某个需要登录才能访问的连接,这时程序会重定向到登录页面,当用户登录后比较合理的行为是重定向到用户登录前浏 ...
- ActiveMQ任意文件写入漏洞(版本在5.12.X前CVE-2016-3088)
ActiveMQ任意文件写入漏洞(版本在5.12.X前CVE-2016-3088) 查看docker的activemq版本命令:$ docker ps | grep activemq927860512 ...
- php CI框架中URL特殊字符处理与SQL注入隐患
php CI框架中URL特殊字符处理与SQL注入隐患 php CI框架中URL特殊字符有很多是不支持的,导致像c++,括号这些常用的分类,字符都无法正常显示很头痛,而在配置里增加单引号' 反斜杠\ 这 ...
- git push跳过用户名和密码认证配置教程
在使用git commit命令将修改从暂存区提交到本地版本库后,只剩下最后一步将本地版本库的分支推送到远程服务器上对应的分支了,如果不清楚版本库的构成,可以查看我的另一篇,git 仓库的基本结构. 新 ...
- Django框架----分页器(paginator)
Django的分页器(paginator) view.py from django.shortcuts import render,HttpResponse # Create your views h ...
- 自写Jquery插件 Menu
原创文章,转载请注明出处,谢谢!https://www.cnblogs.com/GaoAnLee/p/9067543.html 可以结合我自写的Jquery插件Tab 一起使用哦 上一个整体效果 直接 ...
- django自定义错误响应
在做一个web时,总是会出现各种错误,如400.403.404.500等.一般开发都要做对应的处理,给一些友好提示,或返回一些公益广告等. 在Django中,默认提供了常见的错误处理方式,比如: ha ...
- php 获取今日、昨日、上周、本周、本月、上月、今年的起始时间戳和结束时间戳的方法
//php获取今日开始时间戳和结束时间戳 $beginToday=mktime(0,0,0,date('m'),date('d'),date('Y')); $endToday=mktime(0,0,0 ...