完整版见https://jadyer.github.io/2015/07/26/sso-cas-client-login/

本文源代码下载:http://download.csdn.net/detail/jadyer/8934207

/**
* @see CAS客户端配置
* @see ------------------------------------------------------------------------------------------------------------------------
* @see 这里用的是cas-client-core-3.4.0.jar(这是2015-07-21公布的)
* @see 下载地址http://mvnrepository.com/artifact/org.jasig.cas.client/cas-client-core/3.4.0
* @see 另外为了使客户端在HTTP协议下单点成功,能够改动以下两处配置使其不开启HTTPS验证
* @see 1.\WEB-INF\deployerConfigContext.xml
* @see <bean class="org.jasig...support.HttpBasedServiceCredentialsAuthenticationHandler">加入p:requireSecure="false"
* @see 2.\WEB-INF\spring-configuration\ticketGrantingTicketCookieGenerator.xml和\WEB-INF\spring-configuration\warnCookieGenerator.xml
* @see p:cookieSecure="true"改为p:cookieSecure="false"
* @see 以下介绍两种配置方法,一种是纯web.xml配置,一种是借助Spring来配置,相关的官方文档例如以下所看到的
* @see https://wiki.jasig.org/display/CASC/Configuring+the+Jasig+CAS+Client+for+Java+in+the+web.xml
* @see https://wiki.jasig.org/display/CASC/Configuring+the+JA-SIG+CAS+Client+for+Java+using+Spring
* @see ------------------------------------------------------------------------------------------------------------------------
* @see 纯web.xml
* @see web.xml中需配置四个顺序固定的Filter,并且出于认证考虑,最好配置在其他Filter之前,它们的先后顺序例如以下
* @see AuthenticationFilter
* @see TicketValidationFilter(或其他AbstractTicketValidationFilter实现,比方Cas20ProxyReceivingTicketValidationFilter)
* @see HttpServletRequestWrapperFilter
* @see AssertionThreadLocalFilter
* @see 另外各个Filter的<init-param>优先级都比<context-param>要高,通常<context-param>用来配置公用的參数
* @see 1.AuthenticationFilter
* @see 用来拦截请求,推断是否须要CASServer认证,须要则跳转到CASServer登录页,否则放行请求
* @see 有两个必须參数,一个是指定CASServer登录地址的casServerLoginUrl,还有一个是指定认证成功后跳转地址的serverName或service
* @see service和serverName设置一个就可以,二者都设置时service的优先级更高,即会以service为准
* @see service指的是一个确切的URL,而serverName是用来指定客户端的主机名的,格式为{protocol}:{hostName}:{port}
* @see 指定serverName时,该Filter会把它附加上当前请求的URI及相应的查询參数来构造一个确切的URL作为认证成功后的跳转地址
* @see 比方serverName为"http://gg.cn",当前请求的URI为"/oa",查询參数为"aa=bb",则认证成功后跳转地址为http://gg.cn/oa? aa=bb
* @see casServerLoginUrl--去哪登录,serverName--我是谁
* @see 2.TicketValidationFilter
* @see 请求通过AuthenticationFilter认证后,若请求中携带了ticket參数,则会由该类Filter对携带的ticket进行校验
* @see 验证ticket的时候,要訪问CAS服务的/serviceValidate接口,使用的url就是${casServerUrlPrefix}/serviceValidate
* @see 所以它也有两个參数是必须指定的,casServerUrlPrefix(CASServer相应URL地址的前缀)和serverName或service
* @see 实际上,TicketValidationFilter仅仅是对验证ticket的这一类Filter的统称,其并不正确应CASClient中的详细类型
* @see CASClient中有多种验证ticket的Filter,都继承自AbstractTicketValidationFilter
* @see 常见的有Cas10TicketValidationFilter/Cas20ProxyReceivingTicketValidationFilter/Saml11TicketValidationFilter
* @see 它们的验证逻辑都是一致的,都有AbstractTicketValidationFilter实现,仅仅是使用的TicketValidator不一样而已
* @see 假设要从服务器获取username之外的很多其他信息应该採用CAS20这个2.0协议的代理
* @see 3.HttpServletRequestWrapperFilter
* @see 用于封装每一个请求的HttpServletRequest为其内部定义的CasHttpServletRequestWrapper
* @see 它会将保存在Session或request中的Assertion对象重写HttpServletRequest的getUserPrincipal()、getRemoteUser()、isUserInRole()
* @see 这样在我们的应用中就能够很方便的从HttpServletRequest中获取到用户的相关信息
* @see 4.AssertionThreadLocalFilter
* @see 为了方便用户在应用的其他地方获取Assertion对象,其会将当前的Assertion对象存放到当前的线程变量中
* @see 以后用户在程序的不论什么地方都能够从线程变量中获取当前的Assertion,而无需从Session或request中解析
* @see 该线程变量是由AssertionHolder持有的,我们在获取当前的Assertion时也仅仅需Assertion assertion = AssertionHolder.getAssertion()
* @see ------------------------------------------------------------------------------------------------------------------------
* @see 借助Spring
* @see 与上述web.xml配置四个Filter方式不同的是,能够使用Spring的四个DelegatingFilterProxy来代理须要配置的四个Filter
* @see 此时这四个Filter就应该配置为Spring的Bean对象,并且web.xml中的<filter-name>就应该相应SpringBean名称
* @see 可是SingleSignOutFilter/HttpServletRequestWrapperFilter/AssertionThreadLocalFilter等Filter不含配置參数
* @see 所以实际上仅仅须要配置AuthenticationFilter和Cas20ProxyReceivingTicketValidationFilter两个Filter交由Spring代理就能够了
* @see ------------------------------------------------------------------------------------------------------------------------
* @see 注意
* @see 1.CAS1.0提供的接口有/validate。CAS2.0提供的接口有/serviceValidate,/proxyValidate,/proxy
* @see 2.四个Filter太多了,有时间的话考虑參考org.springframework.web.filter.CompositeFilter写一个Filter来实现
* @see 3.web.xml的优点是能够配置匿名訪问的资源,配置參数參考AuthenticationFilter中的ignoreUrlPatternMatcherStrategyClass
* @see 起码cas-client-core-3.4.0.jar中的Spring配置还不支持ignorePattern(该參数默认正则验证,此外还有contains和equals验证)
* @see 4.javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateException: No name matching casserver found
* @see 这是因为创建证书的域名和应用中配置的CAS服务域名不一致导致出错(说白了就是指客户端导入的CRT证书与CAS服务端的域名不同)
* @see ------------------------------------------------------------------------------------------------------------------------
* @create 2015-7-26 下午1:00:14
* @author 玄玉<http://blog.csdn.net/jadyer>
*/

以下是web.xml的配置

<?

xml version="1.0" encoding="UTF-8"?

>
<web-app version="2.5"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener> <servlet>
<servlet-name>SpringMVC</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>SpringMVC</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping> <filter>
<filter-name>CharacterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping> <!-- SSO -->
<filter>
<filter-name>casAuthenticationFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>casAuthenticationFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter>
<filter-name>casTicketValidationFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>casTicketValidationFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!--
<context-param>
<param-name>serverName</param-name>
<param-value>http://boss.jadyer.com:8080</param-value>
</context-param>
<filter>
<filter-name>casAuthenticationFilter</filter-name>
<filter-class>org.jasig.cas.client.authentication.AuthenticationFilter</filter-class>
<init-param>
<param-name>casServerLoginUrl</param-name>
<param-value>http://sso.jadyer.com:8080/cas-server-web/login</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>casAuthenticationFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter>
<filter-name>casTicketValidationFilter</filter-name>
<filter-class>org.jasig.cas.client.validation.Cas20ProxyReceivingTicketValidationFilter</filter-class>
<init-param>
<param-name>casServerUrlPrefix</param-name>
<param-value>http://sso.jadyer.com:8080/cas-server-web</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>casTicketValidationFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
-->
<filter>
<filter-name>casHttpServletRequestWrapperFilter</filter-name>
<filter-class>org.jasig.cas.client.util.HttpServletRequestWrapperFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>casHttpServletRequestWrapperFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter>
<filter-name>casAssertionThreadLocalFilter</filter-name>
<filter-class>org.jasig.cas.client.util.AssertionThreadLocalFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>casAssertionThreadLocalFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>

以下是//src//applicationContext.xml

<?

xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd">
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE"/>
<property name="ignoreResourceNotFound" value="false"/>
<property name="locations">
<list>
<value>classpath:config.properties</value>
</list>
</property>
</bean>
<mvc:resources mapping="/index.jsp" location="/index.jsp"/> <!-- cas -->
<bean name="casAuthenticationFilter" class="org.jasig.cas.client.authentication.AuthenticationFilter">
<property name="serverName" value="${casClientServerName}"/>
<property name="casServerLoginUrl" value="${casServerLoginUrl}"/>
</bean>
<bean name="casTicketValidationFilter" class="org.jasig.cas.client.validation.Cas20ProxyReceivingTicketValidationFilter">
<property name="serverName" value="${casClientServerName}"/>
<property name="ticketValidator">
<bean class="org.jasig.cas.client.validation.Cas20ServiceTicketValidator">
<constructor-arg index="0" value="${casServerUrlPrefix}"/>
</bean>
</property>
</bean>
</beans>

以下是//src//config.properties

#<<Central Authentication Service>>
#where to login
casServerLoginUrl=http://sso.jadyer.com:8080/cas-server-web/login
#login server root
casServerUrlPrefix=http://sso.jadyer.com:8080/cas-server-web
#who am i
#casClientServerName=http://boss.jadyer.com:8180
casClientServerName=http://risk.jadyer.com:8280

最后是//WebRoot//index.jsp

<%@ page pageEncoding="UTF-8"%>
<%@ page import="java.util.Map"%>
<%@ page import="java.net.URLDecoder"%>
<%@ page import="org.jasig.cas.client.util.AssertionHolder"%>
<%@ page import="org.jasig.cas.client.authentication.AttributePrincipal"%> <body style="background-color:#CBE0C9;">
<span style="color:red; font-size:32px; font-weight:bold;">客户端登录成功</span>
</body> <hr size="2"> <%
AttributePrincipal principal = (AttributePrincipal)request.getUserPrincipal();
Map<String, Object> attributes = principal.getAttributes();
out.print("principal.getName()=" + principal.getName() + "<br/>");
out.print("request.getRemoteUser()=" + request.getRemoteUser() + "<br/>");
out.print("登录用户:" + attributes.get("userId") + "<br/>");
out.print("登录时间:" + AssertionHolder.getAssertion().getAuthenticationDate() + "<br/>");
out.print("-----------------------------------------------------------------------<br/>");
for(Map.Entry<String,Object> entry : attributes.entrySet()){
//服务端返回中文时须要encode,客户端接收显示中文时须要decode,否则会乱码
out.print(entry.getKey() + "=" + URLDecoder.decode(entry.getValue().toString(), "UTF-8") + "<br/>");
}
out.print("-----------------------------------------------------------------------<br/>");
Map<String, Object> attributes22 = AssertionHolder.getAssertion().getAttributes();
for(Map.Entry<String,Object> entry : attributes22.entrySet()){
out.print(entry.getKey() + "=" + entry.getValue() + "<br/>");
}
out.print("-----------------------------------------------------------------------<br/>");
Map<String, Object> attributes33 = AssertionHolder.getAssertion().getPrincipal().getAttributes();
for(Map.Entry<String,Object> entry : attributes33.entrySet()){
out.print(entry.getKey() + "=" + entry.getValue() + "<br/>");
}
%>

接下来就能够測试了,測试之前先改动几处配置。模拟单点环境

/**
* @see ------------------------------------------------------------------------------------------------------------------------
* @see 測试时在C:\Windows\System32\drivers\etc\hosts中加入下面三个配置
* @see 127.0.0.1 sso.jadyer.com
* @see 127.0.0.1 boss.jadyer.com
* @see 127.0.0.1 risk.jadyer.com
* @see ------------------------------------------------------------------------------------------------------------------------
* @see 然后拷贝三个Tomcat,分别用作sso服务器和两个ssoclient
* @see 改动两个ssoclient的\Tomcat\conf\server.xml的下面三个端口,保证启动监听端口不反复
* @see <Server port="8105" shutdown="SHUTDOWN">
* @see <Connector port="8180" protocol="HTTP/1.1"......>
* @see <Connector port="8109" protocol="AJP/1.3" redirectPort="8443" />
* @see <Server port="8205" shutdown="SHUTDOWN">
* @see <Connector port="8280" protocol="HTTP/1.1"......>
* @see <Connector port="8209" protocol="AJP/1.3" redirectPort="8443" />
* @see ------------------------------------------------------------------------------------------------------------------------
* @see 最后改动两个ssoclient的\Tomcat\webapps\cas-client\WEB-INF\classes\config.properties的casClientServerName值
* @see casClientServerName=http://boss.jadyer.com:8180
* @see casClientServerName=http://risk.jadyer.com:8280
* @see ------------------------------------------------------------------------------------------------------------------------
* @create 2015-7-26 下午1:08:35
* @author 玄玉<http://blog.csdn.net/jadyer>
*/

如今開始測试

先訪问http://boss.jadyer.com:8180/cas-client,发现没登录会自己主动跳转到单点登录页

输入password后登录成功

再訪问http://risk.jadyer.com:8280/cas-client,会发现自己主动登录成功,不用再登录了

【试水CAS-4.0.3】第07节_CASclient配置单点登录的更多相关文章

  1. 单点登录CAS系列第06节之客户端配置单点登录

    原理 纯web.xml 借助Spring 注意 代码 测试 原理 这里用的是:cas-client-core-3.4.0.jar(2015-07-21发布的) 下载地址为:http://mvnrepo ...

  2. cas单点登录系统:客户端(client)详细配置(包含统一单点注销配置)

    最近一直在研究cas登录中心这一块的应用,分享一下记录的一些笔记和心得.后面会把cas-server端的配置和重构,另外还有这几天再搞nginx+cas的https反向代理配置,以及cas的证书相关的 ...

  3. Liferay7.0与cas单点登录配置

    1.简介     Liferay7.0支持多种登录方式,包括:常规的.opensso.cas.ntlm.ldap.openid.Facebook.Google等. 其中, (1) 常规:则是默认Lif ...

  4. 单点登录(二)----实战------简单搭建CAS---测试认证方式搭建CAS

    我们在上一篇文章中已经介绍了cas以及它的工作流程. 单点登录(一)-----理论-----单点登录SSO的介绍和CAS+选型 本章我们开始动手搭建一个完整的cas服务实现2个web之间的单点登录. ...

  5. CAS单点登录和spring securtiy集成

    说明:本文章主要建立在spring-security早已集成在系统中的前提下: 1.需要创建一个spring-security.xml文件并关联在applicationContext.xml文件中:& ...

  6. 2、cas4.0 单点登录 之 cas-client

    cas4.0 单点登录 之 cas-client cas4.0 单点登录 之 https证书已经做好了证书的准备工作.如今结合cas-server来配置单点登录: 一.安装cas服务端(cas-ser ...

  7. cas单点登录搭建

    Cas Server下载:http://developer.jasig.org/cas/ Cas Client下载:http://developer.jasig.org/cas-clients/ 测试 ...

  8. SSO之CAS单点登录实例演示

    本文目录: 一.概述 二.演示环境 三.JDK安装配置 四.安全证书配置 五.部署CAS-Server相关的Tomcat 六.部署CAS-Client相关的Tomcat 七. 测试验证SSO 一.概述 ...

  9. 搭建CAS单点登录服务器

    最近公司的一个项目需要用到单点登录的功能,之前对单点登录了解得不多.于是网上找了下单点登录的解决方案,发现CAS是个不错的解决方案.于是搭个环境测试了一下.这里记录下测试的详细步骤. 官网:http: ...

随机推荐

  1. 紫书 例题 10-16 UVa 12230(数学期望)

    感觉数学期望的和化学里面求元素的相对原子质量的算法是一样的 就是同位素的含量乘上质量然后求和得出 这道题因为等待时机是0到2*l/v均匀分配的,所以平均时间就是l/v 再加上过河的l/v, 最后加上步 ...

  2. unity调用Android的两种方式:其二,调用aar包

    上一篇我们讲了unity如何调用jar包 http://www.cnblogs.com/Jason-c/p/6743224.html, 现在我们介绍一下怎么生成aar包和unity怎么调用aar 一. ...

  3. FOJ1205 小鼠迷宫问题 (BFD+递推)

    FOJ1205 小鼠迷宫问题 (BFD+递推) 小鼠a与小鼠b身处一个m×n的迷宫中,如图所示.每一个方格表示迷宫中的一个房间.这m×n个房间中有一些房间是封闭的,不允许任何人进入.在迷宫中任何位置均 ...

  4. Android Private Libraries 和 Dependencies的区别

    Android项目开发中,是不是常看到android-support-v4.jar.appcompat_v7.jar等的jar包? 至于为什么要添加这些包?添加有什么用?添加到哪里?相信很多人没过多关 ...

  5. BZOJ 4385 单调队列

    思路: 对于每一个r 要找最小的符合条件的l最优 这时候就要找在这个区间中 d长度的和的最大值 用单调队列更新就好了 //By SiriusRen #include <cstdio> #i ...

  6. HTTP 协议基础及发展历史

    一. 5层网络模型介绍 低三层 物理层:主要作用是定义物理设备如何传输数据. 数据链路层:在通信的实体间建立数据链路连接. 网路层:为数据在结点之间传输创建逻辑链路. 传输层: 想用户提供可靠的端到端 ...

  7. eq3

    然而一旦美国经济进入持续复苏,美联储必将逐步退出量化宽松和逐渐收紧银根,美国联邦基金利率和银行同业间拆借利率将会上升.这将使美元升值,并使部分套利交易平仓.而一旦美元企稳走强,国债利率上扬,大宗商品价 ...

  8. refresh table tablename ;MSCK REPAIR TABLE table_name;

    在更改分区内的文件后刷新表 refresh table tablename ; 我们平时通常是通过alter table add partition方式增加Hive的分区的,但有时候会通过HDFS p ...

  9. FreeBSD是UNIX系统的重要分支,其命令与Linux大部分通用,少部分是其特有。

    FreeBSD是UNIX系统的重要分支,其命令与Linux大部分通用,少部分是其特有. 1: man 在线查询 man ls2: ls 查看目录与档案 ls -la3: ln 建立链接文件 ln -f ...

  10. 干货分享 -- Math

    昼猫笔记 JavaScript -- Math Math也是JS的内置对象,但是它不是一个构造函数,它属于一个工具类不用创建对象,它封装了数学运算相关的属性和方法,今天就来写下常用的函数[API(ap ...