cas sso单点登录系列5_cas单点登录增加验证码功能完整步骤
转:http://blog.csdn.net/ae6623/article/details/8919718
本篇教程cas-server端下载地址:解压后,直接放到tomcat的webapp目录下就能用了,不过你需要登录的话,要修改数据源,C:\tomcat7\webapps\casServer\WEB-INF\deployerConfigContext.xml,嗯。地址:http://pan.baidu.com/share/link?shareid=439449164&uk=436295647
环境:
server端:cas-server-core-3.5.2.jar、cas-client-core-3.2.1.jar
client端:cas-client-core-3.1.3.jar、http屏蔽了https后的casclient.jar(http://blog.csdn.net/dengtaowei/article/details/7039399)
之前做的界面里面缺少一个验证码的功能,上周由于搞其他事情去了,就没有开始验证码的教程写作,今天补上,希望能按照教程制作出你们想要的功能。
结果图:
至此为止,五篇教程,自定义的java类不是很多,还不是很深入。包结构和jar包如下图,程序去我的csdn下载频道下载。
C:\TOMCAT7\WEBAPPS\CASSERVER\WEB-INF\CLASSES\ORG
└─jasig
└─cas
├─authentication
│ └─handler
│ │ CaptchaImageLoginCredentials.class
│ │ Crypt.class
│ │ ImageVaditeAuthenticationViaFormAction.class
│ │ MD5.class
│ │ RsCasDaoAuthenticationHandler.class
│ │
│ ├─captchaImage
│ │ CaptchaImageCreateController.class
│ │
│ └─util
│ ValidatorCodeUtil$ValidatorCode.class
│ ValidatorCodeUtil.class
│
├─util
│ AutowiringSchedulerFactoryBean.class
│
└─web
│ FlowExecutionExceptionResolver.class
│
└─flow
GatewayServicesManagementCheck.class
ServiceAuthorizationCheck.class
1.cas-servlet.xml
.找到C:\tomcat7\webapps\casServer\WEB-INF\cas-servlet.xml文件,在
<span style="font-family:Microsoft YaHei;font-size:14px;"><bean
id="handlerMappingC"
class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<props>
<prop key="/logout">logoutController</prop>
<prop key="/serviceValidate">serviceValidateController</prop>
<prop key="/validate">legacyValidateController</prop>
<prop key="/proxy">proxyController</prop>
<prop key="/proxyValidate">proxyValidateController</prop>
<prop key="/samlValidate">samlValidateController</prop>
<prop key="/services/add.html">addRegisteredServiceSimpleFormController</prop>
<prop key="/services/edit.html">editRegisteredServiceSimpleFormController</prop>
<prop key="/services/loggedOut.html">serviceLogoutViewController</prop>
<prop key="/services/viewStatistics.html">viewStatisticsController</prop>
<prop key="/services/*">manageRegisteredServicesMultiActionController</prop>
<prop key="/openid/*">openIdProviderController</prop>
<prop key="/authorizationFailure.html">passThroughController</prop>
<prop key="/403.html">passThroughController</prop>
<prop key="/status">healthCheckController</prop>
<!--增加验证码的功能-->
<prop key="/captcha.htm">captchaImageCreateController</prop> </props>
</property>
<property
name="alwaysUseFullPath" value="true"/>
<!--
uncomment this to enable sending PageRequest events.
<property
name="interceptors">
<list>
<ref bean="pageRequestHandlerInterceptorAdapter" />
</list>
</property>
-->
</bean></span>
captchaImageCreateController需要我们自己写java类
在上述xml代码后面继续添加一个bean,如下,而类class路径是我们自己写的,在myeclipse里面自己diy的包名org.jasig.cas.authentication.handler.captchaImage.CaptchaImageCreateController
<span style="font-family:Microsoft YaHei;font-size:14px;"><!--增加一个bean处理验证码-->
<bean id="captchaImageCreateController" class="org.jasig.cas.authentication.handler.captchaImage.CaptchaImageCreateController"></bean></span>
2.然后我们开始写这个CaptchaImageCreateController类
org.jasig.cas.authentication.handler.captchaImage.CaptchaImageCreateController
CaptchaImageCreateController.java
/**
* Project Name:casServerHandler
* File Name:CaptchaImageCreateController.java
* Package Name:org.jasig.cas.authentication.handler.captchaImage
* Date:2013-4-28下午03:04:06
* Copyright (c) 2013, riambsoft All Rights Reserved.
*
*/ package org.jasig.cas.authentication.handler.captchaImage;
import java.io.IOException; import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import org.jasig.cas.authentication.handler.util.ValidatorCodeUtil;
import org.jasig.cas.authentication.handler.util.ValidatorCodeUtil.ValidatorCode; import org.springframework.beans.factory.InitializingBean;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller; import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGImageEncoder;
// import com.wokejia.flow.ValidatorCodeUtil.ValidatorCode; public class CaptchaImageCreateController implements Controller, InitializingBean { public void afterPropertiesSet() throws Exception { } public ModelAndView handleRequest(HttpServletRequest arg0,
HttpServletResponse response) throws Exception {
ValidatorCode codeUtil = ValidatorCodeUtil.getCode();
System.out.println("code="+codeUtil.getCode()); arg0.getSession().setAttribute("code", codeUtil.getCode());
// 禁止图像缓存。
response.setHeader("Pragma", "no-cache");
response.setHeader("Cache-Control", "no-cache");
response.setDateHeader("Expires", 0);
response.setContentType("image/jpeg"); ServletOutputStream sos = null;
try {
// 将图像输出到Servlet输出流中。
sos = response.getOutputStream();
JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(sos);
encoder.encode(codeUtil.getImage());
sos.flush();
sos.close();
} catch (Exception e) {
} finally {
if (null != sos) {
try {
sos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return null;
}
}
3.开始搞验证码图片生成java类的编写:
这个类中用到了网上经常用的验证码生成类,这个类你可以自己随便写,下面提供一个网上写的,生成的验证码挺漂亮的。
import org.jasig.cas.authentication.handler.util.ValidatorCodeUtil;
import org.jasig.cas.authentication.handler.util.ValidatorCodeUtil.ValidatorCode;
ValidatorCode类是ValidatorCodeUtil类的一个内部类,代码如下
ValidatorCode.java
/**
* Project Name:casServerHandler
* File Name:ValidatorCodeUtil.java
* Package Name:org.jasig.cas.authentication.handler.util
* Date:2013-4-28下午03:01:38
* Copyright (c) 2013, riambsoft All Rights Reserved.
*
*/ package org.jasig.cas.authentication.handler.util; import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.util.Random;
/**
* ClassName:ValidatorCodeUtil <br/> Function: TODO ADD FUNCTION. <br/> Reason: TODO ADD REASON. <br/> Date: 2013-4-28 下午03:01:38 <br/>
*
* @author Administrator
* @version
* @since JDK 1.5
* @see
*/
public class ValidatorCodeUtil {
public static ValidatorCode getCode() {
// 验证码图片的宽度。
int width = 80;
// 验证码图片的高度。
int height = 30;
BufferedImage buffImg = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
Graphics2D g = buffImg.createGraphics(); // 创建一个随机数生成器类。
Random random = new Random(); // 设定图像背景色(因为是做背景,所以偏淡)
g.setColor(Color.WHITE);
g.fillRect(0, 0, width, height);
// 创建字体,字体的大小应该根据图片的高度来定。
Font font = new Font("微软雅黑", Font.HANGING_BASELINE, 28);
// 设置字体。
g.setFont(font); // 画边框。
g.setColor(Color.BLACK);
g.drawRect(0, 0, width - 1, height - 1);
// 随机产生155条干扰线,使图象中的认证码不易被其它程序探测到。
// g.setColor(Color.GRAY);
// g.setColor(getRandColor(160, 200));
// for (int i = 0; i < 155; i++) {
// int x = random.nextInt(width);
// int y = random.nextInt(height);
// int xl = random.nextInt(12);
// int yl = random.nextInt(12);
// g.drawLine(x, y, x + xl, y + yl);
// } // randomCode用于保存随机产生的验证码,以便用户登录后进行验证。
StringBuffer randomCode = new StringBuffer(); // 设置默认生成4个验证码
int length = 4;
// 设置备选验证码:包括"a-z"和数字"0-9"
String base = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; int size = base.length(); // 随机产生4位数字的验证码。
for (int i = 0; i < length; i++) {
// 得到随机产生的验证码数字。
int start = random.nextInt(size);
String strRand = base.substring(start, start + 1); // 用随机产生的颜色将验证码绘制到图像中。
// 生成随机颜色(因为是做前景,所以偏深)
// g.setColor(getRandColor(1, 100)); // 调用函数出来的颜色相同,可能是因为种子太接近,所以只能直接生成
g.setColor(new Color(20 + random.nextInt(110), 20 + random.nextInt(110), 20 + random.nextInt(110)));
g.drawString(strRand, 15 * i + 6, 24); // 将产生的四个随机数组合在一起。
randomCode.append(strRand);
} // 图象生效
g.dispose();
ValidatorCode code = new ValidatorCode();
code.image = buffImg;
code.code = randomCode.toString();
return code;
} // 给定范围获得随机颜色
static Color getRandColor(int fc, int bc) {
Random random = new Random();
if (fc > 255)
fc = 255;
if (bc > 255)
bc = 255;
int r = fc + random.nextInt(bc - fc);
int g = fc + random.nextInt(bc - fc);
int b = fc + random.nextInt(bc - fc);
return new Color(r, g, b);
} /**
*
* <p class="detail">
* 验证码图片封装
* </p>
*
* @ClassName: ValidatorCode
* @version V1.0
* @date 2012-4-9 下午07:24:14
* @author 罗伟俊
*
*/
public static class ValidatorCode {
private BufferedImage image;
private String code; /**
* <p class="detail">
* 图片流
* </p>
*
* @return
*/
public BufferedImage getImage() {
return image;
} /**
* <p class="detail">
* 验证码
* </p>
*
* @return
*/
public String getCode() {
return code;
}
}
}
4.验证码生成做完了,那么我们开始修改默认的认证器的认证方式,增加验证码验证
自己新建一个java类:
ImageVaditeAuthenticationViaFormAction.java,此类其实是改造的org.jasig.cas.web.flow.AuthenticationViaFormAction.java这个类,它里面本来只是验证用户名和密码,我们增加一个成员变量,code,然后在验证用户名和密码之前,我们先开始验证验证码。
/*
* Licensed to Jasig under one or more contributor license
* agreements. See the NOTICE file distributed with this work
* for additional information regarding copyright ownership.
* Jasig licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a
* copy of the License at the following location:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jasig.cas.authentication.handler; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.constraints.NotNull; import org.jasig.cas.CentralAuthenticationService;
import org.jasig.cas.authentication.handler.AuthenticationException;
import org.jasig.cas.authentication.principal.Credentials;
import org.jasig.cas.authentication.principal.Service;
import org.jasig.cas.ticket.TicketException;
import org.jasig.cas.web.bind.CredentialsBinder;
import org.jasig.cas.web.support.WebUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.binding.message.MessageBuilder;
import org.springframework.binding.message.MessageContext;
import org.springframework.util.StringUtils;
import org.springframework.web.util.CookieGenerator;
import org.springframework.webflow.execution.RequestContext; /**
* Action to authenticate credentials and retrieve a TicketGrantingTicket for those credentials. If there is a request for renew, then it also generates the Service Ticket required.
*
* @author Scott Battaglia
* @version $Revision$ $Date$
* @since 3.0.4
*/
public class ImageVaditeAuthenticationViaFormAction { // 验证码参数:
private String code = "code"; /**
* Binder that allows additional binding of form object beyond Spring defaults.
*/
private CredentialsBinder credentialsBinder; /** Core we delegate to for handling all ticket related tasks. */
@NotNull
private CentralAuthenticationService centralAuthenticationService; @NotNull
private CookieGenerator warnCookieGenerator; protected Logger logger = LoggerFactory.getLogger(getClass()); public final void doBind(final RequestContext context, final Credentials credentials) throws Exception {
final HttpServletRequest request = WebUtils.getHttpServletRequest(context); if (this.credentialsBinder != null && this.credentialsBinder.supports(credentials.getClass())) {
this.credentialsBinder.bind(request, credentials);
}
} public final String submit(final RequestContext context, final Credentials credentials, final MessageContext messageContext) throws Exception { // 检测验证码
if (credentials instanceof CaptchaImageLoginCredentials) {
// 这个类也是我们自己搞的,里面能取到验证码
CaptchaImageLoginCredentials rmupc = (CaptchaImageLoginCredentials) credentials;
// 从session中取出生成验证码的时候就保存在session中的验证码
String sessionCode = (String) WebUtils.getHttpServletRequest(context).getSession().getAttribute(code); // 如果验证码为null
if (rmupc.getCode() == null) {
// 写入日志
logger.warn("验证码为空");
// 错误信息,会在配置文件(messages_zh_CN.properties)里面先定义好
final String code = "login.code.tip";
// 发送错误信息到前台
messageContext.addMessage(new MessageBuilder().error().code(code).arg("").defaultText(code).build());
return "error";
}
// 如果验证码不正确
if (!rmupc.getCode().toUpperCase().equals(sessionCode.toUpperCase())) {
logger.warn("验证码检验有误");
final String code = "login.code.error";
messageContext.addMessage(new MessageBuilder().error().code(code).arg("").defaultText(code).build());
return "error";
} } // Validate login ticket
final String authoritativeLoginTicket = WebUtils.getLoginTicketFromFlowScope(context);
final String providedLoginTicket = WebUtils.getLoginTicketFromRequest(context);
if (!authoritativeLoginTicket.equals(providedLoginTicket)) {
this.logger.warn("Invalid login ticket " + providedLoginTicket);
final String code = "INVALID_TICKET";
messageContext.addMessage(new MessageBuilder().error().code(code).arg(providedLoginTicket).defaultText(code).build());
return "error";
} final String ticketGrantingTicketId = WebUtils.getTicketGrantingTicketId(context);
final Service service = WebUtils.getService(context);
if (StringUtils.hasText(context.getRequestParameters().get("renew")) && ticketGrantingTicketId != null && service != null) { try {
final String serviceTicketId = this.centralAuthenticationService.grantServiceTicket(ticketGrantingTicketId, service, credentials);
WebUtils.putServiceTicketInRequestScope(context, serviceTicketId);
putWarnCookieIfRequestParameterPresent(context);
return "warn";
} catch (final TicketException e) {
if (isCauseAuthenticationException(e)) {
populateErrorsInstance(e, messageContext);
return getAuthenticationExceptionEventId(e);
} this.centralAuthenticationService.destroyTicketGrantingTicket(ticketGrantingTicketId);
if (logger.isDebugEnabled()) {
logger.debug("Attempted to generate a ServiceTicket using renew=true with different credentials", e);
}
}
} try {
WebUtils.putTicketGrantingTicketInRequestScope(context, this.centralAuthenticationService.createTicketGrantingTicket(credentials));
putWarnCookieIfRequestParameterPresent(context);
return "success";
} catch (final TicketException e) {
populateErrorsInstance(e, messageContext);
if (isCauseAuthenticationException(e))
return getAuthenticationExceptionEventId(e);
return "error";
}
} private void populateErrorsInstance(final TicketException 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);
}
} private void putWarnCookieIfRequestParameterPresent(final RequestContext context) {
final HttpServletResponse response = WebUtils.getHttpServletResponse(context); if (StringUtils.hasText(context.getExternalContext().getRequestParameterMap().get("warn"))) {
this.warnCookieGenerator.addCookie(response, "true");
} else {
this.warnCookieGenerator.removeCookie(response);
}
} private AuthenticationException getAuthenticationExceptionAsCause(final TicketException e) {
return (AuthenticationException) e.getCause();
} private String getAuthenticationExceptionEventId(final TicketException e) {
final AuthenticationException authEx = getAuthenticationExceptionAsCause(e); if (this.logger.isDebugEnabled())
this.logger.debug("An authentication error has occurred. Returning the event id " + authEx.getType()); return authEx.getType();
} private boolean isCauseAuthenticationException(final TicketException e) {
return e.getCause() != null && AuthenticationException.class.isAssignableFrom(e.getCause().getClass());
} public final void setCentralAuthenticationService(final CentralAuthenticationService centralAuthenticationService) {
this.centralAuthenticationService = centralAuthenticationService;
} /**
* Set a CredentialsBinder for additional binding of the HttpServletRequest to the Credentials instance, beyond our default binding of the Credentials as a Form Object in Spring WebMVC parlance. By the time we invoke this CredentialsBinder, we have already engaged in default binding such that for each HttpServletRequest parameter, if there was a JavaBean property of the Credentials implementation of the same name, we have set that property to be the value of the corresponding request parameter. This CredentialsBinder plugin point exists to allow consideration of things other than HttpServletRequest parameters in populating the Credentials (or more sophisticated consideration of the HttpServletRequest parameters).
*
* @param credentialsBinder
* the credentials binder to set.
*/
public final void setCredentialsBinder(final CredentialsBinder credentialsBinder) {
this.credentialsBinder = credentialsBinder;
} public final void setWarnCookieGenerator(final CookieGenerator warnCookieGenerator) {
this.warnCookieGenerator = warnCookieGenerator;
}
}
CaptchaImageLoginCredentials.java
/**
* Project Name:casServerHandler
* File Name:CaptchaImageLoginCredentials.java
* Package Name:org.jasig.cas.authentication.handler
* Date:2013-4-28下午06:55:08
* Copyright (c) 2013, riambsoft All Rights Reserved.
*
*/ package org.jasig.cas.authentication.handler; import java.util.Map; import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size; import org.jasig.cas.authentication.principal.RememberMeUsernamePasswordCredentials; /**
* ClassName:CaptchaImageLoginCredentials <br/> Function: TODO ADD FUNCTION. <br/> Reason: TODO ADD REASON. <br/> Date: 2013-4-28 下午06:55:08 <br/>
*
* @author Administrator
* @version
* @since JDK 1.5
* @see
*/
public class CaptchaImageLoginCredentials extends RememberMeUsernamePasswordCredentials {
private static final long serialVersionUID = 1L; private Map<String, Object> param; /** The username. */
@NotNull
@Size(min = 1, message = "验证码为空")
private String code; public String getCode() {
return code;
} public void setCode(String code) {
this.code = code;
} public Map<String, Object> getParam() {
return param;
} public void setParam(Map<String, Object> param) {
this.param = param;
}
}
5.下面开始对xml文件进行修改:
1)还是刚才那个路径,我们之前修改的xml文件:C:\tomcat7\webapps\casServer\WEB-INF\cas-servlet.xml
<!-- 修改这个bean,变成我们自己的改造后的类
<bean id="authenticationViaFormAction" class="org.jasig.cas.web.flow.AuthenticationViaFormAction"
p:centralAuthenticationService-ref="centralAuthenticationService"
p:warnCookieGenerator-ref="warnCookieGenerator"/>
--> <bean id="authenticationViaFormAction" class="org.jasig.cas.authentication.handler.ImageVaditeAuthenticationViaFormAction"
p:centralAuthenticationService-ref="centralAuthenticationService"
p:warnCookieGenerator-ref="warnCookieGenerator"/> <!-- over -->
2)C:\tomcat7\webapps\casServer\WEB-INF\login-webflow.xml
<flow xmlns="http://www.springframework.org/schema/webflow"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/webflow
http://www.springframework.org/schema/webflow/spring-webflow-2.0.xsd"> <!-- 替换这个
<var name="credentials" class="org.jasig.cas.authentication.principal.UsernamePasswordCredentials" />
-->
<var name="credentials" class="org.jasig.cas.authentication.handler.CaptchaImageLoginCredentials" /> <!-- over --> <on-start>
<evaluate expression="initialFlowSetupAction" />
</on-start>
找到节点:viewLoginForm
<!-- 修改这个
<view-state id="viewLoginForm" view="casLoginView" model="credentials">
<binder>
<binding property="username" />
<binding property="password" />
</binder>
<on-entry>
<set name="viewScope.commandName" value="'credentials'" />
</on-entry>
<transition on="submit" bind="true" validate="true" to="realSubmit">
<evaluate expression="authenticationViaFormAction.doBind(flowRequestContext, flowScope.credentials)" />
</transition>
</view-state>
--> <view-state id="viewLoginForm" view="casLoginView" model="credentials">
<binder>
<binding property="username" />
<binding property="password" />
<binding property="code" /> </binder>
<on-entry>
<set name="viewScope.commandName" value="'credentials'" />
</on-entry>
<transition on="submit" bind="true" validate="true" to="realSubmit">
<evaluate expression="authenticationViaFormAction.doBind(flowRequestContext, flowScope.credentials)" />
</transition>
</view-state>
其实你看到就是增加一个binding属性code,方便注入到ImageVaditeAuthenticationViaFormAction这个类里面。
文章末尾会粘贴所有xml文件,以及源码下载地址
3)在C:\tomcat7\webapps\casServer\WEB-INF\classes最下面添加错误提示信息,由于是使用unicode编码,所以是看不懂的字符
login.code.tip=\u8BF7\u8F93\u5165\u9A8C\u8BC1\u7801
login.code.error=\u9A8C\u8BC1\u7801\u8F93\u5165\u6709\u8BEF
其实这两行的意思如下:
login.code.tip=请输入验证码
login.code.error=验证码输入有误
4)C:\tomcat7\webapps\casServer\WEB-INF\web.xml下新增对URL的处理
<!-- validate code-->
<servlet-mapping>
<servlet-name>cas</servlet-name>
<url-pattern>/captcha.htm</url-pattern>
</servlet-mapping>
<!-- over-->
这一步很重要,否则首页打开时,根本找不到captacha.htm而不显示图片,我做这个的时候,也是搞了好久,才发现web.xml这么重要的配置忘记写。
5)现在去找你的前台页面C:\tomcat7\webapps\casServer\WEB-INF\view\jsp\default\ui\casLoginView.jsp,给加上验证码的文本框和响应事件吧,比如说看不清楚换一张
<!-- 验证码 -->
<div class="row fl-controls-left">
<label for="code" class="fl-label">验证码:</label> <script type="text/javascript">
function refresh(){
fm1.vali.src="";
fm1.vali.src="captcha.htm";
//img.src='captcha.htm?t='+new Date().getTime()
}
</script>
<input class="required" type="text" tabindex="3" id="code" size="10" name="code" autocomplete="off" style="float:left;"/> <div style="height:30px;width:150px;text-align:center;margin-left:5px; float:left;vertical-align:middle; display: table-cell;">
<a href="javascript:refresh();" onclick="refresh();" style="width:130px;height:30px;"> <span style="display: block;float:left;width:60px;height:25px;float:left;">
<img id="vali" width="60" height="30" src="captcha.htm" style="padding-left: 5px;"/>
</span>
<span style="display:block;width:60px;height:100%;float:left;vertical-align:middle; display: table-cell;margin-left:15px;">看不清楚?换一个</span>
</a> </div>
ok 大功告成,编译完的class这几个文件,统统放入你的server端的各个指定路径下,重启tomcat,回帖感谢各位百度前辈吧。
文中所涉及的xml文件完整版:
下载地址:http://pan.baidu.com/share/link?shareid=439449164&uk=436295647
cas sso单点登录系列5_cas单点登录增加验证码功能完整步骤的更多相关文章
- SSO单点登录系列5:cas单点登录增加验证码功能完整步骤
本篇教程cas-server端下载地址:解压后,直接放到tomcat的webapp目录下就能用了,不过你需要登录的话,要修改数据源,C:\tomcat7\webapps\casServer\WEB-I ...
- cas sso单点登录系列7_ 单点登录cas常见问题系列汇总
转:http://blog.csdn.net/matthewei6/article/details/50709252 单点登录cas常见问题(一) - 子系统是否还要做session处理?单点登录ca ...
- cas sso单点登录系列6_cas单点登录防止登出退出后刷新后退ticket失效报500错
转(http://blog.csdn.net/ae6623/article/details/9494601) 问题: 我登录了client2,又登录了client3,现在我把client2退出了,在c ...
- 2019微软Power BI 每月功能更新系列——Power BI 4月版本功能完整解读
Power BI4月份的更新对整个产品进行了重大更新.此版本增加了基于DAX表达式定义视觉效果标题和按钮URL的功能.本月Power BI也新增了许多新的连接器,现在可以使用几种预览连接器,包括Pow ...
- cas sso单点登录系列4_cas-server登录页面自定义修改过程(jsp页面修改)
转:http://blog.csdn.net/ae6623/article/details/8861065 SSO单点登录系列4:cas-server登录页面自定义修改过程,全新DIY. 目标: ...
- cas sso单点登录系列2:cas客户端和cas服务端交互原理动画图解,cas协议终极分析
转:http://blog.csdn.net/ae6623/article/details/8848107 1)PPT流程图:ppt下载:http://pan.baidu.com/s/1o7KIlom ...
- SSO单点登录系列2:cas客户端和cas服务端交互原理动画图解,cas协议终极分析
落雨 cas 单点登录 一.用户第一次访问web1应用. ps:上图少画了一条线,那一条线,应该再返回来一条,然后再到server端,画少了一步...谢谢提醒.而且,重定向肯定是从浏览器过去的.我写的 ...
- cas sso单点登录系列3_cas-server端配置认证方式实践(数据源+自定义java类认证)
转:http://blog.csdn.net/ae6623/article/details/8851801 本篇将讲解cas-server端的认证方式 1.最简单的认证,用户名和密码一致就登录成功 2 ...
- SSO单点登录系列4:cas-server登录页面自定义修改过程(jsp页面修改)
落雨 cas 单点登录 SSO单点登录系列4:cas-server登录页面自定义修改过程,全新DIY. 目标: 下面是正文: 打开cas的默认首页,映入眼帘的是满眼的中文and英文混杂体,作为一 ...
随机推荐
- PHP实现单击“添加”按钮增加一行表单项,并将所有内容插入到数据库中
PHP实现单击“添加”按钮增加一行表单项,并将所有内容插入到数据库中 效果图: html+jquery: <html> <head> <meta http-equiv=& ...
- 【Linux】鸟哥的Linux私房菜基础学习篇整理(九)
1. quotacheck [-avugfM] [/mount_point]:扫描文件系统并创建Quota配置文件.参数:-a:扫描所有在/etc/mtab内,含有quota支持的文件系统,加上此参数 ...
- bzoj1076
好像题目有点问题?且现在决定不吃的宝物以后也不能再吃好像下次还是可以吃的,就是这样然后明显是状压dp,注意这道题明显倒推更容易因为顺推很可能从一个无效状态推到有效状态 ..,..] of double ...
- Pet
Problem Description One day, Lin Ji wake up in the morning and found that his pethamster escaped. He ...
- 《University Calculus》-chaper13-向量场中的积分-线积分
线积分: 基于二重积分和三重积分的引入,我们对于线积分的引入过程将会轻车熟路. 对于一根不均匀密度的铜丝,我们如何求其总质量?如下图. 类似二重积分和三重积分的引入,我们首先基于实际问题给出黎曼和的形 ...
- C++ 路径中\\与/
windows默认使用\\ linux默认使用/ 可以都用/
- Break、continue、return用法(C++)
(1)break 直接调出当前循环体.如果是嵌套循环,他只能调出一层循环体. Exp-1: 程序: #include<iostream> using namespace std; int ...
- Android eclipse下数据开源框架GreenDao的配置
1.前言 ORM(Object-RelationMapping,对象关系映射),是一种为了解决面向对象与数据库存在的互一匹配的现象的技术,通过描述对象和关系数据库之间的映射,将程序中的对象自动持久化到 ...
- 关于python保留几位小数,不进行四舍五入的方法
def cut(num,c): c=10**(-c) return (num//c)*c print cut(2.999,2) 不过有一部分数会出现问题,还请大神评论 例如: >>> ...
- Team Foundation Server 2013 with Update 3 Install LOG
[Info @10:14:58.155] ====================================================================[Info @ ...