CAS5.3 單點登錄/登出/springboot/springmvc


環境:

jdk:1.8

cas server:5.3.14 + tomcat 8.5

cas client:3.5.1

客戶端1:springmvc 傳統web項目(使用web.xml)

客戶端2:springboot 

參考博客:https://blog.csdn.net/anumbrella/category_7765386.html

為了方便,沒配置https.如果需要參考上面博客

一.CAS 服務端搭建

1.下載源碼包:cas overlay github地址:https://github.com/apereo/cas-overlay-template/tree/5.3

2.部署:

在根目錄下執行mvn clean package,下載依賴需要一段時間,如果有的包下載失敗就要修改pom.xml比如xmlsectool的jar包要先從maven中央倉庫手動下載,然后加進去,我的放到了圖中的maven目錄下

 以下是我修改的pom.xml,對xmlselectool依賴路徑進行了更改,增加了json注冊服務,jdbc驗證等依賴包

  1 <?xml version="1.0" encoding="UTF-8"?>
  2 <project xmlns="http://maven.apache.org/POM/4.0.0"
  3          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd ">
  5 
  6 
  7     <modelVersion>4.0.0</modelVersion>
  8     <groupId>org.apereo.cas</groupId>
  9     <artifactId>cas-overlay</artifactId>
 10     <packaging>war</packaging>
 11     <version>1.0</version>
 12 
 13     <build>
 14         <plugins>
 15             <plugin>
 16                 <groupId>com.rimerosolutions.maven.plugins</groupId>
 17                 <artifactId>wrapper-maven-plugin</artifactId>
 18                 <version>0.0.5</version>
 19                 <configuration>
 20                     <verifyDownload>true</verifyDownload>
 21                     <checksumAlgorithm>MD5</checksumAlgorithm>
 22                 </configuration>
 23             </plugin>
 24             <plugin>
 25                 <groupId>org.springframework.boot</groupId>
 26                 <artifactId>spring-boot-maven-plugin</artifactId>
 27                 <version>${springboot.version}</version>
 28                 <configuration>
 29                     <mainClass>${mainClassName}</mainClass>
 30                     <addResources>true</addResources>
 31                     <executable>${isExecutable}</executable>
 32                     <layout>WAR</layout>
 33                 </configuration>
 34                 <executions>
 35                     <execution>
 36                         <goals>
 37                             <goal>repackage</goal>
 38                         </goals>
 39                     </execution>
 40                 </executions>
 41             </plugin>
 42             <plugin>
 43                 <groupId>org.apache.maven.plugins</groupId>
 44                 <artifactId>maven-war-plugin</artifactId>
 45                 <version>2.6</version>
 46                 <configuration>
 47                     <warName>cas</warName>
 48                     <failOnMissingWebXml>false</failOnMissingWebXml>
 49                     <recompressZippedFiles>false</recompressZippedFiles>
 50                     <archive>
 51                         <compress>false</compress>
 52                         <manifestFile>${manifestFileToUse}</manifestFile>
 53                     </archive>
 54                     <overlays>
 55                         <overlay>
 56                             <groupId>org.apereo.cas</groupId>
 57                             <artifactId>cas-server-webapp${app.server}</artifactId>
 58                         </overlay>
 59                     </overlays>
 60                 </configuration>
 61             </plugin>
 62             <plugin>
 63                 <groupId>org.apache.maven.plugins</groupId>
 64                 <artifactId>maven-compiler-plugin</artifactId>
 65                 <version>3.3</version>
 66             </plugin>
 67         </plugins>
 68         <finalName>cas</finalName>
 69     </build>
 70 
 71     <properties>
 72         <cas.version>5.3.14</cas.version>
 73         <springboot.version>1.5.18.RELEASE</springboot.version>
 74         <mybatis.spring.version>1.3.2</mybatis.spring.version>
 75         <mybatis.version>3.4.6</mybatis.version>
 76         <!-- app.server could be -jetty, -undertow, -tomcat, or blank if you plan to provide appserver -->
 77         <app.server>-tomcat</app.server>
 78 
 79         <mainClassName>org.springframework.boot.loader.WarLauncher</mainClassName>
 80         <isExecutable>false</isExecutable>
 81         <manifestFileToUse>${project.build.directory}/war/work/org.apereo.cas/cas-server-webapp${app.server}/META-INF/MANIFEST.MF</manifestFileToUse>
 82 
 83         <maven.compiler.source>1.8</maven.compiler.source>
 84         <maven.compiler.target>1.8</maven.compiler.target>
 85         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
 86     </properties>
 87 
 88    <dependencies>
 89          <dependency>
 90             <groupId>net.shibboleth.tool</groupId>
 91             <artifactId>xmlsectool</artifactId>
 92             <version>2.0.0</version>
 93              <scope>system</scope>
 94             <systemPath>${pom.basedir}/maven/xmlsectool-2.0.0.jar</systemPath>
 95          </dependency>
 96        <!--新增支持jdbc驗證-->
 97        <dependency>
 98            <groupId>org.apereo.cas</groupId>
 99            <artifactId>cas-server-support-jdbc</artifactId>
100            <version>${cas.version}</version>
101            <exclusions>
102                <exclusion>
103                    <artifactId>jul-to-slf4j</artifactId>
104                    <groupId>org.slf4j</groupId>
105                </exclusion>
106            </exclusions>
107        </dependency>
108 
109 
110        <dependency>
111            <groupId>org.apereo.cas</groupId>
112            <artifactId>cas-server-core-cookie</artifactId>
113            <version>${cas.version}</version>
114        </dependency>
115 
116        <dependency>
117            <groupId>org.apereo.cas</groupId>
118            <artifactId>cas-server-support-jdbc-drivers</artifactId>
119            <version>${cas.version}</version>
120            <scope>runtime</scope>
121        </dependency>
122 
123        <dependency>
124            <groupId>org.apereo.cas</groupId>
125            <artifactId>cas-server-core-configuration</artifactId>
126            <version>${cas.version}</version>
127        </dependency>
128 
129        <!-- Custom Authentication -->
130        <dependency>
131            <groupId>org.apereo.cas</groupId>
132            <artifactId>cas-server-core-authentication-api</artifactId>
133            <version>${cas.version}</version>
134        </dependency>
135 
136        <!-- Custom Configuration -->
137        <dependency>
138            <groupId>org.apereo.cas</groupId>
139            <artifactId>cas-server-core-configuration-api</artifactId>
140            <version>${cas.version}</version>
141        </dependency>
142 
143 
144        <dependency>
145            <groupId>org.apereo.cas</groupId>
146            <artifactId>cas-server-support-json-service-registry</artifactId>
147            <version>${cas.version}</version>
148        </dependency>
149 
150        <!-- Authentication Attributes -->
151        <dependency>
152            <groupId>org.apereo.cas</groupId>
153            <artifactId>cas-server-core-authentication-attributes</artifactId>
154            <version>${cas.version}</version>
155        </dependency>
156 
157        <dependency>
158            <groupId>com.alibaba</groupId>
159            <artifactId>fastjson</artifactId>
160            <version>1.2.56</version>
161        </dependency>
162 
163 
164        <!-- lombok -->
165        <dependency>
166            <groupId>org.projectlombok</groupId>
167            <artifactId>lombok</artifactId>
168            <version>1.18.10</version>
169            <scope>provided</scope>
170        </dependency>
171 
172        <dependency>
173            <groupId>org.apereo.cas</groupId>
174            <artifactId>cas-server-core-webflow</artifactId>
175            <version>${cas.version}</version>
176        </dependency>
177 
178 
179 
180 
181      </dependencies>
182 
183     <profiles>
184         <profile>
185             <activation>
186                 <activeByDefault>true</activeByDefault>
187             </activation>
188             <id>default</id>
189             <dependencies>
190                 <dependency>
191                     <groupId>org.apereo.cas</groupId>
192                     <artifactId>cas-server-webapp${app.server}</artifactId>
193                     <version>${cas.version}</version>
194                     <type>war</type>
195                     <scope>runtime</scope>
196                 </dependency>
197                 <!--
198                 ...Additional dependencies may be placed here...
199                 -->
200             </dependencies>
201         </profile>
202 
203         <profile>
204             <activation>
205                 <activeByDefault>false</activeByDefault>
206             </activation>
207             <id>exec</id>
208             <properties>
209                 <mainClassName>org.apereo.cas.web.CasWebApplication</mainClassName>
210                 <isExecutable>true</isExecutable>
211                 <manifestFileToUse></manifestFileToUse>
212             </properties>
213             <build>
214                 <plugins>
215                     <plugin>
216                         <groupId>com.soebes.maven.plugins</groupId>
217                         <artifactId>echo-maven-plugin</artifactId>
218                         <version>0.3.0</version>
219                         <executions>
220                             <execution>
221                                 <phase>prepare-package</phase>
222                                 <goals>
223                                     <goal>echo</goal>
224                                 </goals>
225                             </execution>
226                         </executions>
227                         <configuration>
228                             <echos>
229                                 <echo>Executable profile to make the generated CAS web application executable.</echo>
230                             </echos>
231                         </configuration>
232                     </plugin>
233                 </plugins>
234             </build>
235         </profile>
236 
237         <profile>
238             <activation>
239                 <activeByDefault>false</activeByDefault>
240             </activation>
241             <id>bootiful</id>
242             <properties>
243                 <app.server>-tomcat</app.server>
244                 <isExecutable>false</isExecutable>
245             </properties>
246             <dependencies>
247                 <dependency>
248                     <groupId>org.apereo.cas</groupId>
249                     <artifactId>cas-server-webapp${app.server}</artifactId>
250                     <version>${cas.version}</version>
251                     <type>war</type>
252                     <scope>runtime</scope>
253                 </dependency>
254             </dependencies>
255         </profile>
256 
257         <profile>
258             <activation>
259                 <activeByDefault>false</activeByDefault>
260             </activation>
261             <id>pgp</id>
262             <build>
263                 <plugins>
264                     <plugin>
265                         <groupId>com.github.s4u.plugins</groupId>
266                         <artifactId>pgpverify-maven-plugin</artifactId>
267                         <version>1.1.0</version>
268                         <executions>
269                             <execution>
270                                 <goals>
271                                     <goal>check</goal>
272                                 </goals>
273                             </execution>
274                         </executions>
275                         <configuration>
276                             <pgpKeyServer>hkp://pool.sks-keyservers.net</pgpKeyServer>
277                             <pgpKeysCachePath>${settings.localRepository}/pgpkeys-cache</pgpKeysCachePath>
278                             <scope>test</scope>
279                             <verifyPomFiles>true</verifyPomFiles>
280                             <failNoSignature>false</failNoSignature>
281                         </configuration>
282                     </plugin>
283                 </plugins>
284             </build>
285         </profile>
286     </profiles>
287 </project>
View Code

2.接下來我們要做一些定制化,如果想先看下效果參考https://blog.csdn.net/Anumbrella/article/details/81045885

導入idea,導入的時候可以看到實際導入的是

新建src/main/java和resources,鼠標放到項目上,然后F4,把java目錄標記為sources,resources標記為resources

從overlays目錄下的WEB-INF拷貝services,META-INF文件夾已經application.properties到我們新建的resources目錄下

先說下services文件夾,該文件夾下的json文件定義了哪些應用要接入cas,命名格式為 app-id.json如

重點講下兩個屬性:1.serviceId定義哪些服務可以接入,可以寫統配符,也可以用項目名2.attributeReleaseStrategy定義返回哪些屬性,比如登錄后返回的用戶信息,其他的參考

https://apereo.github.io/cas/5.3.x/installation/Service-Management.html,提醒下logouturl謹慎使用,一定概率造成無法單點退出

 

 application.properties,端口號,項目名,開啟json服務識別

 1 ##  2 # CAS Server Context Configuration  3 #  4 server.context-path=/cas  5 #server.port=8443
 6 server.port=8090
 7 server.ssl.enabled=false
 8 #server.ssl.key-store=file:/etc/cas/thekeystore  9 #server.ssl.key-store-password=changeit  10 #server.ssl.key-password=changeit  11         
 12 cas.tgc.secure=false
 13 
 14 spring.devtools.restart.enabled=true
 15 
 16 
 17 server.max-http-header-size=2097152
 18 server.use-forward-headers=true
 19 server.connection-timeout=20000
 20 server.error.include-stacktrace=ALWAYS  21 
 22 server.compression.enabled=true
 23 server.compression.mime-types=application/javascript,application/json,application/xml,text/html,text/xml,text/plain  24 
 25 server.tomcat.max-http-post-size=2097152
 26 server.tomcat.basedir=build/tomcat  27 server.tomcat.accesslog.enabled=true
 28 server.tomcat.accesslog.pattern=%t %a "%r" %s (%D ms)  29 server.tomcat.accesslog.suffix=.log  30 server.tomcat.min-spare-threads=10
 31 server.tomcat.max-threads=200
 32 server.tomcat.port-header=X-Forwarded-Port  33 server.tomcat.protocol-header=X-Forwarded-Proto  34 server.tomcat.protocol-header-https-value=https  35 server.tomcat.remote-ip-header=X-FORWARDED-FOR  36 server.tomcat.uri-encoding=UTF-8
 37 
 38 spring.http.encoding.charset=UTF-8
 39 spring.http.encoding.enabled=true
 40 spring.http.encoding.force=true
 41 
 42 ##  43 # CAS Cloud Bus Configuration  44 #  45 spring.cloud.bus.enabled=false
 46 
 47 # Indicates that systemPropertiesOverride can be used.  48 # Set to false to prevent users from changing the default accidentally. Default true.  49 spring.cloud.config.allow-override=true
 50 
 51 # External properties should override system properties.  52 spring.cloud.config.override-system-properties=false
 53 
 54 # When allowOverride is true, external properties should take lowest priority, and not override any  55 # existing property sources (including local config files).  56 spring.cloud.config.override-none=false
 57 
 58 # spring.cloud.bus.refresh.enabled=true
 59 # spring.cloud.bus.env.enabled=true
 60 # spring.cloud.bus.destination=CasCloudBus  61 # spring.cloud.bus.ack.enabled=true
 62 
 63 endpoints.enabled=false
 64 endpoints.sensitive=true
 65 
 66 endpoints.restart.enabled=false
 67 endpoints.shutdown.enabled=false
 68 
 69 # Control the security of the management/actuator endpoints  70 # The 'enabled' flag below here controls the rendering of details for the health endpoint amongst other things.  71 management.security.enabled=true
 72 management.security.roles=ACTUATOR,ADMIN  73 management.security.sessions=if_required  74 management.context-path=/status  75 management.add-application-context-header=false
 76 
 77 # Define a CAS-specific "WARN" status code and its order  78 management.health.status.order=WARN, DOWN, OUT_OF_SERVICE, UNKNOWN, UP  79 
 80 # Control the security of the management/actuator endpoints  81 # With basic authentication, assuming Spring Security and/or relevant modules are on the classpath.  82 security.basic.authorize-mode=role  83 security.basic.path=/cas/status/**
 84 security.basic.enabled=true  85 security.user.name=casuser  86 security.user.password=123  87 
 88 ##  89 # CAS Web Application Session Configuration  90 #  91 server.session.timeout=3000  92 server.session.cookie.http-only=false  93 server.session.tracking-modes=COOKIE  94 
 95 ##  96 # CAS Thymeleaf View Configuration  97 #  98 spring.thymeleaf.encoding=UTF-8  99 spring.thymeleaf.cache=true 100 spring.thymeleaf.mode=HTML 101 spring.thymeleaf.template-resolver-order=100 102 ## 103 # CAS Log4j Configuration 104 # 105 # logging.config=file:/etc/cas/log4j2.xml 106 server.context-parameters.isLog4jAutoInitializationDisabled=true 107 
108 ## 109 # CAS AspectJ Configuration 110 # 111 spring.aop.auto=true 112 spring.aop.proxy-target-class=true 113 
114 ## 115 # CAS Authentication Credentials 116 # 117 #cas.authn.accept.users=wangyuancheng::Baizhu7958 118 
119 
120 
121 ## 122 # Service Registry(服務注冊) 123 # 124 # 開啟識別Json文件,默認false 125 cas.serviceRegistry.initFromJson=true 126 
127 #自動掃描服務配置,默認開啟 128 #cas.serviceRegistry.watcherEnabled=true 129 
130 #120秒掃描一遍 131 cas.serviceRegistry.schedule.repeatInterval=120000 132 
133 #延遲15秒開啟 134 # cas.serviceRegistry.schedule.startDelay=15000 135 
136 ## 137 # Json配置 138 cas.serviceRegistry.json.location=classpath:/services 139 
140 
141 cas.ticket.tgt.maxTimeToLiveInSeconds=28800 142 cas.ticket.tgt.timeToKillInSeconds=7200 143 cas.ticket.tgt.rememberMe.enabled=true 144 # 使用次數 145 cas.ticket.st.numberOfUses=1 146 # 過期時間100秒 147 cas.ticket.st.timeToKillInSeconds=100 148 
149 cas.httpClient.allowLocalLogoutUrls=true 150 
151 
152 cas.slo.disabled=false 153 cas.logout.followServiceRedirects=true 154 cas.logout.removeDescendantTickets=true 155 cas.slo.asynchronous=true

默認情況下cas會提供一個jdbc的驗證方式,把sql寫在application.properties,但這種方式無法提供返回的用戶信息,因此需要定義驗證處理器及配置信息

 1 package cn.bz.bzsso.authentication;
 2 
 3 import cn.bz.bzsso.entity.User;
 4 import cn.bz.bzsso.handler.MyAuthenticationHandler;
 5 import cn.bz.bzsso.mapper.UserMapper;
 6 import org.apereo.cas.authentication.AuthenticationEventExecutionPlan;
 7 import org.apereo.cas.authentication.AuthenticationEventExecutionPlanConfigurer;
 8 import org.apereo.cas.authentication.AuthenticationHandler;
 9 import org.apereo.cas.authentication.principal.DefaultPrincipalFactory;
10 import org.apereo.cas.configuration.CasConfigurationProperties;
11 import org.apereo.cas.services.ServicesManager;
12 import org.springframework.beans.factory.annotation.Autowired;
13 import org.springframework.beans.factory.annotation.Qualifier;
14 import org.springframework.boot.context.properties.EnableConfigurationProperties;
15 import org.springframework.context.annotation.Bean;
16 import org.springframework.context.annotation.Configuration;
17 
18 /**
19  * @author tele
20  * @Description
21  * @create 2019-12-04
22  */
23 @Configuration("myAuthenticationConfiguration")
24 @EnableConfigurationProperties(CasConfigurationProperties.class)
25 public class MyAuthenticationConfiguration implements AuthenticationEventExecutionPlanConfigurer {
26 
27     @Autowired
28     private CasConfigurationProperties casProperties;
29 
30     @Autowired
31     @Qualifier("servicesManager")
32     private ServicesManager servicesManager;
33 
34 
35     /**
36      * 將自定義驗證器注冊為Bean
37      * @return
38      */
39     @Bean
40     public AuthenticationHandler myAuthenticationHandler() {
41         MyAuthenticationHandler handler = new MyAuthenticationHandler(MyAuthenticationHandler.class.getSimpleName(), servicesManager, new DefaultPrincipalFactory(), 1);
42         return handler;
43     }
44 
45     /**
46      * 注冊驗證器
47      * @param plan
48      */
49     @Override
50     public void configureAuthenticationExecutionPlan(AuthenticationEventExecutionPlan plan) {
51         plan.registerAuthenticationHandler(myAuthenticationHandler());
52     }
53 }
View Code
 1 package cn.bz.bzsso.handler;
 2 
 3 import cn.bz.bzsso.entity.LoginCode;
 4 import cn.bz.bzsso.entity.LoginStatus;
 5 import cn.bz.bzsso.entity.User;
 6 import com.alibaba.fastjson.JSON;
 7 import com.alibaba.fastjson.serializer.SerializerFeature;
 8 import org.apereo.cas.authentication.AuthenticationHandlerExecutionResult;
 9 import org.apereo.cas.authentication.PreventedException;
10 import org.apereo.cas.authentication.UsernamePasswordCredential;
11 import org.apereo.cas.authentication.handler.support.AbstractUsernamePasswordAuthenticationHandler;
12 import org.apereo.cas.authentication.principal.PrincipalFactory;
13 import org.apereo.cas.services.ServicesManager;
14 import org.springframework.jdbc.core.BeanPropertyRowMapper;
15 import org.springframework.jdbc.core.JdbcTemplate;
16 import org.springframework.jdbc.datasource.DriverManagerDataSource;
17 import java.security.GeneralSecurityException;
18 import java.util.ArrayList;
19 import java.util.HashMap;
20 import java.util.Map;
21 
22 /**
23  * @author tele
24  * @Description
25  * @create 2019-12-04
26  */
27 public class MyAuthenticationHandler extends AbstractUsernamePasswordAuthenticationHandler {
28 
29 
30     public MyAuthenticationHandler(String name, ServicesManager servicesManager, PrincipalFactory principalFactory, Integer order) {
31         super(name, servicesManager, principalFactory, order);
32     }
33 
34     @Override
35     protected AuthenticationHandlerExecutionResult authenticateUsernamePasswordInternal(UsernamePasswordCredential credential, String originalPassword) throws GeneralSecurityException, PreventedException {
36         String username = credential.getUsername();
37         String password = credential.getPassword();
38 
39 
40         DriverManagerDataSource dataSource = new DriverManagerDataSource();
41         dataSource.setDriverClassName("com.mysql.jdbc.Driver");
42         dataSource.setUrl("xx");
43         dataSource.setUsername("xx");
44         dataSource.setPassword("xx");
45 
46         // 創建JDBC模板
47         JdbcTemplate jdbcTemplate = new JdbcTemplate();
48         jdbcTemplate.setDataSource(dataSource);
49 
50         String sql = "select id,username,nickname,password from tb_user where username = ?";
51 
52         User user = (User) jdbcTemplate.queryForObject(sql, new Object[]{username}, new BeanPropertyRowMapper(User.class));
53 
54         LoginStatus loginStatus = new LoginStatus();
55         loginStatus.setId(user.getId());
56         loginStatus.setUsername(user.getUserName());
57         loginStatus.setNickname(user.getNickName());
58 
59         if(user.getPassword().equals(password)) {
60             loginStatus.setCode(LoginCode.LOGIN_SUCCESS);
61             loginStatus.setMessage(LoginCode.MSG_LOGIN_SUCCESS);
62         }else {
63             loginStatus.setCode(LoginCode.ERROR_OF_USER_PWD);
64             loginStatus.setMessage(LoginCode.MSG_ERROR_OF_USER_PWD);
65         }
66 
67         Map<String,Object> resultMap = new HashMap<>(4);
68 
69         resultMap.put("loginStatus", JSON.toJSONString(loginStatus,SerializerFeature.WriteNullStringAsEmpty));
70 
71         return createHandlerResult(credential, this.principalFactory.createPrincipal(credential.getUsername(),resultMap), new ArrayList<>(0));
72 
73     }
74 }
View Code

修改MATA-INF下的spring.factoriesorg.springframework.boot.autoconfigure.EnableAutoConfiguration=xx.MyAuthenticationConfiguration

ok,服務端配置到此結束,你可以自定義返回的信息,狀態碼等

二.客戶端接入

既然接入了cas,那么所有的客戶端都應該關閉登錄與退出接口,扒了下官網,看到一句話大概意思是cas不是一個session管理器,每個應用應當對自己的session負責,cas只會在退出時給接入的應用發通知,然后移除內部維護的tgt對象

,換句話說,每個應用內部應當調用session.invalidate()來銷毀各自的session

1.傳統web項目接入.這種指的是帶有web.xml的web

加入cas-client 版本3.5.1依賴

 1 <!--CAS Client-->
 2 <dependency>
 3     <groupId>org.jasig.cas.client</groupId>
 4     <artifactId>cas-client-core</artifactId>
 5     <version>${cas-client.version}</version>
 6 </dependency>
 7 
 8 <dependency>
 9     <groupId>org.jasig.cas.client</groupId>
10     <artifactId>cas-client-integration-tomcat-common</artifactId>
11     <version>${cas-client.version}</version>
12 </dependency>

在web.xml中加入如下配置,本機環境不建議使用localhost,使用127.0.0.1(5.1版本使用localhost會有退出失效無法通信的問題,瀏覽器存儲cookie時127.0.0.1和localhost是兩個不同的文件夾)

servername指的是客戶端地址

 1 <listener>
 2         <listener-class>org.jasig.cas.client.session.SingleSignOutHttpSessionListener</listener-class>
 3     </listener>
 4 
 5 
 6    <!-- 單點登出過濾器-->
 7     <filter>
 8         <filter-name>CAS Single Sign Out Filter</filter-name>
 9         <filter-class>org.jasig.cas.client.session.SingleSignOutFilter</filter-class>
10         <init-param>
11             <param-name>casServerUrlPrefix</param-name>
12             <param-value>http://127.0.0.1:8090/cas/</param-value>
13         </init-param>
14     </filter>
15     <filter-mapping>
16         <filter-name>CAS Single Sign Out Filter</filter-name>
17         <url-pattern>/*</url-pattern> 18  </filter-mapping> 19     
20    
21 
22  <!--用來跳轉登錄--> 23  <filter> 24  <filter-name>CAS Authentication Filter</filter-name> 25  <filter-class>org.jasig.cas.client.authentication.AuthenticationFilter</filter-class> 26  <init-param> 27  <param-name>casServerLoginUrl</param-name> 28  <param-value>http://127.0.0.1:8090/cas/login</param-value> 29  </init-param> 30  <init-param> 31  <param-name>serverName</param-name> 32  <!--這是客戶端的部署地址,認證時會帶着這個地址,認證成功后會跳轉到這個地址--> 33  <param-value>http://127.0.0.1:8080</param-value> 34  </init-param> 35  </filter> 36  <filter-mapping> 37  <filter-name>CAS Authentication Filter</filter-name> 38  <url-pattern>/*</url-pattern> 39  </filter-mapping> 40     
41 
42  <!--Ticket校驗過濾器--> 43  <filter> 44  <filter-name>CAS Validation Filter</filter-name> 45  <filter-class>org.jasig.cas.client.validation.Cas30ProxyReceivingTicketValidationFilter</filter-class> 46  <init-param> 47  <param-name>casServerUrlPrefix</param-name> 48  <param-value>http://127.0.0.1:8090/cas/</param-value> 49  </init-param> 50  <init-param> 51  <param-name>serverName</param-name> 52  <param-value>http://127.0.0.1:8080</param-value> 53  </init-param> 54  <init-param> 55  <param-name>redirectAfterValidation</param-name> 56  <param-value>true</param-value> 57  </init-param> 58  <init-param> 59  <param-name>useSession</param-name> 60  <param-value>true</param-value> 61  </init-param> 62  <init-param> 63  <param-name>authn_method</param-name> 64  <param-value>mfa-duo</param-value> 65  </init-param> 66  </filter> 67  <filter-mapping> 68  <filter-name>CAS Validation Filter</filter-name> 69  <url-pattern>/*</url-pattern> 70  </filter-mapping> 71     
72  <!-- 該過濾器使得開發者可以通過org.jasig.cas.client.util.AssertionHolder來獲取用戶的登錄名。--> 73  <filter> 74  <filter-name>CASAssertion Thread LocalFilter</filter-name> 75  <filter-class>org.jasig.cas.client.util.AssertionThreadLocalFilter</filter-class> 76  </filter> 77  <filter-mapping> 78  <filter-name>CASAssertion Thread LocalFilter</filter-name> 79  <url-pattern>/*</url-pattern> 80  </filter-mapping> 81     
82 
83  <!-- 該過濾器負責實現HttpServletRequest請求包裝--> 84  <filter> 85  <filter-name>CAS HttpServletRequest Wrapper Filter</filter-name> 86  <filter-class>org.jasig.cas.client.util.HttpServletRequestWrapperFilter</filter-class> 87  </filter> 88     
89  <filter-mapping> 90  <filter-name>CAS HttpServletRequest Wrapper Filter</filter-name> 91  <url-pattern>/*</url-pattern> 92  </filter-mapping>

客戶端獲得cas返回的登錄信息的api,或者使用AssertionHolder.getAssertion().getPrincipal().getAttributes("xx");,嚴謹一點可以先判空,避免NPE

1 @RequestMapping("/login") 2 @ResponseBody 3 public String login() { 4     AttributePrincipal userPrincipal = (AttributePrincipal)request.getUserPrincipal(); 5     return userPrincipal.getAttributes().get("loginStatus").toString(); 6 }

下面講下退出

@RequestMapping(value = "logout") public String logout(HttpSession session) throws InterruptedException { session.invalidate(); return "redirect:" + CASConstant.LOGOUT_URL; }

我在做的時候發現退出請求總是無法觸發,后來發現是項目中有攔截器,於是加了一個excluedUrl,然后在對應的攔截器init的時候filterConfig.getInitParameter("excludedUrl");接下來dofilter時判斷如果含有該路徑重定向即可,但這樣實際相當於重定向兩次

 還有一個問題是上面redirect的地址如果需要spring靜態注入,(當然寫死可以),在applicationContext.xml中引入對應的url.properties,然后需要注入的常量類提供set方法即可,需要注意的是spring的注入是基於對象的.所以該set方法不能有static

 

2.springboot 項目接入cas.springboot內置tomcat,不再需要加入tomcat

pom.xml

 1 <properties>
 2         <java.version>1.8</java.version>
 3         <cas.client.version>3.5.1</cas.client.version>
 4 </properties>
 5 
 6 <dependencies>
 7 
 8 <!--cas的客戶端 -->
 9 <dependency>
10     <groupId>org.jasig.cas.client</groupId>
11     <artifactId>cas-client-core</artifactId>
12     <version>${cas.client.version}</version>
13 </dependency>
14 
15 
16 <dependency>
17     <groupId>org.springframework.boot</groupId>
18     <artifactId>spring-boot-devtools</artifactId>
19     <optional>true</optional>
20 </dependency>
21 
22 <dependency>
23     <groupId>org.springframework.boot</groupId>
24     <artifactId>spring-boot-configuration-processor</artifactId>
25 </dependency>
26 
27 
28 <dependency>
29     <groupId>org.springframework.boot</groupId>
30     <artifactId>spring-boot-starter-web</artifactId>
31 </dependency>
32 
33 <dependency>
34     <groupId>org.springframework.boot</groupId>
35     <artifactId>spring-boot-autoconfigure</artifactId>
36     <version>2.2.0.RELEASE</version>
37 </dependency>
38 
39 <dependency>
40     <groupId>org.mybatis.spring.boot</groupId>
41     <artifactId>mybatis-spring-boot-starter</artifactId>
42     <version>2.1.1</version>
43 </dependency>
44 
45 <dependency>
46     <groupId>mysql</groupId>
47     <artifactId>mysql-connector-java</artifactId>
48     <scope>runtime</scope>
49 </dependency>
50 
51 <dependency>
52     <groupId>com.alibaba</groupId>
53     <artifactId>druid</artifactId>
54     <version>1.1.10</version>
55 </dependency>
56 
57 <dependency>
58     <groupId>org.projectlombok</groupId>
59     <artifactId>lombok</artifactId>
60     <optional>true</optional>
61 </dependency>
62 <dependency>
63     <groupId>org.springframework.boot</groupId>
64     <artifactId>spring-boot-starter-test</artifactId>
65     <scope>test</scope>
66     <exclusions>
67         <exclusion>
68             <groupId>org.junit.vintage</groupId>
69             <artifactId>junit-vintage-engine</artifactId>
70         </exclusion>
71     </exclusions>
72 </dependency>
73 </dependencies>    
View Code

在你的application.properties加入如下配置,依然建議使用127.0.0.1

 1 # 監聽退出的接口,即所有接口都會進行監聽  2 spring.cas.sign-out-filters=/*
 3 # 需要攔截的認證的接口  4 spring.cas.auth-filters=/*  5 spring.cas.validate-filters=/*  6 spring.cas.request-wrapper-filters=/*  7 spring.cas.assertion-filters=/*  8 # 表示忽略攔截的接口,也就是不用進行攔截  9 spring.cas.ignore-filters=/test 10 spring.cas.cas-server-login-url=http://127.0.0.1:8090/cas/login 11 spring.cas.cas-server-url-prefix=http://127.0.0.1:8090/cas/ 12 spring.cas.redirect-after-validation=true 13 spring.cas.use-session=true 14 spring.cas.redirectAfterValidation=true 15 # 客戶端地址 16 spring.cas.server-name=http://127.0.0.1:8081

下面要注入之前在web.xml中配置的各種攔截器

代碼與參考的博客類似,做了些修改,@ConfigurationProperties依賴spring-boot-configuration-processor

  1 @Configuration
  2 public class CasCustomConfig {
  3     @Autowired
  4     SpringCasAutoconfig autoconfig;
  5 
  6     private static boolean casEnabled = true;
  7 
  8     public CasCustomConfig() {
  9     }
 10 
 11     @Bean
 12     public SpringCasAutoconfig getSpringCasAutoconfig() {
 13         return new SpringCasAutoconfig();
 14     }
 15 
 16     @Bean
 17     public ServletListenerRegistrationBean<SingleSignOutHttpSessionListener> singleSignOutHttpSessionListener() {
 18         ServletListenerRegistrationBean<SingleSignOutHttpSessionListener> listener = new ServletListenerRegistrationBean<SingleSignOutHttpSessionListener>();
 19         listener.setEnabled(casEnabled);
 20         listener.setListener(new SingleSignOutHttpSessionListener());
 21         listener.setOrder(1);
 22         return listener;
 23     }
 24 
 25 
 26 
 27     /**
 28      * 該過濾器用於實現單點登出功能,單點退出配置,一定要放在其他filter之前
 29      * @return
 30      */
 31     @Bean
 32     public FilterRegistrationBean singleSignOutFilter() {
 33         FilterRegistrationBean filterRegistration = new FilterRegistrationBean();
 34         filterRegistration.setFilter(new SingleSignOutFilter());
 35         filterRegistration.setEnabled(casEnabled);
 36         if (autoconfig.getSignOutFilters().size() > 0) {
 37             filterRegistration.setUrlPatterns(autoconfig.getSignOutFilters());
 38         } else {
 39             filterRegistration.addUrlPatterns("/*");
 40         }
 41         filterRegistration.addInitParameter("casServerUrlPrefix", autoconfig.getCasServerUrlPrefix());
 42         filterRegistration.addInitParameter("serverName",autoconfig.getServerName());
 43         filterRegistration.setOrder(1);
 44         return filterRegistration;
 45     }
 46 
 47 
 48     /**
 49      * 該過濾器負責用戶的認證工作
 50      *
 51      * @return
 52      */
 53     @Bean
 54     public FilterRegistrationBean authenticationFilter() {
 55         FilterRegistrationBean filterRegistration = new FilterRegistrationBean();
 56         filterRegistration.setFilter(new AuthenticationFilter());
 57         filterRegistration.setEnabled(casEnabled);
 58         if (autoconfig.getAuthFilters().size() > 0) {
 59             filterRegistration.setUrlPatterns(autoconfig.getAuthFilters());
 60         } else {
 61             filterRegistration.addUrlPatterns("/*");
 62         }
 63         if (autoconfig.getIgnoreFilters() != null) {
 64             filterRegistration.addInitParameter("ignorePattern", autoconfig.getIgnoreFilters());
 65         }
 66         filterRegistration.addInitParameter("casServerLoginUrl", autoconfig.getCasServerLoginUrl());
 67         filterRegistration.addInitParameter("serverName", autoconfig.getServerName());
 68      //   filterRegistration.addInitParameter("useSession", autoconfig.isUseSession() ? "true" : "false");
 69      //   filterRegistration.addInitParameter("redirectAfterValidation", autoconfig.isRedirectAfterValidation() ? "true" : "false");
 70         filterRegistration.setOrder(2);
 71         return filterRegistration;
 72     }
 73 
 74     /**
 75      * 該過濾器負責對Ticket的校驗工作,使用CAS 3.0協議
 76      *
 77      * @return
 78      */
 79     @Bean
 80     public FilterRegistrationBean cas30ProxyReceivingTicketValidationFilter() {
 81         FilterRegistrationBean filterRegistration = new FilterRegistrationBean();
 82         filterRegistration.setFilter(new Cas30ProxyReceivingTicketValidationFilter());
 83         filterRegistration.setEnabled(casEnabled);
 84         if (autoconfig.getValidateFilters().size() > 0) {
 85             filterRegistration.setUrlPatterns(autoconfig.getValidateFilters());
 86         } else {
 87             filterRegistration.addUrlPatterns("/*");
 88         }
 89         filterRegistration.addInitParameter("casServerUrlPrefix", autoconfig.getCasServerUrlPrefix());
 90         filterRegistration.addInitParameter("serverName", autoconfig.getServerName());
 91         filterRegistration.addInitParameter("useSession", autoconfig.isUseSession() ? "true" : "false");
 92         filterRegistration.addInitParameter("redirectAfterValidation", autoconfig.isRedirectAfterValidation() ? "true" : "false");
 93         filterRegistration.addInitParameter("authn_method", "mfa-duo");
 94         filterRegistration.setOrder(3);
 95         return filterRegistration;
 96     }
 97 
 98 
 99     /**
100      * 該過濾器使得可以通過org.jasig.cas.client.util.AssertionHolder來獲取用戶的登錄名。
101      * 比如AssertionHolder.getAssertion().getPrincipal().getName()。
102      * 這個類把Assertion信息放在ThreadLocal變量中,這樣應用程序不在web層也能夠獲取到當前登錄信息
103      *
104      * @return
105      */
106     @Bean
107     public FilterRegistrationBean assertionThreadLocalFilter() {
108         FilterRegistrationBean filterRegistration = new FilterRegistrationBean();
109         filterRegistration.setFilter(new AssertionThreadLocalFilter());
110         filterRegistration.setEnabled(true);
111         if (autoconfig.getAssertionFilters().size() > 0) {
112             filterRegistration.setUrlPatterns(autoconfig.getAssertionFilters());
113         } else {
114             filterRegistration.addUrlPatterns("/*");
115         }
116         filterRegistration.setOrder(4);
117         return filterRegistration;
118     }
119 
120 
121     @Bean
122     public FilterRegistrationBean httpServletRequestWrapperFilter() {
123         FilterRegistrationBean filterRegistration = new FilterRegistrationBean();
124         filterRegistration.setFilter(new HttpServletRequestWrapperFilter());
125         filterRegistration.setEnabled(true);
126         if (autoconfig.getRequestWrapperFilters().size() > 0) {
127             filterRegistration.setUrlPatterns(autoconfig.getRequestWrapperFilters());
128         } else {
129             filterRegistration.addUrlPatterns("/*");
130         }
131         filterRegistration.setOrder(5);
132         return filterRegistration;
133     }
134 }
View Code
  1 @ConfigurationProperties(prefix = "spring.cas")
  2 public class SpringCasAutoconfig {
  3 
  4     static final String separator = ",";
  5 
  6     private String validateFilters;
  7     private String signOutFilters;
  8     private String authFilters;
  9     private String assertionFilters;
 10     private String requestWrapperFilters;
 11     private String ignoreFilters; //需要放行的url,多個可以使用|分隔,遵循正則
 12 
 13     private String casServerUrlPrefix;
 14     private String casServerLoginUrl;
 15     private String serverName;
 16     private boolean useSession = true;
 17     private boolean redirectAfterValidation = true;
 18 
 19     public String getIgnoreFilters() {
 20         return ignoreFilters;
 21     }
 22 
 23     public void setIgnoreFilters(String ignoreFilters) {
 24         this.ignoreFilters = ignoreFilters;
 25     }
 26 
 27     public List<String> getValidateFilters() {
 28         return Arrays.asList(validateFilters.split(separator));
 29     }
 30 
 31     public void setValidateFilters(String validateFilters) {
 32         this.validateFilters = validateFilters;
 33     }
 34 
 35     public List<String> getSignOutFilters() {
 36         return Arrays.asList(signOutFilters.split(separator));
 37     }
 38 
 39     public void setSignOutFilters(String signOutFilters) {
 40         this.signOutFilters = signOutFilters;
 41     }
 42 
 43     public List<String> getAuthFilters() {
 44         return Arrays.asList(authFilters.split(separator));
 45     }
 46 
 47     public void setAuthFilters(String authFilters) {
 48         this.authFilters = authFilters;
 49     }
 50 
 51     public List<String> getAssertionFilters() {
 52         return Arrays.asList(assertionFilters.split(separator));
 53     }
 54 
 55     public void setAssertionFilters(String assertionFilters) {
 56         this.assertionFilters = assertionFilters;
 57     }
 58 
 59     public List<String> getRequestWrapperFilters() {
 60         return Arrays.asList(requestWrapperFilters.split(separator));
 61     }
 62 
 63     public void setRequestWrapperFilters(String requestWrapperFilters) {
 64         this.requestWrapperFilters = requestWrapperFilters;
 65     }
 66 
 67     public String getCasServerUrlPrefix() {
 68         return casServerUrlPrefix;
 69     }
 70 
 71     public void setCasServerUrlPrefix(String casServerUrlPrefix) {
 72         this.casServerUrlPrefix = casServerUrlPrefix;
 73     }
 74 
 75     public String getCasServerLoginUrl() {
 76         return casServerLoginUrl;
 77     }
 78 
 79     public void setCasServerLoginUrl(String casServerLoginUrl) {
 80         this.casServerLoginUrl = casServerLoginUrl;
 81     }
 82 
 83     public String getServerName() {
 84         return serverName;
 85     }
 86 
 87     public void setServerName(String serverName) {
 88         this.serverName = serverName;
 89     }
 90 
 91     public boolean isRedirectAfterValidation() {
 92         return redirectAfterValidation;
 93     }
 94 
 95     public void setRedirectAfterValidation(boolean redirectAfterValidation) {
 96         this.redirectAfterValidation = redirectAfterValidation;
 97     }
 98 
 99     public boolean isUseSession() {
100         return useSession;
101     }
102 
103     public void setUseSession(boolean useSession) {
104         this.useSession = useSession;
105     }
106 }
View Code

接下來時登錄和登出,不要直接丟個@RestController就完事了,這個主解會讓redirect失效,當成字符串轉成json返回了,最好的方式是使用@Controller,需要轉json的加上@ResponseBody

 1 @Controller  2 public class LoginController {  3 
 4  @Autowired  5     private UserMapper userMapper;  6 
 7  @Autowired  8     private HttpServletRequest request;  9 
10     @RequestMapping("/login") 11  @ResponseBody 12     public String login() { 13         AttributePrincipal userPrincipal = (AttributePrincipal)request.getUserPrincipal(); 14         return userPrincipal.getAttributes().get("loginStatus").toString(); 15  } 16 
17     @RequestMapping("/logout") 18     public String logout(HttpSession session) { 19  session.removeAttribute(AbstractCasFilter.CONST_CAS_ASSERTION); 20  session.invalidate(); 21         return "redirect:http://127.0.0.1:8090/cas/logout?service=http://127.0.0.1:8081/spring_boot/login/"; 22  } 23 
24     private void println(Object object) { 25  System.out.println(object); 26  } 27 }

三.驗證

 

 

 三.關於源碼

源碼看了下客戶端的攔截器與處理器,大概流程如下,在瀏覽器輸入http://127.0.0.1:8081/spring_boot/login/會被重定向到http://127.0.0.1:8090/cas/login?service=http://127.0.0.1:8081/spring_boot/login/,也就是cas的登錄頁,點擊登錄之后,cas server進行驗證,之后會進入客戶端的攔截器SingleSignOutFilter,攔截器判斷請求類型,如果是tokenrequest(帶token的請求),保存session和st,如果是登出請求,將st,session從map中移除,在destroySession中session.invalidate(),但是其他接入的客戶端並沒有銷毀session,退出時,cas只會給接入的客戶端發通知,當然從哪個客戶端發起的退出該客戶端的session會被destroy,但其他客戶端要在登出接口中session.invalidate(),

 

 

 

 

 
       


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM