CAS Client使用以及执行原理

CAS Client使用以及执行原理

流程介绍

CAS Client是利用Java Web中的Filter进行实现认证功能,客户端对CAS Server的认证流程分为以下步骤:

  • 访问CAS Client服务

  • 由于当前session中未检测到认证信息,会重定向到CAS Server地址进行认证

  • 在CAS Server上进行认证

  • 认证通过之后,CAS Server会重定向携带Ticket回到CAS Client地址

  • 将携带的Ticket在后台进行CAS Server校验

  • CAS Server校验Ticket通过之后会返回当前认证的账号信息

  • 在CAS Client拿到CAS Server返回的认证信息之后,缓存到当前session中

在以上流程中,CAS Client使用了两个Filter实现该主要功能。

使用

Maven依赖引入

<dependency>
  <groupId>org.jasig.cas.client</groupId>
  <artifactId>cas-client-core</artifactId>
  <version>3.6.4</version>
</dependency>

这里使用的Spring Boot 2.x版本(即JDK8版本),所以使用的依赖版本为3.6.4版本,如果是Spring Boot 3.x的话(JDK17),应当使用如下依赖:

<dependency>
    <groupId>org.apereo.cas.client</groupId>
    <artifactId>cas-client-core</artifactId>
    <version>4.0.4</version>
</dependency>

3.6.x以下的版本就不推荐引用了,之前的版本Spring版本为3.x,有兴趣的可以上Github看下官方版本:GitHub - apereo/java-cas-client: Apereo Java CAS Client。

配置

将CAS Client依赖包中的两个Filter过滤器注入到Spring容器即可。

Spring Boot的配置文件,CAS相关

cas:
  server:
    name: http://localhost:9999
    login:
      url: http://localhost:8443/cas/login
    url:
      prefix: http://localhost:8443/cas/
AuthenticationFilter

该过滤器主要是用来检测当前客户端是否通过了CAS Server认证,如果没有通过的话则会调整到CAS Server地址,否则视为通过。

    // 设置cas server的登陆地址
    @Value("${cas.server.login.url}")
    private String casServerLoginUrl;
    // 设置cas server服务前缀,用于拼接cas server服务接口
    @Value("${cas.server.url.prefix}")
    private String casServerUrlPrefix;
    // 设置当前服务名称
    @Value("${cas.server.name}")
    private String serverName;    
​
    @Bean
    public FilterRegistrationBean casClientFilterRegistrationBean() {
        FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
        // 拦截所有接口请求,可根据各自的业务进行配置
        filterRegistrationBean.addUrlPatterns("/*");
        filterRegistrationBean.setFilter(new AuthenticationFilter());
        filterRegistrationBean.addInitParameter("casServerLoginUrl", casServerLoginUrl);
        filterRegistrationBean.addInitParameter("casServerUrlPrefix", casServerUrlPrefix);
        filterRegistrationBean.addInitParameter("serverName", serverName);
        return filterRegistrationBean;
    }
​
TicketValidationFilter

该过滤器是用于获取Ticket以及校验Ticket是否有效,如果检验成功的话,则将校验接口返回的认证用户信息塞到当前session中。

该过滤器有多个版本,这边使用的是如下版本:

    @Bean
    public FilterRegistrationBean ticketValidateFilterRegistrationBean() {
        FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
        // 拦截所有接口请求,可根据各自的业务进行配置
        filterRegistrationBean.addUrlPatterns("/*");
        filterRegistrationBean.setFilter(new Cas20ProxyReceivingTicketValidationFilter());
        filterRegistrationBean.addInitParameter("casServerLoginUrl", casServerLoginUrl);
        filterRegistrationBean.addInitParameter("casServerUrlPrefix", casServerUrlPrefix);
        filterRegistrationBean.addInitParameter("serverName", serverName);
        return filterRegistrationBean;
    }

其中配置与上个Filter参数一致即可;总共有四个是实现类,使用CAS20和CAS30的版本较多:

到这CAS Client的配置已经完成了。上述为主要配置,CAS Client中还有一些其他比较好用的Filter便于开发使用,比如AssertionThreadLocalFilter过滤器,将当前认证的用户信息保存到ThreadLocal当中,在开发过程中可以使用AssertionHolder.getAssertion()直接获取到当前用户信息。

执行原理

CAS Client的所有的配置项可以在ConfigurationKeys类中看到配置Key以及默认值;

Filter所有的参数初始化都是在initInternal方法进行的,在看doFilter方法时,需结合initInternal初始化方法一起,这样会了解的比较透彻。

通过解析CAS Client的两个过滤器来看看执行原理,先看看AuthenticationFilter中doFilter方法,重要步骤在如下一步一步说明:

@Override
    public final void doFilter(final ServletRequest servletRequest, final ServletResponse servletResponse, final FilterChain filterChain) throws IOException, ServletException {
​
        final HttpServletRequest request = (HttpServletRequest) servletRequest;
        final HttpServletResponse response = (HttpServletResponse) servletResponse;
        // 1.判断当前接口请求是否需要被过滤
        if (isRequestUrlExcluded(request)) {
            logger.debug("Request is ignored.");
            filterChain.doFilter(request, response);
            return;
        }
​
        final HttpSession session = request.getSession(false);
        final Assertion assertion = session != null ? (Assertion) session.getAttribute(CONST_CAS_ASSERTION) : null;
        // 2.判断当前session中是否存在认证用户信息
        if (assertion != null) {
            filterChain.doFilter(request, response);
            return;
        }
        // 3.构建当前请求的服务地址,用于跳转cas server页面拼接的service参数
        final String serviceUrl = constructServiceUrl(request, response);
        // 4.获取当前请求是否存在ticket
        final String ticket = retrieveTicketFromRequest(request);
        // 5.判断当前请求是否为配置的网关地址
        final boolean wasGatewayed = this.gateway && this.gatewayStorage.hasGatewayedAlready(request, serviceUrl);
        // 6.如果存在ticket获取是在配置的网关地址中,则直接放开
        if (CommonUtils.isNotBlank(ticket) || wasGatewayed) {
            filterChain.doFilter(request, response);
            return;
        }
​
        final String modifiedServiceUrl;
​
        logger.debug("no ticket and no assertion found");
        if (this.gateway) {
            logger.debug("setting gateway attribute in session");
            modifiedServiceUrl = this.gatewayStorage.storeGatewayInformation(request, serviceUrl);
        } else {
            modifiedServiceUrl = serviceUrl;
        }
​
        logger.debug("Constructed service url: {}", modifiedServiceUrl);
        // 7.需拼接重定向地址页面
        final String urlToRedirectTo = CommonUtils.constructRedirectUrl(this.casServerLoginUrl,
            getProtocol().getServiceParameterName(), modifiedServiceUrl, this.renew, this.gateway, this.method);
​
        logger.debug("redirecting to \"{}\"", urlToRedirectTo);
        this.authenticationRedirectStrategy.redirect(request, response, urlToRedirectTo);
    }

以上可以综合为,先校验配置的不需要校验的接口,判断当前session是否存在认证的信息,不存在则跳转到指定的CAS Server认证页面。

而在Cas20ProxyReceivingTicketValidationFilter过滤器中,则就是解析Ticket以及将返回的认证用户信息塞到当前session中;

@Override
    public final void doFilter(final ServletRequest servletRequest, final ServletResponse servletResponse,
                               final FilterChain filterChain) throws IOException, ServletException {
        // 1.检测是否执行代理请求,一般为false,除非一些特殊的业务场景才需要用到
        if (!preFilter(servletRequest, servletResponse, filterChain)) {
            return;
        }
​
        final HttpServletRequest request = (HttpServletRequest) servletRequest;
        final HttpServletResponse response = (HttpServletResponse) servletResponse;
        // 2.获取Ticket,存在则进入解析,否则直接进入下一个过滤器
        final String ticket = retrieveTicketFromRequest(request);
        
        if (CommonUtils.isNotBlank(ticket)) {
            logger.debug("Attempting to validate ticket: {}", ticket);
​
            try {
                // 3.去请求cas server的接口进行校验Ticket是否正确,正确并返回认证用户信息
                // CAS30是请求/p3/serviceValidate,而CAS20是请求/serviceValidate,两者接口均可以
                final Assertion assertion = this.ticketValidator.validate(ticket,
                        constructServiceUrl(request, response));
​
                logger.debug("Successfully authenticated user: {}", assertion.getPrincipal().getName());
               // 4.校验Ticket通过之后,将认证用户信息塞入请求中
                request.setAttribute(CONST_CAS_ASSERTION, assertion);
               // 默认是会塞入到session中,除非特殊业务场景
                if (this.useSession) {
                    request.getSession().setAttribute(CONST_CAS_ASSERTION, assertion);
                }
                onSuccessfulValidation(request, response, assertion);
                // 5.默认是重定向到请求地址
                if (this.redirectAfterValidation) {
                    logger.debug("Redirecting after successful ticket validation.");
                    response.sendRedirect(constructServiceUrl(request, response));
                    return;
                }
            } catch (final TicketValidationException e) {
                logger.debug(e.getMessage(), e);
               // Ticket校验失败,封装错误信息返回
                onFailedValidation(request, response);
​
                if (this.exceptionOnValidationFailure) {
                    throw new ServletException(e);
                }
​
                response.sendError(HttpServletResponse.SC_FORBIDDEN, e.getMessage());
​
                return;
            }
        }
​
        filterChain.doFilter(request, response);
​
    }
​

该过滤器用于校验Ticket并将返回的认证用户信息塞到session中,下次接口请求就无需校验了。

总结

以上为CAS Client的主要流程;在开发过程中大多数都是使用的Spring Boot作为业务开发框架,如果仅仅自己手动配置的CAS Client的话确实有点不和事宜,在CAS官方也提供了自动配置的依赖,目前找到了两种自动配置的依赖:

Unicon网址提供的CAS Client自动配置,该依赖很久没有更新了。

<dependency>
  <groupId>net.unicon.cas</groupId>
  <artifactId>cas-client-autoconfig-support</artifactId>
  <version>2.3.0-GA</version>
</dependency>

CAS官方提供的,分为Spring Boot 2.x以及3.x版本。

<dependency>
    <groupId>org.jasig.cas.client</groupId>
    <artifactId>cas-client-support-springboot</artifactId>
    <version>3.6.4</version>
</dependency>
<dependency>
    <groupId>org.apereo.cas.client</groupId>
    <artifactId>cas-client-support-springboot</artifactId>
    <version>4.0.4</version>
</dependency>

两者代码几乎是一致的,参数配置的话均可以根据CasClientConfigurationProperties进行配置即可。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/562385.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【深度学习】Dropout、DropPath

一、Dropout 1. 概念 Dropout 在训练阶段会让当前层每个神经元以drop_prob&#xff08; 0 ≤ drop_prob ≤ 1 0\leq\text{drop\_prob}\leq1 0≤drop_prob≤1&#xff09;的概率失活并停止工作&#xff0c;效果如下图。 在测试阶段不会进行Dropout。由于不同批次、不同样本的神…

IMUGNSS的误差状态卡尔曼滤波器(ESKF)---更新过程

IMU&GNSS的误差状态卡尔曼滤波器&#xff08;ESKF&#xff09;---更新过程 ESKF的更新过程 ESKF的更新过程 前面介绍的是ESKF的运动过程&#xff0c;现在考虑更新过程。假设一个抽象的传感器能够对状态变量产生观测&#xff0c;其观测方程为抽象的h,那么可以写为 其中z为…

创新指南|节日期间提高销量的 10 个最佳技巧

许多网上购物者在感恩节前开始假日购物。假期是在线企业销售产品和增加销售额的最佳时机。根据万事达卡的数据&#xff0c;去年在线假日销售额增长了 10.6%&#xff0c;而店内销售额增长了 6.8%。此外&#xff0c;2023年美国消费者平均计划在假日旺季花费约1,530美元。在线企业…

存储过程的查询

Oracle从入门到总裁:​​​​​​https://blog.csdn.net/weixin_67859959/article/details/135209645 在实际使用中&#xff0c;经常会需要查询数据库中已有的存储过程或者某一个存储过程的内容&#xff0c; 下面就介绍-下如何查询存储过程。 这需要使用到数据字典 user_sou…

vscode 配置verilog环境

一、常用的设置 1、语言设置 安装如下插件&#xff0c;然后在config 2、编码格式设置 解决中文注释乱码问题。vivado 默认是这个格式&#xff0c;这里也设置一样。 ctrl shift p 打开设置项 3、插件信任区设 打开一个verilog 文件&#xff0c;显示是纯本文&#xff0c;没…

B树和B+树试题解析

一、单项选择题 01&#xff0e;下图所示是一棵&#xff08;A ). A.4阶B树 B.3阶B树 C.4阶B树 D.无法确定 02.下列关于m阶B树的说法中&#xff0c;错误的是( C ). A.根结点至多有m棵子树 B.所有叶结点都在同一层次上 C.非叶结点至…

算法入门——二分查找

目录 1、二分模板 2、习题 1.704.二分查找 2.35.搜索插入位置 3.744. 寻找比目标字母大的最小字母 4.69. x 的平方根 5.1351. 统计有序矩阵中的负数 6.74. 搜索二维矩阵 7.34. 在排序数组中查找元素的第一个和最后一个位置 8.33. 搜索旋转排序数组 9.153. 寻找旋转排…

【GoWeb框架初探————XORM篇】

1. XORM xorm 是一个简单而强大的Go语言ORM库. 通过它可以使数据库操作非常简便。 1.1 特性 支持 Struct 和数据库表之间的灵活映射&#xff0c;并支持自动同步事务支持同时支持原始SQL语句和ORM操作的混合执行使用连写来简化调用支持使用ID, In, Where, Limit, Join, Havi…

java学习笔记2

3 选择结构 3.1 if选择结构 3.1.1 基本if结构 语法if(条件){// 代码块 }执行流程 当if条件为真,执行代码块,否则不执行代码块。 代码 public class Demo1 {public static void main(String[] args) {// 需求: 张浩的考试成绩>90分,奖励一部Iphone6sScanner sc = new S…

mapreduce中的ReduceTask工作机制(Hadoop)

ReduceTask 是 Hadoop 中的一个重要组件&#xff0c;负责对 MapTask 的输出进行合并、排序和归并&#xff0c;最终生成最终的输出结果。 ReduceTask 的工作机制 1. 分组&#xff08;Shuffle&#xff09;阶段&#xff1a; 在分组阶段&#xff0c;ReduceTask 会从多个 Mapper …

第二届 Oceanbase 开发者大会 实录

第二届 Oceanbase 开发者大会 实录 今天很有幸参加了Oceanbase 开发者大会&#xff0c;我是真的我一开始还不知道什么是Oceanbase &#xff0c;直到我开了会才知道。看来真的需要多参加一些这样活动。 会议议程 我们科普一下什么是Oceanbase OceanBase 是阿里巴巴集团推出…

FastChat启动与部署通义千问大模型

FastChat简介 FastChat is an open platform for training, serving, and evaluating large language model based chatbots. FastChat powers Chatbot Arena, serving over 10 million chat requests for 70 LLMs.Chatbot Arena has collected over 500K human votes from sid…

Llama 3 实测效果炸裂,一秒写数百字(附镜像站)

这几天大火的llama 3刚刚在https://askmanyai.cn上线了&#xff01; 玩了一会儿&#xff0c;这个生成速度是真的亚麻呆住。文案写作和代码生成直接爽到起飞&#xff0c;以往gpt要写一两分钟的千字文&#xff0c;llama 3几秒钟就写完了。而且效果甚至感觉更好&#xff1f; 效果惊…

日期相关的题目

日期相关的题目 1. 计算日期到天数转换2. 日期累加3. 打印日期4. 日期差值 1. 计算日期到天数转换 输出示例: 思路&#xff1a;计算前n-1个月的天数在加上这个月的天数。 #include <iostream> using namespace std;int main() {int year, month, day;cin >> yea…

数据结构练习-数据结构概述

----------------------------------------------------------------------------------------------------------------------------- 1. 在数据结构中&#xff0c;从逻辑上可以把数据结构分成( )。 A. 动态结构和静态结构 B. 紧凑结构和非紧凑结构 C. 线性结…

Spring AI Summary

版权声明 本文原创作者&#xff1a;谷哥的小弟作者博客地址&#xff1a;http://blog.csdn.net/lfdfhl Spring AI is a project that aims to streamline the development of AI applications by providing abstractions and reusable components that can be easily integrate…

梯度消失/梯度爆炸

梯度消失/梯度爆炸&#xff08;Vanishing / Exploding gradients&#xff09; 梯度消失或梯度爆炸&#xff1a;训练神经网络的时候&#xff0c;导数或坡度有时会变得非常大&#xff0c;或者非常小&#xff0c;甚至于以指数方式变小&#xff0c;这加大了训练的难度。 g ( z ) …

Java学习Go(入门)

下载Go 《官网下载golang》 直接点Download&#xff0c;然后根据你自己的操作系统进行下载&#xff0c;我这里以win10为例 安装go 默认安装到C:\Program Files\Go&#xff0c;这里我们可以选择安装到其他盘&#xff0c;也可以选择默认安装。初学者建议直接一路next。 安装完…

Java发送邮件 启用SSL

使用的maven依赖: <dependency><groupId>com.sun.mail</groupId><artifactId>javax.mail</artifactId><version>1.4.7</version> </dependency> 配置文件mail.properties如下: # 邮箱配置 email.username=your-email@exa…

(助力国赛)美赛O奖数学建模可视化!!!含代码2(箱型图、旭日图、直方图、三元图、平行坐标图、密度图、局部放大图)

众所周知&#xff0c;数学建模的过程中&#xff0c;将复杂的数据和模型结果通过可视化图形呈现出来&#xff0c;不仅能够帮助我们更深入地理解问题&#xff0c;还能够有效地向评委展示我们的研究成果。   今天&#xff0c;承接《可视化代码1》&#xff0c;作者将与大家分享《…