- 浏览: 176586 次
- 性别:
- 来自: 福州
文章分类
最新评论
-
vil:
请问CAS 单点登录加负载均衡后,httpClient tim ...
(转)CAS负载均衡配置 -
bcs2099:
男男女女[flash=200,200][/flash]
学Ext的好网站 -
bcs2099:
不过关
学Ext的好网站 -
qingteng1983:
请问,这个上传组件支持断点续传吗?
利用SWFUpload实现大附件上传 -
yangwn:
LZ,我想请教,hdfs://192.168.4.27:900 ...
编写JAVA代码读取Hadoop存储服务器文件
客户端即指使用CAS中央认证服务器的应用程序,而不是指用户浏览器
在上一篇《让CAS支持客户端自定义登陆页面——服务器篇 》中我们介绍了如何修改CAS服务器端来支持客户端自定义登陆页面,这一节我们开始讲述客户端实现理论和详细修改
客户端实现目标
客户端实现主要需要满足5个case:
- 1. 用户未在中央认证服务器登陆,访问客户端受保护资源时,客户端重定向到中央认证服务器请求TGT认证,认证失败,转回客户端登陆页面,保证受保护资源URL信息不丢失
- 2. 用户未在中央认证服务器登陆,访问客户端登陆页面时,客户端重定向到中央认证服务器请求TGT认证,认证失败,转回客户端登陆页面,此次登录页面不再受保护,允许访问
- 3. 用户已在中央认证服务器登陆,访问客户端受保护资源时,客户端重定向到中央认证服务器请求TGT认证,认证成功,直接转回受保护资源
- 4. 用户在客户端登陆页面提交用户名密码,客户端将用户名密码信息提交给服务器端,认证失败,转回客户端登陆页面,携带失败信息并保证转到登陆页面前受保护资源URL信息不丢失
- 5. 用户在客户端登陆页面提交用户名密码,客户端将用户名密码信息提交给服务器端,认证成功,转回转到登陆页面前受保护资源
对于case 1和case 3,普通的CAS客户端即可满足需求,但对于case 4和case 5,则需要我们定制自己的登陆页面。对于case 2,主要是需要满足部分登陆页面希望在用户未登陆状态显示登陆框,在已登陆状态显示用户欢迎信息的需求,实现这个需求我们是通过让CAS客户端认证器满足 一个排除约定,即当用户请求路径为登陆页面且带有validated=true的参数时,即不进行重定向TGT认证请求
客户端修改方案
远程客户端修改,对于任何一种客户端方案都可以实现,这里为了简单起见,我们给出的修改方案基于CAS官方提供的Java客户端3.1.3。首先我们使用CAS Client 3.1.3搭建一个CAS客户端,具体搭建方法可以参考CAS官网:CAS Client for Java 3.1
根据服务器流程修改方案,我们可以知道,所有的远程请求都必须携带有loginUrl参数信息以使得服务器端知道在认证失败后转向客户端登陆页面。 而在CAS客户端上,上一节的case 4和case 5,我们主要通过提交表单的方式传递loginUrl,而case 1, case 3则是依靠org.jasig.cas.client.authentication.AuthenticationFilter类进行的转向,但使用 AuthenticationFilter转向时,是没有loginUrl信息的,因此我们首先需要重新实现一个自己的认证过滤器,以下是我们自己的认证 过滤器的代码:
/**
* 远程认证过滤器.
* 由于AuthenticationFilter的doFilter方法被声明为final,
* 只好重新实现一个认证过滤器,支持localLoginUrl设置.
*
* @author GuoLin
*
*/
public class RemoteAuthenticationFilter extends AbstractCasFilter {
public static final String CONST_CAS_GATEWAY = "_const_cas_gateway_";
/**
* 本地登陆页面URL.
*/
private String localLoginUrl;
/**
* The URL to the CAS Server login.
*/
private String casServerLoginUrl;
/**
* Whether to send the renew request or not.
*/
private boolean renew = false;
/**
* Whether to send the gateway request or not.
*/
private boolean gateway = false;
protected void initInternal(final FilterConfig filterConfig) throws ServletException {
super.initInternal(filterConfig);
setCasServerLoginUrl(getPropertyFromInitParams(filterConfig, "casServerLoginUrl", null));
log.trace("Loaded CasServerLoginUrl parameter: " + this.casServerLoginUrl);
setLocalLoginUrl(getPropertyFromInitParams(filterConfig, "localLoginUrl", null));
log.trace("Loaded LocalLoginUrl parameter: " + this.localLoginUrl);
setRenew(Boolean.parseBoolean(getPropertyFromInitParams(filterConfig, "renew", "false")));
log.trace("Loaded renew parameter: " + this.renew);
setGateway(Boolean.parseBoolean(getPropertyFromInitParams(filterConfig, "gateway", "false")));
log.trace("Loaded gateway parameter: " + this.gateway);
}
public void init() {
super.init();
CommonUtils.assertNotNull(this.localLoginUrl, "localLoginUrl cannot be null.");
CommonUtils.assertNotNull(this.casServerLoginUrl, "casServerLoginUrl cannot be null.");
}
public final void doFilter(final ServletRequest servletRequest,
final ServletResponse servletResponse, final FilterChain filterChain)
throws IOException, ServletException {
final HttpServletRequest request = (HttpServletRequest) servletRequest;
final HttpServletResponse response = (HttpServletResponse) servletResponse;
final HttpSession session = request.getSession(false);
final String ticket = request.getParameter(getArtifactParameterName());
final Assertion assertion = session != null ? (Assertion) session
.getAttribute(CONST_CAS_ASSERTION) : null;
final boolean wasGatewayed = session != null
&& session.getAttribute(CONST_CAS_GATEWAY) != null;
// 如果访问路径为localLoginUrl且带有validated参数则跳过
URL url = new URL(localLoginUrl);
final boolean isValidatedLocalLoginUrl = request.getRequestURI().endsWith(url.getPath()) &&
CommonUtils.isNotBlank(request.getParameter("validated"));
if (!isValidatedLocalLoginUrl &&
CommonUtils.isBlank(ticket) && assertion == null && !wasGatewayed) {
log.debug("no ticket and no assertion found");
if (this.gateway) {
log.debug("setting gateway attribute in session");
request.getSession(true).setAttribute(CONST_CAS_GATEWAY, "yes");
}
final String serviceUrl = constructServiceUrl(request, response);
if (log.isDebugEnabled()) {
log.debug("Constructed service url: " + serviceUrl);
}
String urlToRedirectTo = CommonUtils.constructRedirectUrl(
this.casServerLoginUrl, getServiceParameterName(),
serviceUrl, this.renew, this.gateway);
// 加入localLoginUrl
urlToRedirectTo += (urlToRedirectTo.contains("?") ? "&" : "?") + "loginUrl=" + URLEncoder.encode(localLoginUrl, "utf-8");
if (log.isDebugEnabled()) {
log.debug("redirecting to \"" + urlToRedirectTo + "\"");
}
response.sendRedirect(urlToRedirectTo);
return;
}
if (session != null) {
log.debug("removing gateway attribute from session");
session.setAttribute(CONST_CAS_GATEWAY, null);
}
filterChain.doFilter(request, response);
}
public final void setRenew(final boolean renew) {
this.renew = renew;
}
public final void setGateway(final boolean gateway) {
this.gateway = gateway;
}
public final void setCasServerLoginUrl(final String casServerLoginUrl) {
this.casServerLoginUrl = casServerLoginUrl;
}
public final void setLocalLoginUrl(String localLoginUrl) {
this.localLoginUrl = localLoginUrl;
}
}
以上粗体代码为修改部分,其余代码均拷贝自 org.jasig.cas.client.authentication.AuthenticationFilter,可以看到我们为原有的认证过滤器 增加了一个参数localLoginUrl。在WEB-INF/web.xml中配置:
<context-param>
<param-name>serverName</param-name>
<param-value>http://192.168.7.131:8080</param-value>
</context-param>
<filter>
<filter-name>CAS Single Sign Out Filter</filter-name>
<filter-class>org.jasig.cas.client.session.SingleSignOutFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>CAS Single Sign Out Filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<listener>
<listener-class>org.jasig.cas.client.session.SingleSignOutHttpSessionListener</listener-class>
</listener>
<filter>
<filter-name>CAS Authentication Filter</filter-name>
<filter-class>cn.RemoteAuthenticationFilter</filter-class>
<init-param>
<param-name>localLoginUrl</param-name>
<param-value>
http://192.168.7.131:8080/zz/login.jsp
</param-value>
</init-param>
<init-param>
<param-name>casServerLoginUrl</param-name>
<param-value>http://192.168.7.130:8080/sso/remoteLogin</param-value>
</init-param>
<init-param>
<param-name>renew</param-name>
<param-value>false</param-value>
</init-param>
<init-param>
<param-name>gateway</param-name>
<param-value>false</param-value>
</init-param>
<init-param>
<param-name>serverName</param-name>
<param-value>http://192.168.7.131:8080</param-value>
</init-param>
</filter>
<filter>
<filter-name>CAS Validation Filter</filter-name>
<filter-class>org.jasig.cas.client.validation.Cas20ProxyReceivingTicketValidationFilter</filter-class>
<init-param>
<param-name>casServerUrlPrefix</param-name>
<param-value>http://192.168.7.130:8080</param-value>
</init-param>
<init-param>
<param-name>casServerUrlPrefix</param-name>
<param-value>http://192.168.7.130:8080/sso</param-value>
</init-param>
<init-param>
<param-name>useSession</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>redirectAfterValidation</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter>
<filter-name>CAS HttpServletRequest Wrapper Filter</filter-name>
<filter-class>org.jasig.cas.client.util.HttpServletRequestWrapperFilter</filter-class>
</filter>
<filter>
<filter-name>CAS Assertion Thread Local Filter</filter-name>
<filter-class>org.jasig.cas.client.util.AssertionThreadLocalFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>CAS Authentication Filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>CAS Validation Filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>CAS HttpServletRequest Wrapper Filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>CAS Assertion Thread Local Filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
此处我们将过滤器指向自己的过滤器并增加本地登陆页面路径设置。最后我们来看看登陆页面login.jsp:
<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd
">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>远程CAS客户端登陆页面</title>
<link rel="stylesheet" type="text/css" href="<%= request.getContextPath() %>/styles/main.css" />
<script type="text/javascript">
function getParam(name) {
var queryString = window.location.search;
var param = queryString.substr(1, query.length - 1).split("&");
for (var i = 0; i < param.length; i++) {
var keyValue = param[i].split("=");
if (keyValue[0] == name) return keyValue[1];
}
return null;
}
function init() {
// 显示异常信息
var error = getParam("errorMessage");
if (error) {
document.getElementById("errorMessage").innerHTML = decodeURIComponent(error);
}
// 注入service
var service = getParam("service");
if (service)
document.getElementById("service").value = decodeURIComponent(service);
else
document.getElementById("service").value = location.href;
}
</script>
</head>
<body>
<h1>远程CAS客户端登陆页面</h1>
<% if (request.getRemoteUser() == null) { %>
<div id="errorMessage"></div>
<form id="myLoginForm" action="https://guolin/cas-server/remoteLogin
" method="post">
<input type="hidden" id="service" name="service" value="">
<input type="hidden" name="loginUrl" value="
http://guolin:9080/cas-client-java-custom-login/login.jsp
">
<input type="hidden" name="submit" value="true" />
<table>
<tr>
<td>用户名:</td>
<td><input type="text" name="username"></td>
</tr>
<tr>
<td>密 码:</td>
<td><input type="password" name="password"></td>
</tr>
<tr>
<td colspan="2"><input type="submit" value="登陆" /></td>
</tr>
</table>
</form>
<script type="text/javascript">init()</script>
<% } else { %>
<div class="welcome">您好:<%= request.getRemoteUser() %></div>
<div id="logout">
<a href="https://GUOLIN/cas-server/remoteLogout?service=http://guolin:9080/cas-client-java-custom-login/login.jsp
">单点登出</a>
</div>
<% } %>
</body>
</html>
login.jsp主要是为了满足上一节中的case 4和case 5,这里为了简单起见,仅有是否已登陆判断使用了服务器端代码,其他均使用客户端代码实现。以上粗体字中,我们首先将表单action指向服务器端 remoteLogin,然后在里面设置了两个重要的hidden域以传递 loginUrl和submit参数,前者用于告诉服务器失败后转向何处,后者告诉服务器端webflow现在要进行提交而不是TGT认证请求
这样我们的自定义客户端远程登陆页面就完成了,现在赶快测试一下吧
- casclient.rar (8.4 KB)
- 下载次数: 105
发表评论
-
CAS 3.x代理配置
2010-02-04 16:04 2690http://fallenlord.blogbus.com/l ... -
(转)CAS负载均衡配置
2010-01-28 09:38 8106http://fallenlord.blogbus.com ... -
获取汉字拼音首字母功能函数
2010-01-18 14:52 962如: System.out.println(HZPY. ... -
JAVA MVC构架详解
2009-12-22 15:04 987整理。。。 -
Web服务端组件事件开发与MVC开发
2009-12-19 11:14 1254本周一起跟.net开 ... -
内存控制效率优化的启示
2009-12-05 10:01 8724 内存控制效率优化的 ... -
记录下载中文附件出现乱码
2009-10-28 14:16 874环境:jsp页面,编码全部用UTF-8 在下载代码中写 ... -
web.xml 中 mime-mapping的使用
2009-10-08 09:58 6097mime-mapping 如果Web应用程序包含一 ... -
从Struts到Spring MVC的应用
2009-09-27 11:42 1478从 Struts 转到 Spring MVC 的应用 ... -
容易被搞晕的——堆和栈
2009-09-23 11:10 770容易被搞晕的——堆和 ... -
Tomcat的配置文件server.xml 中各个域的说明
2009-07-09 15:10 808Tomcat的配置文件server.xml 中各个域的说明 ... -
让CAS支持客户端自定义登陆页面——服务器篇
2009-06-19 16:40 2059修改需要基于几个基本原则: 不影响原有统一登陆界面功能 ... -
将页面输出进行压缩
2009-06-15 16:07 883压缩是解决数据冗余的一个好的方法,特别是在网络带宽 ... -
在spring mvc中用 jquery 出现的在IE,firefox乱码问题解决
2009-06-11 19:47 1706由于在开发中大量用GB2312出现此问题,解决方法可以有下方法 ... -
Hibernate中分页查询在SQL Server2005产生的SQL语句
2009-05-26 15:18 1631Hibernate 的分页代码 query.setFi ... -
不要重复 DAO!
2009-04-16 17:03 825http://www.ibm.com/developerwor ... -
jquery异步附件上传
2009-03-30 20:30 4230http://valums.com/wp-content/up ... -
JAVA中不错的处理日期工具单元
2009-02-10 10:54 974/**Revision Information: *@ver ... -
MyEclipse6.5注册码
2009-01-12 13:42 734Subscriber:QQ24785490 Subscrip ... -
Hibernate3.2官方中文参考手册
2009-01-09 16:37 1826如附件:
相关推荐
让CAS支持客户端自定义登陆页面——服务器篇[参考].pdf
让CAS支持客户端自定义登陆页面——服务器篇.docx
让CAS支持客户端自定义登陆页面----服务器篇--.doc
让CAS支持客户端自定义登陆页面----服务器篇.doc
让CAS支持客户端自定义登陆页面----服务器篇-.pdf
让CAS支持客户端自定义登陆页面----服务器篇--.doc
CAS客户端自定义核心过滤器,继承CAS的AbstractCasFilter自定义AuthenticationFilter
详细描述了cas 自定义登陆页面的配置与demo
cas客户端登录配置详细文档,支持客户端自定义登录和服务端统一登录。
包含cas源码、cas使用说明文档(包含配置信息)、连接数据库所需jar包、cas服务端自定义返回值等
cas4.2.7服务端+cas客户端+示例程序+环境搭建之客户端war包 一切跑不起来的程序和走不通的教程都是耍流氓,二话不说,先按照我的步骤把程序跑起来在说吧。 请看博客...
这是boot2.0+shiro+pac4j+cas 整合项目 cas还可以自定义登陆页和认证校验数据库
cas .net客户端的配置代码 CAS 与_net 集成的 “循环重定向”问题分析 - 邢少 - 博客园.mht根本不行的。 我自己另外找的一段代码
CAS客户端获取用户保存至sessionUser
cas的客户端cas的客户端cas的客户端cas的客户端cas的客户端cas的客户端
单点登录CAS.net客户端源码,已调试成功,需要在webconfig中将服务端地址以及跳转地址修改好即可
cas客户端集成单点登录代码cas客户端集成单点登录代码cas客户端集成单点登录代码cas客户端集成单点登录代码cas客户端集成单点登录代码cas客户端集成单点登录代码
Cas3.2.1客户端Jar包