CAS单点登录(客户端、服务端)搭建

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/chao821/article/details/84991298

一、单点登录简介

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

CAS 是一个开源的企业级单点登录系统,CAS 包含两个部分:CAS Server 和 CAS Client,它们之间独立部署。CAS 客户端拦截未认证的用户请求,并重定向至 CAS 服务端,由 CAS 服务端对用户身份进行统一认证。

二、服务端搭建

对于搭建 CAS 服务端,CAS官方网站提供了基于 Maven 和 Gradle 的 Overlay 构建方式:具体见

1)Maven: https://github.com/apereo/cas-overlay-template

2)Gradle:https://github.com/apereo/cas-gradle-overlay-template

本文使用的是 CAS Maven WAR Overlay。Overlay 技术可以把多个项目 war 合并成为一个项目,如果项目存在同名文件,那么主项目中的文件将覆盖掉其他项目的同名文件。使用 Overlay 无需对 CAS 源码进行编译,也避免了对 CAS 源码进行侵入性改造。

1、搭建环境

JDK 1.8
Tomcat 8.0+
IntelliJ IDEA 2017.2

2、OverLay构建

打开 Project Structure,可以观察到该工程具有两个 Web Root,但是 src/main/webapp 目录并不存在,需要进行手动创建。

拷贝 overlays 目录下的 application.properties 配置文件至 resources 目录,用于覆盖 CAS WAR 中的同名文件。最终工程目录结构如下:

启动tomcat(可以内置或者外置),本文是使用了外置tomcat。

启动成功后,访问 http://localhost:8080/cas/login 进入登录界面。

注:

Non-secure Connection提示需要配置 SSL,

Static Authentication提示需要对用户配置进行修改,可以修改为 JDBC、REST 等方式。

目前用户配置写死在 application.properties 配置文件中,用户名为 casuser,密码为 Mellon。

3、配置services

客户端接入 CAS 首先需要在服务端进行注册,否则客户端访问将提示“未认证授权的服务”警告。

在 resources 文件夹下创建 services 文件夹进行服务定义,该目录中可包含多个 JSON 文件,其命名必须满足以下规则:

JSON fileName = serviceName + "-" + serviceNumericId + ".json"

创建 services/localhost-10000003.json 文件,表示允许所有以 http://localhost 开头的认证请求:

{
  "@class": "org.apereo.cas.services.RegexRegisteredService",
  "serviceId": "^(http)://localhost.*",
  "name": "localhost",
  "id": 10000003,
  "description": "这是一个本地允许的服务,通过localhost访问都允许通过",
  "evaluationOrder": 1
}

说明:

@class:必须为org.apereo.cas.services.RegisteredService的实现类
serviceId:对服务进行描述的表达式,可用于匹配一个或多个 URL 地址
name: 服务名称
id:全局唯一标志
evaluationOrder:定义多个服务的执行顺序

然后修改application.properties 文件告知 CAS 服务端从本地加载服务定义文件

#开启识别json文件,默认false
cas.serviceRegistry.initFromJson=true
#自动扫描服务配置,默认开启
#cas.serviceRegistry.watcherEnabled=true
#120秒扫描一遍
#cas.serviceRegistry.repeatInterval=120000
#延迟15秒开启
#cas.serviceRegistry.startDelay=15000
#资源加载路径
#cas.serviceRegistry.config.location=classpath:/services

重新启动tomcat,出现如下日志,说明服务注册成功。

2018-03-18 23:36:08,660 INFO [org.apereo.cas.services.AbstractServicesManager] - <Loaded [0] service(s) from [InMemoryServiceRegistry].>
2018-03-18 23:36:08,876 INFO [org.apereo.cas.config.CasServiceRegistryInitializationConfiguration] - <Attempting to initialize the service registry [InMemoryServiceRegistry] from service definition resources found at [class path resource [services]]>
2018-03-18 23:36:08,877 WARN [org.apereo.cas.services.ServiceRegistryInitializer] - <Service registry [InMemoryServiceRegistry] will be auto-initialized from JSON service definitions. This behavior is only useful for testing purposes and MAY NOT be appropriate for production. Consider turning off this behavior via the setting [cas.serviceRegistry.initFromJson=false] and explicitly register definitions in the services registry.>
2018-03-18 23:36:09,283 INFO [org.apereo.cas.services.AbstractServicesManager] - <Loaded [3] service(s) from [InMemoryServiceRegistry].>

三、搭建客户端

CAS官方网站上有CAS-client的案例,见https://apereo.github.io/cas/5.2.x/integration/CAS-Clients.html

亦可参考:https://github.com/cas-projects/cas-sample-java-webapp,本文是参考了后者搭建的。

修改 pom.xml,修改 tomcat7-maven-plugin 设置访问地址为http://localhost:8181/node1

<!--  tomcat7 plugin -->
<plugin>
    <groupId>org.apache.tomcat.maven</groupId>
    <artifactId>tomcat7-maven-plugin</artifactId>
    <version>2.2</version>
    <configuration>
        <port>8181</port>
        <uriEncoding>UTF-8</uriEncoding>
        <server>tomcat7</server>
        <path>/node1</path>
    </configuration>
</plugin>

CAS Client 通过拦截器将未认证的请求重定向到 CAS Server,这里对 cas-sample-java-webapp 的 web.xml 文件进行修改,将服务端、客户端地址替换为实际测试的地址:

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">

<!--
   <context-param>
       <param-name>renew</param-name>
       <param-value>true</param-value>
   </context-param>
-->
    <!--单点登出过滤器-->
    <filter>
        <filter-name>CAS Single Sign Out Filter</filter-name>
        <filter-class>org.jasig.cas.client.session.SingleSignOutFilter</filter-class>
        <init-param>
            <param-name>casServerUrlPrefix</param-name>
            <param-value>http://localhost:8080/cas</param-value>
        </init-param>
    </filter>

    <listener>
        <listener-class>org.jasig.cas.client.session.SingleSignOutHttpSessionListener</listener-class>
    </listener>

    <!--用来跳转登录-->
    <filter>
        <filter-name>CAS Authentication Filter</filter-name>
        <!--<filter-class>org.jasig.cas.client.authentication.Saml11AuthenticationFilter</filter-class>-->
        <filter-class>org.jasig.cas.client.authentication.AuthenticationFilter</filter-class>
        <init-param>
            <param-name>casServerLoginUrl</param-name>
            <param-value>http://localhost:8080/cas/login</param-value>
        </init-param>
        <init-param>
            <param-name>serverName</param-name>
            <!--这是客户端的部署地址,认证时会带着这个地址,认证成功后会跳转到这个地址-->
            <param-value>http://localhost:8181/node1</param-value>
        </init-param>
    </filter>

    <!--Ticket校验过滤器-->
    <filter>
        <filter-name>CAS Validation Filter</filter-name>
        <!--<filter-class>org.jasig.cas.client.validation.Saml11TicketValidationFilter</filter-class>-->
        <filter-class>org.jasig.cas.client.validation.Cas30ProxyReceivingTicketValidationFilter</filter-class>
        <init-param>
            <param-name>casServerUrlPrefix</param-name>
            <param-value>http://localhost:8080/cas</param-value>
        </init-param>
        <init-param>
            <param-name>serverName</param-name>
            <param-value>http://localhost:8181/node1</param-value>
        </init-param>
        <init-param>
            <param-name>redirectAfterValidation</param-name>
            <param-value>true</param-value>
        </init-param>
        <init-param>
            <param-name>useSession</param-name>
            <param-value>true</param-value>
        </init-param>
        <init-param>
            <param-name>authn_method</param-name>
            <param-value>mfa-duo</param-value>
        </init-param>
    </filter>

    <!-- 该过滤器负责实现HttpServletRequest请求的包裹,比如允许开发者通过HttpServletRequest的getRemoteUser()方法获得SSO登录用户的登录名,可选配置-->
    <filter>
        <filter-name>CAS HttpServletRequest Wrapper Filter</filter-name>
        <filter-class>org.jasig.cas.client.util.HttpServletRequestWrapperFilter</filter-class>
    </filter>

    <!-- 该过滤器使得开发者可以通过org.jasig.cas.client.util.AssertionHolder来获取用户的登录名。 比如AssertionHolder.getAssertion().getPrincipal().getName()-->
    <!--<filter>
        <filter-name>CASAssertion Thread LocalFilter</filter-name>
        <filter-class>org.jasig.cas.client.util.AssertionThreadLocalFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>CASAssertion Thread LocalFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>-->

    <filter-mapping>
        <filter-name>CAS Single Sign Out Filter</filter-name>
        <url-pattern>/*</url-pattern>

运行该tomcat,登录http://localhost:8081/node1,网页如下:

输入密码登录成功后的网页如下:

利用相同的方法配置第二个客户端,访问地址为http://localhost:8288/node2,可知在 node1 登录成功的情况下,无需再次输入用户密码即可访问 node2 后台页面。

 

参考文章:

https://apereo.github.io/cas/5.2.x/installation/Maven-Overlay-Installation.html

https://segmentfault.com/a/1190000013844049

https://www.cnblogs.com/flying607/p/7600947.html

https://github.com/apereo/cas/tree/4.0.x

猜你喜欢

转载自blog.csdn.net/chao821/article/details/84991298