CAS 6.1.x 单点登录、登出

CAS(Central Authentication Service):关于 SSO 的一套解决方案,即统一身份认证服务或中央身份服务器,由服务端和客户端组成,容易进行企业应用的集成。

CAS 原理
  • 架构

架构

  • CAS 最基本的协议过程

CAS实现过程

  • 访问服务: SSO 客户端发送请求访问应用系统提供的服务资源。
  • 定向认证: SSO 客户端会重定向用户请求到 SSO 服务器。
  • 用户认证:用户身份认证。
  • 发放票据: SSO 服务器会产生一个随机的 Service Ticket 。
  • 验证票据: SSO 服务器验证票据 Service Ticket 的合法性,验证通过后,允许客户端访问服务。
  • 传输用户信息: SSO 服务器验证票据通过后,传输用户认证结果信息给客户端。
CAS Server 部署
  • 构建 war 包

    • cas-overlay-template 项目下载地址:https://github.com/apereo/cas-overlay-template ,选择需要的版本下载到本地,新版本需要自己构建 war 包。

      git clone -b 分支名 https://github.com/apereo/cas-overlay-template.git
      
    • 项目初次构建完成后,按照 README 中提示执行命令,在 build/libs/ 目录下可找到 cas.war。

    • 如果想根据需要自己配置,可执行 ./gradlew[.bat] explodeWar 命令将 war 包解压,将解压得到的 cas-resources 文件夹复制到 src/main/目录下,即可对相关的文件进行修改,主要配置文件 src/main/resources/application.properties,修改完之后需要再次 build ,使得最新的配置生效。

  • cas 需要使用 https 访问,故需要生成证书和密钥,此处使用 Java 自带的数据证书管理工具 keytool

    • 生成密钥(别名、密钥、证书名最好保持一致)

      keytool -genkey -alias castest -keyalg RSA -keystore 对应路径/keystore/castest
      
    • 导出证书(此处将证书颁发给 castest)

      keytool -export -trustcacerts -alias castest -file 对应路径/keystore/castest.cer -keystore 对应路径//keystore/castest
      
    • 将证书导入到 JDK 证书库(默认密码:changeit)

      keytool -import -trustcacerts -alias castest -file 对应路径/keystore/castest.cer -keystore "jdk路径/jdk-11/lib/security/cacerts"
      
    • 配置 tomcat https 访问,在 tomcat 安装目录下找到 conf/server.xml,加入 https 配置,将生成的密钥及生成密钥时设置的密码配置到文件中。

      <Connector port="8443" protocol="org.apache.coyote.http11.Http11AprProtocol"
                     maxThreads="150" SSLEnabled="true" scheme="https" secure="true" 
      			   clientAuth="false" sslProtocol="TLS" 
      			   keystoreFile="D:\CAS\keystore\castest" 
      			   keystorePass="123456">
      </Connector>
      
    • C:\Windows\System32\drivers\etc 目录下找到 hosts 文件,添加配置将证书颁发的域名指向 127.0.0.1

      127.0.0.1 castest
      
  • 将构建好的 war 包放到 Tomact 的 webapps 目录下,启动 tomcat 会自动解压部署该 war 包。

    • 若正常启动,访问 https://castest:8443/cas/login 即可访问到 CAS 默认的登录页面。
    • 采用默认的静态认证方式,用户名casuser,密码Mellon
  • 我们实际开发一般不会采用静态认证方式,可以根据需要配置数据库认证,这里使用 MySQL 数据库。

    • build.gradle 中引入相关依赖,注意自己的 MySQL 版本

      添加依赖

      dependencies {
          // Other CAS dependencies/modules may be listed here...
          compile "org.apereo.cas:cas-server-webapp-init:${casServerVersion}"
          compile "org.apereo.cas:cas-server-support-json-service-registry:${casServerVersion}"
      //    添加数据库认证相关的包
          compile "org.apereo.cas:cas-server-support-jdbc:${casServerVersion}"
          compile "org.apereo.cas:cas-server-support-jdbc-drivers:${casServerVersion}"
          compile "mysql:mysql-connector-java:5.7.9"
      //    compile "org.jasig.cas:${casServerVersion}"
      }
      
    • src/main/resources/application.properties 中将之前的静态认证配置注释掉,添加数据库认证配置。

      • CAS 默认的密码加密方式为 MD5,如果数据库中密码没有加密,则需要手动生成对应的 MD5 值,才能验证通过,不过我使用在线工具生成 MD5 加密密码校验一直无法通过,查阅资料大致原因应该是 CAS 使用的 MD5 算法与我们使用的不同,可以自己实现一下 PasswordEncoder ,配置使用自己的实现去校验密码(这里未实现)。
      • 不配置则使用明文方式,此处则使用明文方式。
      ##
      # CAS Authentication Credentials
      #
      #cas.authn.accept.users=casuser::Mellon
      #cas.authn.accept.name=Static Credentials
      cas.jdbc.showSql=true
      cas.authn.jdbc.query[0].dialect=org.hibernate.dialect.MySQL5Dialect
      cas.authn.jdbc.query[0].url=jdbc:mysql://localhost:3306/hibernate_demo01?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
      cas.authn.jdbc.query[0].user=root
      cas.authn.jdbc.query[0].password=root
      cas.authn.jdbc.query[0].sql=select user_passwd from d_user where user_name=?
      # 数据库中的密码字段名称
      cas.authn.jdbc.query[0].fieldPassword=user_passwd
      # com.mysql.cj.jdbc.Driver: mysql-connector-java 6 比 5 版本多了关于时区的设置
      cas.authn.jdbc.query[0].driverClass=com.mysql.cj.jdbc.Driver
      #cas.authn.jdbc.query[0].passwordEncoder.type=DEFAULT
      #cas.authn.jdbc.query[0].passwordEncoder.characterEncoding=UTF-8
      #cas.authn.jdbc.query[0].passwordEncoder.encodingAlgorithm=MD5
      

    到这里我们启动 tomcat,就可以通过数据库中的用户名、密码登录 CAS Server 了。

  • src/main/resources/services/HTTPSandIMAPS-10000001.json 中添加 http 访问配置

添加http

{
  "@class": "org.apereo.cas.services.RegexRegisteredService",
  "serviceId": "^(http|https|imaps)://.*",
  "name": "HTTP、HTTPS and IMAPS",
  "id": 10000001,
  "description": "This service definition authorizes all application urls that support HTTP、HTTPS and IMAPS protocols.",
  "evaluationOrder": 10000
}
  • src/main/resources/application.properties 中添加 http 访问配置

    # 设置 http 访问
    # 服务注册的 json 配置文件路径
    cas.serviceRegistry.json.location=classpath:/services
    # 设置安全为 false
    cas.tgc.secure=false
    # *******tomcat 自动部署 cas.war时无法正确解析该设置*******
    # 开启识别 json 文件,默认为 false
    #cas.serviceRegistry.initFromJson=true
    
CAS Client 部署
  • 此处客户端基于 SpringMVC 搭建,可以在一个项目下构建两个 Module,便于后续测试单点登录、登出,分别将两个模块部署到tomcat上,设置不同的端口如 http://localhost:18081/http://localhost:18082/ ,同时启动可正常访问即可。

  • 在 pom.xml 中添加 cas client 依赖

    <!-- CAS客户端相关依赖-->
    <dependency>
        <groupId>org.jasig.cas.client</groupId>
        <artifactId>cas-client-core</artifactId>
        <version>3.6.2</version>
    </dependency>
    
  • src/main/webapp/WEB-INF/web.xml 中配置相关过滤器

    • 注意此处 CAS 服务端和客户端的访问地址不能使用 localhost,否则会报错,我理解是从 CAS Server 服务器可能
    <!-- 负责用户认证 ,必须启用 -->
    <filter>
        <filter-name>CASFilter</filter-name>
        <filter-class>org.jasig.cas.client.authentication.AuthenticationFilter</filter-class>
        <!-- cas server 的服务端 IP -->
        <init-param>
            <param-name>casServerLoginUrl</param-name>
            <param-value>https://castest:8443/cas/login</param-value>
        </init-param>
        <!-- cas client 的客户端 IP -->
        <init-param>
            <param-name>serverName</param-name>
            <param-value>http://castest:18081</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>CASFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    
    <!-- 负责 Ticket 的校验,必须启用 -->
    <filter>
        <filter-name>CAS Validation Filter</filter-name>
        <filter-class>org.jasig.cas.client.validation.Cas20ProxyReceivingTicketValidationFilter</filter-class>
        <!-- cas server 的服务端 IP -->
        <init-param>
            <param-name>casServerUrlPrefix</param-name>
            <param-value>https://castest:8443/cas</param-value>
        </init-param>
        <!-- cas client 的客户端 IP -->
        <init-param>
            <param-name>serverName</param-name>
            <param-value>http://castest:18081</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>CAS Validation Filter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    
    <!-- 该过滤器负责实现HttpServletRequest请求的包裹,如允许获取SSO登录的用户名 -->
    <filter>
        <filter-name>CAS HttpServletRequest Wrapper Filter</filter-name>
        <filter-class>org.jasig.cas.client.util.HttpServletRequestWrapperFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>CAS HttpServletRequest Wrapper Filter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    
    <filter>
        <filter-name>CAS Assertion Thread Local Filter</filter-name>
        <filter-class>org.jasig.cas.client.util.AssertionThreadLocalFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>CAS Assertion Thread Local Filter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    
  • 配置好之后,重新启动 client,访问 http://localhost:18081/ 此时会直接重定向到 CAS 的登录认证页面,输入正确的用户名密码才能访问到启动页面,此时再访问http://localhost:18082/ 则会直接访问到启动页面,无需再进行登录,这就是单点登录。

  • 单点登出

    • src/main/webapp/WEB-INF/web.xml 中配置相关过滤器及监听器
    <!-- 用于实现单点登出的监听器和过滤器 -->
    <listener>
        <listener-class>org.jasig.cas.client.session.SingleSignOutHttpSessionListener</listener-class>
    </listener>
    <filter>
        <filter-name>CAS Single Sign Out Filter</filter-name>
        <filter-class>org.jasig.cas.client.session.SingleSignOutFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>CAS Single Sign Out Filter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    
    • 编写登出方法,重定向到 CAS Server 的 logout 方法,可以在重定向 url 后面加一个后缀 service,表示登出之后回到 service 指定的页面。
    @RequestMapping(value = "logout", method = {RequestMethod.GET, RequestMethod.POST})
    public String logout (HttpSession session) {
        session.invalidate();
        return "redirect:https://castest:8443/cas/logout?service=https://castest:8443/cas/login";
    }
    
    • 在 index.jsp 可添加登出按钮,获取当前登录用户等信息。
    <%@page contentType="text/html; charset=utf-8" language="java" %>>
    <html>
    <body>
    <div style="text-align: right">
        <a href="/logout">登出</a>
    </div>
    <h2>Hello World!</h2>
    
    <%=request.getRemoteUser()%>
    </body>
    </html>
    
    • 重新启动 client,访问 http://localhost:18081/ ,输入正确的用户名密码访问到启动页面,再访问http://localhost:18082/ 之后点击登出,再回到 http://localhost:18081/ 的启动页面刷新界面,此时页面会变为 login 页面,即在 18082 登出那么 18081 也会登出,即单点登出。

到这里 CAS Client 就部署完成了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值