单点登录解决方案-CAS

释放双眼,带上耳机,听听看~!

开源单点登录系统CAS入门

什么是单点登录

单点登录(Single Sign On),简称为 SSO,是目前比较流行的企业业务整合的解决方案之一。SSO的定义是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统。

我们目前的系统存在诸多子系统,而这些子系统是分别部署在不同的服务器中,那么使用传统方式的session是无法解决的,我们需要使用相关的单点登录技术来解决。
单点登录解决方案-CAS

什么是CAS

CAS 是 Yale 大学发起的一个开源项目,旨在为 Web 应用系统提供一种可靠的单点登录方法,CAS 在 2004 年 12 月正式成为 JA-SIG 的一个项目。CAS 具有以下特点:

  • 开源的企业级单点登录解决方案。
  • CAS Server 为需要独立部署的 Web 应用。
  • CAS Client 支持非常多的客户端(这里指单点登录系统中的各个 Web 应用),包括 Java, .Net, PHP, Perl, Apache, uPortal, Ruby 等。

从结构上看,CAS 包含两个部分: CAS Server 和 CAS Client。CAS Server 需要独立部署,主要负责对用户的认证工作;CAS Client 负责处理对客户端受保护资源的访问请求,需要登录时,重定向到 CAS Server。下图是 CAS 最基本的协议过程:
单点登录解决方案-CAS
SSO单点登录访问流程主要有以下步骤:

  1. 访问服务:SSO客户端发送请求访问应用系统提供的服务资源。
  2. 定向认证:SSO客户端会重定向用户请求到SSO服务器。
  3. 用户身份认证
  4. 发放票据:SSO服务器会产生一个随机的Service Ticket。
  5. 验证票据:SSO服务器验证票据Service Ticket的合法性,验证通过后,允许客户端访问服务。
  6. 传输用户信息:SSO服务器验证票据通过后,传输用户认证结果信息给客户端。

CAS服务端部署

Cas服务端其实就是一个war包。

在资源\cas\source\cas-server-4.0.0-release\cas-server-4.0.0\modules目录下cas-server-webapp-4.0.0.war 将其改名为cas.war放入tomcat目录下的webapps下。启动tomcat自动解压war包。浏览器输入http://localhost:8080/cas/login ,可看到登录页面:
单点登录解决方案-CAS
不要嫌弃这个页面丑,我们后期可以再提升它的颜值。暂时把注意力放在功能实现上。

这里有个固定的用户名和密码 casuser /Mellon

登录成功后会跳到登录成功的提示页面:
单点登录解决方案-CAS

CAS服务端配置

端口修改

(1)修改tomcat的端口

  • 打开tomcat 目录 conf\server.xml 找到下面的配置

单点登录解决方案-CAS
将端口8080,改为9100。

(2)修改CAS配置文件

修改cas的WEB-INF/cas.properties


1
2
3
1server.name=http://localhost:9100
2
3

去除https认证

CAS默认使用的是HTTPS协议,如果使用HTTPS协议需要SSL安全证书(需向特定的机构申请和购买) 。如果对安全要求不高或是在开发测试阶段,可使用HTTP协议。我们这里讲解通过修改配置,让CAS使用HTTP协议。

(1)修改cas的WEB-INF/deployerConfigContext.xml。找到下面的配置


1
2
3
4
1<bean class="org.jasig.cas.authentication.handler.support.HttpBasedServiceCredentialsAuthenticationHandler"
2p:httpClient-ref="httpClient"/>
3
4

这里需要增加参数p:requireSecure="false",requireSecure属性意思为是否需要安全验证,即HTTPS,false为不采用

(2)修改cas的/WEB-INF/spring-configuration/ticketGrantingTicketCookieGenerator.xml。找到下面配置:


1
2
3
4
5
6
7
1<bean id="ticketGrantingTicketCookieGenerator" class="org.jasig.cas.web.support.CookieRetrievingCookieGenerator"
2      p:cookieSecure="true"
3      p:cookieMaxAge="-1"
4      p:cookieName="CASTGC"
5      p:cookiePath="/cas" />
6
7

参数p:cookieSecure=“true”,同理为HTTPS验证相关,TRUE为采用HTTPS验证,FALSE为不采用https验证。

参数p:cookieMaxAge="-1",是COOKIE的最大生命周期,-1为无生命周期,即只在当前打开的窗口有效,关闭或重新打开其它窗口,仍会要求验证。可以根据需要修改为大于0的数字,比如3600等,意思是在3600秒内,打开任意窗口,都不需要验证。

我们这里将cookieSecure改为false , cookieMaxAge 改为3600

(3)修改cas的WEB-INF/spring-configuration/warnCookieGenerator.xml。找到下面配置


1
2
3
4
5
6
7
1<bean id="warnCookieGenerator" class="org.jasig.cas.web.support.CookieRetrievingCookieGenerator"
2p:cookieSecure="true"
3p:cookieMaxAge="-1"
4p:cookieName="CASPRIVACY"
5p:cookiePath="/cas" />
6
7

我们这里将cookieSecure改为false , cookieMaxAge 改为3600

CAS客户端入门小Demo

客户端工程1搭建

(1)搭建工程引入依赖

  • 创建Maven工程 (war)casclient_demo1 引入cas客户端依赖并制定tomcat运行端口为9001


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
1<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
2  <modelVersion>4.0.0</modelVersion>
3  <groupId>cn.itcast.demo</groupId>
4  <artifactId>casclient_demo1</artifactId>
5  <version>0.0.1-SNAPSHOT</version>
6  <packaging>war</packaging>
7  
8  <dependencies>
9       <!-- cas -->  
10      <dependency>  
11          <groupId>org.jasig.cas.client</groupId>  
12          <artifactId>cas-client-core</artifactId>  
13          <version>3.3.3</version>  
14      </dependency>        
15     
16      <dependency>
17          <groupId>javax.servlet</groupId>
18          <artifactId>servlet-api</artifactId>
19          <version>2.5</version>  
20          <scope>provided</scope>
21      </dependency>
22  </dependencies>  
23
24  <build>  
25    <plugins>
26        <plugin>  
27            <groupId>org.apache.maven.plugins</groupId>  
28            <artifactId>maven-compiler-plugin</artifactId>  
29            <version>2.3.2</version>  
30            <configuration>  
31                <source>1.7</source>  
32                <target>1.7</target>  
33            </configuration>  
34        </plugin>  
35        <plugin>
36              <groupId>org.apache.tomcat.maven</groupId>
37              <artifactId>tomcat7-maven-plugin</artifactId>
38              <configuration>
39                  <!-- 指定端口 -->
40                  <port>9001</port>
41                  <!-- 请求路径 -->
42                  <path>/</path>
43              </configuration>
44        </plugin>
45    </plugins>  
46    </build>
47</project>
48
49

(2)添加web.xml


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
1<?xml version="1.0" encoding="UTF-8"?>
2<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3   xmlns="http://java.sun.com/xml/ns/javaee"
4   xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
5   version="2.5">
6  
7   <!-- ======================== 单点登录开始 ======================== -->  
8    <!-- 用于单点退出,该过滤器用于实现单点登出功能,可选配置 -->  
9    <listener>  
10        <listener-class>org.jasig.cas.client.session.SingleSignOutHttpSessionListener</listener-class>  
11    </listener>  
12  
13    <!-- 该过滤器用于实现单点登出功能,可选配置。 -->  
14    <filter>  
15        <filter-name>CAS Single Sign Out Filter</filter-name>  
16        <filter-class>org.jasig.cas.client.session.SingleSignOutFilter</filter-class>  
17    </filter>  
18    <filter-mapping>  
19        <filter-name>CAS Single Sign Out Filter</filter-name>  
20        <url-pattern>/*</url-pattern>  
21    </filter-mapping>  
22  
23    <!-- 该过滤器负责用户的认证工作,必须启用它 -->  
24    <filter>  
25        <filter-name>CASFilter</filter-name>  
26        <filter-class>org.jasig.cas.client.authentication.AuthenticationFilter</filter-class>  
27        <init-param>  
28            <param-name>casServerLoginUrl</param-name>  
29            <param-value>http://localhost:9100/cas/login</param-value>  
30            <!--这里的server是服务端的IP -->  
31        </init-param>  
32        <init-param>  
33            <param-name>serverName</param-name>  
34            <param-value>http://localhost:9001</param-value>
35        </init-param>  
36    </filter>  
37    <filter-mapping>  
38        <filter-name>CASFilter</filter-name>  
39        <url-pattern>/*</url-pattern>  
40    </filter-mapping>  
41  
42    <!-- 该过滤器负责对Ticket的校验工作,必须启用它 -->  
43    <filter>  
44        <filter-name>CAS Validation Filter</filter-name>  
45        <filter-class>  
46            org.jasig.cas.client.validation.Cas20ProxyReceivingTicketValidationFilter</filter-class>  
47        <init-param>  
48            <param-name>casServerUrlPrefix</param-name>  
49            <param-value>http://localhost:9100/cas</param-value>  
50        </init-param>  
51        <init-param>  
52            <param-name>serverName</param-name>  
53            <param-value>http://localhost:9001</param-value>
54        </init-param>  
55    </filter>  
56    <filter-mapping>  
57        <filter-name>CAS Validation Filter</filter-name>  
58        <url-pattern>/*</url-pattern>  
59    </filter-mapping>  
60  
61    <!-- 该过滤器负责实现HttpServletRequest请求的包裹, 比如允许开发者通过HttpServletRequest的getRemoteUser()方法获得SSO登录用户的登录名,可选配置。 -->  
62    <filter>  
63        <filter-name>CAS HttpServletRequest Wrapper Filter</filter-name>  
64        <filter-class>  
65            org.jasig.cas.client.util.HttpServletRequestWrapperFilter</filter-class>  
66    </filter>  
67    <filter-mapping>  
68        <filter-name>CAS HttpServletRequest Wrapper Filter</filter-name>  
69        <url-pattern>/*</url-pattern>  
70    </filter-mapping>  
71  
72    <!-- 该过滤器使得开发者可以通过org.jasig.cas.client.util.AssertionHolder来获取用户的登录名。 比如AssertionHolder.getAssertion().getPrincipal().getName()。 -->  
73    <filter>  
74        <filter-name>CAS Assertion Thread Local Filter</filter-name>  
75        <filter-class>org.jasig.cas.client.util.AssertionThreadLocalFilter</filter-class>  
76    </filter>  
77    <filter-mapping>  
78        <filter-name>CAS Assertion Thread Local Filter</filter-name>  
79        <url-pattern>/*</url-pattern>  
80    </filter-mapping>  
81  
82    <!-- ======================== 单点登录结束 ======================== -->  
83 
84 
85</web-app>
86
87

(3)在webapp下新建index.jsp,编写index.jsp


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
1<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
2<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
3<html>
4<head>
5   <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
6   <title>cas client demo1</title>
7</head>
8<body>
9欢迎来到一品优购  <%=request.getRemoteUser() %>
10
11<a href="http://localhost:9100/cas/logout?service=http://www.baidu.com">退出登录</a>
12</body>
13</html>
14
15

request.getRemoteUser()为获取远程登录名。

客户端工程2搭建

  1. 创建Maven工程 (war)casclient_demo2 引入cas客户端依赖并制定tomcat运行端口为9002
  2. 创建web.xml,参照casclient_demo1 ,将serverName的值改为http://localhost:9002,一共两处
  3. 创建index.jsp ,内容显示“欢迎来到二品优购”

单点登录测试

  1. 启动cas部署的tomcat
  2. 启动客户端工程1和客户端工程2
  3. 地址栏输入http://localhost:9001/http://localhost:9002/ ,地址均会跳转到CAS登录页
  4. 输入用户名和密码后,页面跳转回9002 ,再次访问9001也可以打开主页面。

单点登录退出

地址栏输入 http://localhost:9100/cas/logout

即可看到退出后的提示页面
单点登录解决方案-CAS
我们可以将这个链接添加到index.jsp中


1
2
3
1<a href="http://localhost:9100/cas/logout">退出登录</a>
2
3

但我们更希望退出登录后,能自动跳转到某个页面,那如何处理呢?

修改cas系统的配置文件cas-servlet.xml


1
2
3
4
5
1<bean id="logoutAction" class="org.jasig.cas.web.flow.LogoutAction"
2      p:servicesManager-ref="servicesManager"
3      p:followServiceRedirects="${cas.logout.followServiceRedirects:true}"/>
4
5

改为true后,可以在退出时跳转页面到目标页面,修改index.jsp的退出链接


1
2
3
1<a href="http://localhost:9100/cas/logout?service=http://www.baidu.com">退出登录</a>
2
3

CAS客服端与SpringSecurity集成

Spring Security测试工程搭建

  1. 建立maven项目casclient_demo3 ,引入spring依赖和spring secrity 相关依赖 ,tomcat端口设置为9003


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
1<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
2  <modelVersion>4.0.0</modelVersion>
3  <groupId>cn.itcast.demo</groupId>
4  <artifactId>casclient_demo3</artifactId>
5  <version>0.0.1-SNAPSHOT</version>
6  <packaging>war</packaging>
7  
8  
9  <properties>
10      <spring.version>4.2.4.RELEASE</spring.version>
11  </properties>
12
13  <dependencies>
14
15      <dependency>
16          <groupId>org.springframework</groupId>
17          <artifactId>spring-core</artifactId>
18          <version>${spring.version}</version>
19      </dependency>
20      <dependency>
21          <groupId>org.springframework</groupId>
22          <artifactId>spring-web</artifactId>
23          <version>${spring.version}</version>
24      </dependency>
25
26      <dependency>
27          <groupId>org.springframework</groupId>
28          <artifactId>spring-webmvc</artifactId>
29          <version>${spring.version}</version>
30      </dependency>
31
32      <dependency>
33          <groupId>org.springframework</groupId>
34          <artifactId>spring-context-support</artifactId>
35          <version>${spring.version}</version>
36      </dependency>
37
38      <dependency>
39          <groupId>org.springframework</groupId>
40          <artifactId>spring-test</artifactId>
41          <version>${spring.version}</version>
42      </dependency>
43
44      <dependency>
45          <groupId>org.springframework</groupId>
46          <artifactId>spring-jdbc</artifactId>
47          <version>${spring.version}</version>
48      </dependency>
49     
50      <dependency>
51          <groupId>javax.servlet</groupId>
52          <artifactId>servlet-api</artifactId>
53          <version>2.5</version>
54          <scope>provided</scope>
55      </dependency>
56
57      <dependency>
58          <groupId>org.springframework.security</groupId>
59          <artifactId>spring-security-web</artifactId>
60          <version>4.1.0.RELEASE</version>
61      </dependency>
62
63      <dependency>
64          <groupId>org.springframework.security</groupId>
65          <artifactId>spring-security-config</artifactId>
66          <version>4.1.0.RELEASE</version>
67      </dependency>
68
69 
70     
71      <dependency>
72          <groupId>org.springframework.security</groupId>
73          <artifactId>spring-security-cas</artifactId>
74          <version>4.1.0.RELEASE</version>
75      </dependency>
76      <dependency>
77          <groupId>org.jasig.cas.client</groupId>
78          <artifactId>cas-client-core</artifactId>
79          <version>3.3.3</version>
80          <exclusions>
81              <exclusion>
82                  <groupId>org.slf4j</groupId>
83                  <artifactId>log4j-over-slf4j</artifactId>
84              </exclusion>
85          </exclusions>
86      </dependency>
87  </dependencies>
88  <build>
89    <plugins>      
90        <!-- java编译插件 -->
91        <plugin>
92              <groupId>org.apache.maven.plugins</groupId>
93              <artifactId>maven-compiler-plugin</artifactId>
94              <version>3.2</version>
95              <configuration>
96                  <source>1.7</source>
97                  <target>1.7</target>
98                  <encoding>UTF-8</encoding>
99              </configuration>
100       </plugin>      
101       <plugin>
102             <groupId>org.apache.tomcat.maven</groupId>
103             <artifactId>tomcat7-maven-plugin</artifactId>
104             <configuration>
105                 <!-- 指定端口 -->
106                 <port>9003</port>
107                 <!-- 请求路径 -->
108                 <path>/</path>
109             </configuration>
110       </plugin>
111    </plugins>  
112    </build>
113</project>
114
115
  1. 建立web.xml ,添加过滤器等配置


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
1<?xml version="1.0" encoding="UTF-8"?>
2<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3   xmlns="http://java.sun.com/xml/ns/javaee"
4   xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
5   version="2.5">
6
7    <context-param>
8       <param-name>contextConfigLocation</param-name>
9       <param-value>classpath:spring-security.xml</param-value>
10   </context-param>
11   <listener>
12      <listener-class>
13          org.springframework.web.context.ContextLoaderListener
14      </listener-class>
15   </listener>
16 
17   <filter>  
18      <filter-name>springSecurityFilterChain</filter-name>  
19      <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>  
20   </filter>  
21   <filter-mapping>  
22      <filter-name>springSecurityFilterChain</filter-name>  
23      <url-pattern>/*</url-pattern>  
24   </filter-mapping>
25 
26 
27  <servlet>
28  <servlet-name>springmvc</servlet-name>
29  <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
30  <!-- 指定加载的配置文件 ,通过参数 contextConfigLocation 加载-->
31      <init-param>
32      <param-name>contextConfigLocation</param-name>
33      <param-value>classpath:springmvc.xml</param-value>
34      </init-param>
35  </servlet>
36  <servlet-mapping>
37      <servlet-name>springmvc</servlet-name>
38      <url-pattern>*.do</url-pattern>
39  </servlet-mapping>   
40</web-app>
41
42
  1. 创建配置文件springmvc.xml


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
1<?xml version="1.0" encoding="UTF-8"?>
2<beans xmlns="http://www.springframework.org/schema/beans"
3   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
4   xmlns:context="http://www.springframework.org/schema/context"
5   xmlns:dubbo="http://code.alibabatech.com/schema/dubbo" xmlns:mvc="http://www.springframework.org/schema/mvc"
6   xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
7        http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
8        http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd
9        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
10  
11  
12    <context:component-scan base-package="cn.itcast.demo" />
13  <mvc:annotation-driven />
14
15</beans>
16
17
  1. 创建spring-security.xml文件


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
1<?xml version="1.0" encoding="UTF-8"?>
2<beans:beans xmlns="http://www.springframework.org/schema/security"
3   xmlns:beans="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4   xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
5                       http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd">
6  
7   <!--   entry-point-ref  入口点引用 -->
8   <http use-expressions="false" entry-point-ref="casProcessingFilterEntryPoint">  
9        <intercept-url pattern="/**" access="ROLE_USER"/>  
10        <csrf disabled="true"/>  
11        <!-- custom-filter为过滤器, position 表示将过滤器放在指定的位置上,before表示放在指定位置之前  ,after表示放在指定的位置之后  -->          
12        <custom-filter ref="casAuthenticationFilter"  position="CAS_FILTER" />      
13        <custom-filter ref="requestSingleLogoutFilter" before="LOGOUT_FILTER"/>  
14        <custom-filter ref="singleLogoutFilter" before="CAS_FILTER"/>  
15    </http>
16    
17      <!-- CAS入口点 开始 -->
18    <beans:bean id="casProcessingFilterEntryPoint" class="org.springframework.security.cas.web.CasAuthenticationEntryPoint">  
19        <!-- 单点登录服务器登录URL -->  
20        <beans:property name="loginUrl" value="http://localhost:9100/cas/login"/>  
21        <beans:property name="serviceProperties" ref="serviceProperties"/>  
22    </beans:bean>      
23    <beans:bean id="serviceProperties" class="org.springframework.security.cas.ServiceProperties">  
24        <!--service 配置自身工程的根地址+/login/cas   -->  
25        <beans:property name="service" value="http://localhost:9003/login/cas"/>
26    </beans:bean>  
27    <!-- CAS入口点 结束 -->
28  
29    <!-- 认证过滤器 开始 -->
30    <beans:bean id="casAuthenticationFilter" class="org.springframework.security.cas.web.CasAuthenticationFilter">  
31        <beans:property name="authenticationManager" ref="authenticationManager"/>  
32    </beans:bean>  
33      <!-- 认证管理器 -->
34  <authentication-manager alias="authenticationManager">
35      <authentication-provider  ref="casAuthenticationProvider">
36      </authentication-provider>
37  </authentication-manager>
38      <!-- 认证提供者 -->
39  <beans:bean id="casAuthenticationProvider"     class="org.springframework.security.cas.authentication.CasAuthenticationProvider">  
40        <beans:property name="authenticationUserDetailsService">  
41            <beans:bean class="org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper">  
42                <beans:constructor-arg ref="userDetailsService" />  
43            </beans:bean>  
44        </beans:property>  
45        <beans:property name="serviceProperties" ref="serviceProperties"/>  
46        <!-- ticketValidator 为票据验证器 -->
47        <beans:property name="ticketValidator">  
48            <beans:bean class="org.jasig.cas.client.validation.Cas20ServiceTicketValidator">  
49                <beans:constructor-arg index="0" value="http://localhost:9100/cas"/>  
50            </beans:bean>  
51        </beans:property>  
52        <beans:property name="key" value="an_id_for_this_auth_provider_only"/>
53    </beans:bean>        
54           <!-- 认证类 -->
55  <beans:bean id="userDetailsService" class="cn.itcast.demo.service.UserDetailServiceImpl"/>  
56 
57  <!-- 认证过滤器 结束 -->
58  <!-- 单点登出  开始  -->    
59    <beans:bean id="singleLogoutFilter" class="org.jasig.cas.client.session.SingleSignOutFilter"/>          
60    <beans:bean id="requestSingleLogoutFilter" class="org.springframework.security.web.authentication.logout.LogoutFilter">  
61        <beans:constructor-arg value="http://localhost:9100/cas/logout?service=http://www.baidu.com"/>  
62        <beans:constructor-arg>  
63            <beans:bean class="org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler"/>  
64        </beans:constructor-arg>  
65        <beans:property name="filterProcessesUrl" value="/logout/cas"/>  
66    </beans:bean>  
67    <!-- 单点登出  结束 -->  
68</beans:beans>
69
70
  1. 添加html页面

单点登录解决方案-CAS

  • index.html


1
2
3
4
5
6
7
8
9
10
11
12
1<!DOCTYPE html>
2<html>
3<head>
4<meta charset="UTF-8">
5<title>首页</title>
6</head>
7<body>
8欢迎进入神奇的spring security世界~~~  <a href="logout/cas">退出</a>
9</body>
10</html>
11
12
  • index2.html


1
2
3
4
5
6
7
8
9
10
11
12
1<!DOCTYPE html>
2<html>
3<head>
4<meta charset="UTF-8">
5<title>首页</title>
6</head>
7<body>
8你已退出神奇的spring security世界~~~ 再见!
9</body>
10</html>
11
12
  • login_error.html


1
2
3
4
5
6
7
8
9
10
11
12
1<!DOCTYPE html>
2<html>
3<head>
4<meta charset="UTF-8">
5<title>首页</title>
6</head>
7<body>
8用户名或密码错误~~~
9</body>
10</html>
11
12
  • login.html


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
1<!DOCTYPE html>
2<html>
3<head>
4<meta charset="UTF-8">
5<title>登陆</title>
6</head>
7<body>
8
9--欢迎的登陆我的系统--
10<form action="/login" method="post">
11  用户名:<input name="username"><br>
12  密码:<input name="password"><br>
13  <button>登陆</button>
14</form>
15
16
17</body>
18</html>
19
20

以上步骤参照我们第四章的spring-security-demo

Spring Security与CAS集成

(1)引入依赖


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
1<dependency>  
2      <groupId>org.springframework.security</groupId>  
3      <artifactId>spring-security-cas</artifactId>  
4      <version>4.1.0.RELEASE</version>  
5</dependency>    
6<dependency>  
7        <groupId>org.jasig.cas.client</groupId>  
8        <artifactId>cas-client-core</artifactId>  
9        <version>3.3.3</version>  
10        <exclusions>  
11            <exclusion>  
12                <groupId>org.slf4j</groupId>  
13                <artifactId>log4j-over-slf4j</artifactId>  
14            </exclusion>  
15        </exclusions>  
16</dependency>
17
18

(2)修改spring-security.xml


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
1<?xml version="1.0" encoding="UTF-8"?>
2<beans:beans xmlns="http://www.springframework.org/schema/security"
3   xmlns:beans="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4   xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
5                       http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd">
6  
7   <!--   entry-point-ref  入口点引用 -->
8   <http use-expressions="false" entry-point-ref="casProcessingFilterEntryPoint">  
9        <intercept-url pattern="/**" access="ROLE_USER"/>  
10        <csrf disabled="true"/>  
11        <!-- custom-filter为过滤器, position 表示将过滤器放在指定的位置上,before表示放在指定位置之前  ,after表示放在指定的位置之后  -->          
12        <custom-filter ref="casAuthenticationFilter"  position="CAS_FILTER" />      
13        <custom-filter ref="requestSingleLogoutFilter" before="LOGOUT_FILTER"/>  
14        <custom-filter ref="singleLogoutFilter" before="CAS_FILTER"/>  
15    </http>
16    
17      <!-- CAS入口点 开始 -->
18    <beans:bean id="casProcessingFilterEntryPoint" class="org.springframework.security.cas.web.CasAuthenticationEntryPoint">  
19        <!-- 单点登录服务器登录URL -->  
20        <beans:property name="loginUrl" value="http://localhost:9100/cas/login"/>  
21        <beans:property name="serviceProperties" ref="serviceProperties"/>  
22    </beans:bean>      
23    <beans:bean id="serviceProperties" class="org.springframework.security.cas.ServiceProperties">  
24        <!--service 配置自身工程的根地址+/login/cas   -->  
25        <beans:property name="service" value="http://localhost:9003/login/cas"/>
26    </beans:bean>  
27    <!-- CAS入口点 结束 -->
28  
29    <!-- 认证过滤器 开始 -->
30    <beans:bean id="casAuthenticationFilter" class="org.springframework.security.cas.web.CasAuthenticationFilter">  
31        <beans:property name="authenticationManager" ref="authenticationManager"/>  
32    </beans:bean>  
33      <!-- 认证管理器 -->
34  <authentication-manager alias="authenticationManager">
35      <authentication-provider  ref="casAuthenticationProvider">
36      </authentication-provider>
37  </authentication-manager>
38      <!-- 认证提供者 -->
39  <beans:bean id="casAuthenticationProvider"     class="org.springframework.security.cas.authentication.CasAuthenticationProvider">  
40        <beans:property name="authenticationUserDetailsService">  
41            <beans:bean class="org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper">  
42                <beans:constructor-arg ref="userDetailsService" />  
43            </beans:bean>  
44        </beans:property>  
45        <beans:property name="serviceProperties" ref="serviceProperties"/>  
46        <!-- ticketValidator 为票据验证器 -->
47        <beans:property name="ticketValidator">  
48            <beans:bean class="org.jasig.cas.client.validation.Cas20ServiceTicketValidator">  
49                <beans:constructor-arg index="0" value="http://localhost:9100/cas"/>  
50            </beans:bean>  
51        </beans:property>  
52        <beans:property name="key" value="an_id_for_this_auth_provider_only"/>
53    </beans:bean>        
54           <!-- 认证类 -->
55  <beans:bean id="userDetailsService" class="cn.itcast.demo.service.UserDetailServiceImpl"/>  
56 
57  <!-- 认证过滤器 结束 -->
58  <!-- 单点登出  开始  -->    
59    <beans:bean id="singleLogoutFilter" class="org.jasig.cas.client.session.SingleSignOutFilter"/>          
60    <beans:bean id="requestSingleLogoutFilter" class="org.springframework.security.web.authentication.logout.LogoutFilter">  
61        <beans:constructor-arg value="http://localhost:9100/cas/logout?service=http://www.baidu.com"/>  
62        <beans:constructor-arg>  
63            <beans:bean class="org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler"/>  
64        </beans:constructor-arg>  
65        <beans:property name="filterProcessesUrl" value="/logout/cas"/>  
66    </beans:bean>  
67    <!-- 单点登出  结束 -->  
68</beans:beans>
69
70

(3)创建UserDetailsServiceImpl


1
2
3
4
5
6
7
8
9
10
11
12
13
14
1/**
2 * 认证类
3 */
4public class UserDetailServiceImpl implements UserDetailsService {
5   @Override
6   public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
7       //构建角色集合
8       List<GrantedAuthority> authorities=new ArrayList();
9       authorities.add(new SimpleGrantedAuthority("ROLE_USER"));
10      return new User(username, ""  , authorities);    
11  }
12}
13
14

这个类的主要作用是在登陆后得到用户名,可以根据用户名查询角色或执行一些逻辑。

获取登录名

我们在处理后端逻辑需要获得登录名,那么如何获取单点登录的用户名呢? 其实和我们之前获得用户名的方式是完全相同的,我们下面来做个测试。

(1)web.xml 添加springmvc


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
1<servlet>
2   <servlet-name>springmvc</servlet-name>
3   <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
4<!-- 指定加载的配置文件 ,通过参数contextConfigLocation加载-->
5<init-param>
6   <param-name>contextConfigLocation</param-name>
7   <param-value>classpath:springmvc.xml</param-value>
8</init-param>
9</servlet>
10
11<servlet-mapping>
12  <servlet-name>springmvc</servlet-name>
13  <url-pattern>*.do</url-pattern>
14</servlet-mapping>
15
16

(2)创建springmvc.xml


1
2
3
4
1   <context:component-scan base-package="cn.itcast.demo" />
2   <mvc:annotation-driven />
3
4

(3)创建UserController


1
2
3
4
5
6
7
8
9
10
1@RestController
2public class UserController {
3   @RequestMapping("/findLoginUser")
4   public void  findLoginUser(){
5       String name = SecurityContextHolder.getContext().getAuthentication().getName();
6       System.out.println(name);      
7   }  
8}
9
10

地址栏输入http://localhost:9003/findLoginUser.do 即可在控制台看到输出的登录名。

退出登录

修改spring-security.xml


1
2
3
4
5
6
7
8
9
1<beans:bean id="requestSingleLogoutFilter" class="org.springframework.security.web.authentication.logout.LogoutFilter">  
2        <beans:constructor-arg value="http://localhost:9100/cas/logout?service=http://localhost:9003/index2.html"/>  
3        <beans:constructor-arg>  
4            <beans:bean class="org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler"/>  
5        </beans:constructor-arg>  
6        <beans:property name="filterProcessesUrl" value="/logout/cas"/>  
7</beans:bean>
8
9

修改spring-security.xml

在页面上添加链接


1
2
3
1<a href="/logout/cas">退出登录</a>
2
3

创建index2.html,将index2.html设置为可匿名访问


1
2
3
1<http pattern="/index2.html" security="none"></http>
2
3

给TA打赏
共{{data.count}}人
人已打赏
安全经验

如何避免Adsense违规封号

2021-10-11 16:36:11

安全经验

安全咨询服务

2022-1-12 14:11:49

个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索