CAS源码追踪系列二:AuthenticationFilter对于请求的处理

上一篇我们说了在web项目中了和spring整合之后,如何进行对应Filter的初始化,如果你还没看过,请点击 《CAS源码追踪系列一:Filter的初始化》。 本篇我们来看看在初始化完成以后,cas-client是如何处理请求的。

源码地址:https://github.com/apereo/java-cas-client

如何你还不太清楚sso的原理,你可以看看这篇文章《单点登录原理与简单实现》。

当访问系统受保护的资源时,cas的过滤器AuthenticationFilter会对它进行拦截,发现用户没有登录(系统中没有对应的session信息),就会跳转到统一登录页面。否则调用FilterChain中下一个Filter。

来看AuthenticationFilter的

doFilter(final ServletRequest servletRequest, final ServletResponse servletResponse,final FilterChain filterChain)

if (isRequestUrlExcluded(request)) {

logger.debug("Request is ignored.");

filterChain.doFilter(request, response);

return;

}

判断请求是否是不需要被拦截,是,则进行直接调用FilterChain中下一个Filter,否则向下执行

来看看isRequestUrlExcluded方法

private boolean isRequestUrlExcluded(final HttpServletRequest request) {

/

是否有忽略url匹配类,

在AuthenticationFilter的initInternal(final FilterConfig filterConfig)进行初始化

*/

if (this.ignoreUrlPatternMatcherStrategyClass == null) {

return false;

}

    final StringBuffer urlBuffer = request.getRequestURL();
    if (request.getQueryString() != null) {
        urlBuffer.append("?").append(request.getQueryString());//拼装url
    }
    final String requestUri = urlBuffer.toString();
    /*
    *匹配url是不是不用被拦截,拦截规则需要用户在配置文件配置,
    *在AuthenticationFilter的initInternal(final FilterConfig *filterConfig)加载到ignoreUrlPatternMatcherStrategyClass
    */
    return this.ignoreUrlPatternMatcherStrategyClass.matches(requestUri);
}

final HttpSession session = request.getSession(false);//获取用户session,注意到参数是false,表示session没有的话不新建一个session

final Assertion assertion = session != null ? (Assertion) session.getAttribute(CONST_CAS_ASSERTION) : null;//如果有session,则从CONST_CAS_ASSERTION属性值获取断言

如果session不存在或者session中CONST_CAS_ASSERTION为空则代表用户还未登录,则需要继续向下执行,否则执行下一个Filter。

final String serviceUrl = constructServiceUrl(request, response);//解析请求地址

该方法最终调用

CommonUtils.constructServiceUrl(final HttpServletRequest request, final HttpServletResponse response,

final String service, final String serverNames, final String serviceParameterName,

final String artifactParameterName, final boolean encode);

@param service: 服务地址或者说是你要请求的地址,该方法更乐意你提供这个参数(可在配置文件配置)

@param serverName:服务名,如http://localhost:8080

if (CommonUtils.isNotBlank(service)) {

return encode ? response.encodeURL(service) : service;

}

代码一开始先对server参数进行校验,如何不为空,直接返回。这也就是为什么为什么期望你配置这个参数,逻辑简单啊。 如果不为空,则需要对请求的url进行解析。

final String serverName = findMatchingServerName(request, serverNames);

final URIBuilder originalRequestUrl = new URIBuilder(request.getRequestURL().toString(), encode);

originalRequestUrl.setParameters(request.getQueryString());

    final URIBuilder builder;
    if (!serverName.startsWith("https://") && !serverName.startsWith("http://")) {
        String scheme = request.isSecure() ? "https://" : "http://";
        builder = new URIBuilder(scheme + serverName, encode);
    } else {
        builder = new URIBuilder(serverName, encode);
    }

    if (builder.getPort() == -1 && !requestIsOnStandardPort(request)) {
        builder.setPort(request.getServerPort());
    }

    builder.setEncodedPath(builder.getEncodedPath() + request.getRequestURI());

根据url获取请求参数(request.getQueryString())时,会判断有没有携带ticket参数且必须在第一个位置(location==0),如果是就直接返回之前拼装的url,否则继续拼装参数 。

final List

final String ticket = retrieveTicketFromRequest(request);//获取请求中的ticket

然后判断如果有ticket而且设置了网关,就直接调用下一个Filter,否则继续向下执行。

final String urlToRedirectTo = CommonUtils.constructRedirectUrl(this.casServerLoginUrl,

getProtocol().getServiceParameterName(), modifiedServiceUrl, this.renew, this.gateway);

根据已有的数据构造一个重定向url,也就是对于请求认证失败的时候跳转的地址,类似于https://localhost:8443/cas/login?service=https%3A%2F%2Flocalhost%3A8443%2Ftest%3Ftest%3D12456%26sss%3D111。“?”前面部分为认证中心登录页面,后面则为登录成功之后要跳转的地址。

最后一步就是执行重定向。

总结

这一片我们简单分析了cas-client如何处理请求,对于认证成功的继续执行下一个Filter,失败的则跳转到登录页面。下一篇我们会讲cas-server端是如何处理登录的。

平时的学习过程记录一下,没有那么高深,希望能帮到大家,与君共同进步。我是敲代码的小鲁班,喜欢的话给个推荐,点赞,关注吧。

原文地址:https://www.cnblogs.com/xuxiaojian/p/9865175.html

时间: 2024-08-28 22:52:57

CAS源码追踪系列二:AuthenticationFilter对于请求的处理的相关文章

CAS源码追踪系列三:cas-server端对请求的处理

目录 InitialFlowSetupAction ServiceAuthorizationCheck AuthenticationViaFormAction SendTicketGrantingTicketAction GenerateServiceTicketAction 第一次访问接入cas的另一个应用系统 总结 系列: CAS源码追踪系列一:Filter的初始化 CAS源码追踪系列二:AuthenticationFilter对于请求的处理 上一篇,我们了解了AuthenticationF

CAS源码追踪系列一:Filter的初始化

目录 代码跟踪 Spring-web:DelegatingFilterProxy CAS:AuthenticationFilter 总结 最近研究了一下SSO(Single Sign On:单点登录)原理. 于是想借助CAS(基于SSO原理的实现框架)加深一下理解同时参考一下具体代码实现,因此有了此系列文章. 先从CAS-CLIENT说起. 假设你已经掌握了如何在你的web项目中引入CAS.我们以AuthenticationFilter为例,说一说它是如何从初始化的. 代码跟踪 Spring-w

Cordova Android源码分析系列二(CordovaWebView相关类分析)

本篇文章是Cordova Android源码分析系列文章的第二篇,主要分析CordovaWebView和CordovaWebViewClient类,通过分析代码可以知道Web网页加载的过程,错误出来,多线程处理等. CordovaWebView类分析 CordovaWebView类继承了Android WebView类,这是一个很自然的实现,共1000多行代码.包含了PluginManager pluginManager,BroadcastReceiver receiver,CordovaInt

swoft| 源码解读系列二: 启动阶段, swoft 都干了些啥?

date: 2018-8-01 14:22:17title: swoft| 源码解读系列二: 启动阶段, swoft 都干了些啥?description: 阅读 sowft 框架源码, 了解 sowft 启动阶段的那些事儿 小伙伴刚接触 swoft 的时候会感觉 压力有点大, 更直观的说法是 难. 开发组是不赞成 难 这个说法的, swoft 的代码都是 php 实现的, 而 php 又是 世界上最好的语言, swoft 的代码阅读起来是很轻松的. 之后开发组会用 系列源码 解读文章, 深入解析

Tomcat总体架构(Tomcat源码解析系列二)

Tomcat即是一个HTTP服务器,也是一个servlet容器,主要目的就是包装servlet,并对请求响应相应的servlet,纯servlet的web应用似乎很好理解Tomcat是如何装载servlet的,但,当使用一些MVC框架时,如spring MVC.strusts2,可能就找不出servlet在哪里?其实spring MVC框架就是一整个servlet,在web.xml中配置如下: <!-- Spring MVC servlet --> <servlet> <se

Redis java客户端 jedis 源码分析系列二:单实例 jedis

在使用Jedis的过程中最简单的用法就是单实例单连接的jedis,如下代码所示: public void testJedis(){ Jedis jedis = new Jedis("127.0.0.1"); jedis.set("key", "value"); jedis.get("key"); jedis.close(); } 让我们深入到内部去看一看其结构,如下图所示: 此处请先忽略 JedisPool 类和 Pool&l

Spring源码由浅入深系列二 类结构

BeanFactory 上一章中,我们提过Spring的依赖注入容器是BeanFactory.BeanFactory是一个基础接口,它有一个默认实现类:DefaultListableBeanFactory.我们可以由它为出发点看看Spring的类层次结构.如下图所示:        上图中,有一个值得我们学习的设计方法.DefaultListableBeanFactory类实现了ConfigurableListableBeanFactory接口.然后ConfigurableListableBea

Spring源码由浅入深系列五 CreateBean

blog宗旨:用图说话. 附:目录 Spring源码由浅入深系列五 GetBean Spring源码由浅入深系列四 创建BeanFactory Spring源码由浅入深系列三 refresh Spring源码由浅入深系列二 类结构 Spring源码由浅入深系列一 简介 

Python解析器源码加密系列之(二):一次使用标准c的FILE*访问内存块的尝试

摘要:由于近期打算修改Python解释器以实现pyc文件的加密/解密,出于保密的要求,解密之后的数据只能放在内存中,不能写入到文件中.但是后续的解析pyc文件的代码又只能接受FILE*作为入参,所以就提出了一种把通过FILE*来访问内存的需求,下文是针对这个需求的几个方面的尝试及其结论. 以下尝试的前提是:Win7 + VS2010. 在vc中,FILE其实就是_iobuf,定义如下: struct _iobuf { char *_ptr; //文件输入的下一个位置 int _cnt; //当前