前言:今天在网上无意间看到cas单点登录排除请求的问题,发现很多人在讨论如何通过改写AuthenticationFilter类来实现忽略/排除请求URL的功能;突发奇想搜了一下,还真蛮多人都是这么干的,原谅我是个耿直的boy,当时我笑的饭都喷出来了,只需要一个配置的问题,被你们搞的这么麻烦;虽然很想回复他们“你们这帮人用别人的东西都不看源码的吗?”,转念一想,这也要怪作者不给力,文档里压根没有提到这个配置,在这里用少量篇幅讲解如何配置排除不需要拦截的请求URL,后面用大量篇幅介绍我是如何从源码中得知这个配置的,希望对大家有用!做好自己!--eguid始终坚持原创的开源技术文章分享,博客园与本博客保持同步更新。欢迎大家加群一起交流:608423839

1、cas-client单点登录配置

http://blog.csdn.net/eguid_1/article/details/51278622,cas-client完整配置。

没有实现忽略/排除请求URL的cas-client登录验证过滤器

  1. <filter>
  2. <filter-name>casAuthenticationFilter</filter-name>
  3. <filter-class>org.jasig.cas.client.authentication.AuthenticationFilter</filter-class>
  4. <init-param>
  5. <param-name>casServerLoginUrl</param-name>
  6. <param-value>https://cas.eguid.cc/cas-server/</param-value>
  7. </init-param>
  8. <init-param>
  9. <param-name>serverName</param-name>
  10. <param-value>http://client.eguid.cc/</param-value>
  11. </init-param>
  12. </filter>
  13. <filter-mapping>
  14. <filter-name>casAuthenticationFilter</filter-name>
  15. <url-pattern>/*</url-pattern>
  16. </filter-mapping>

这个配置依然是可用的,当然我们要实现忽略/排除请求URL的功能,那么我们该怎么做呢?

2、忽略/排除多个请求URL

  1. <filter>
  2. <filter-name>casAuthenticationFilter</filter-name>
  3. <filter-class>org.jasig.cas.client.authentication.AuthenticationFilter</filter-class>
  4. <init-param>
  5. <param-name>casServerLoginUrl</param-name>
  6. <param-value>http://cas.eguid.cc/cas-server/</param-value>
  7. </init-param>
  8. <init-param>
  9. <param-name>serverName</param-name>
  10. <param-value>http://cilent.eguid.cc/</param-value>
  11. <param-name>ignorePattern</param-name>
  12. <param-value>/js/*|/img/*|/view/*|/css/*</param-value>
  13. </init-param>
  14. </filter><!--做好自己!eguid原创-->
  15. <filter-mapping>
  16. <filter-name>casAuthenticationFilter</filter-name>
  17. <url-pattern>/*</url-pattern>
  18. </filter-mapping>

如上所见,我们排除了四个请求URL(必须是正则表达式形式,下面会讲为什么要这么配置)

3、cas-client默认登录验证过滤器源码解析

看源码,一定要带着目的去看;我们的目的就是找AuthenticationFilter这个cas-client默认登录验证过滤器是否具有排除登录请求URL的功能。

(1)打开cas-client项目源码

打开github上的cas-client项目,可以把项目导到本地或者直接在github上找到org.jasig.cas.client.authentication.AuthenticationFilter.Java这个类。

(2)登录验证过滤器AuthenticationFilter的doFilter

既然是个过滤器,就直接找到该类的doFilter方法

  1. <span style="color:#24292e;">   public final void doFilter(final ServletRequest servletRequest, final ServletResponse servletResponse,
  2. final FilterChain filterChain) throws IOException, ServletException {
  3. <!--做好自己!eguid原创-->
  4. final HttpServletRequest request = (HttpServletRequest) servletRequest;
  5. final HttpServletResponse response = (HttpServletResponse) servletResponse;
  6. if (</span><span style="color:#ff0000;">isRequestUrlExcluded</span><span style="color:#24292e;">(request)) {
  7. logger.debug("Request is ignored.");
  8. filterChain.doFilter(request, response);
  9. return;
  10. }
  11. final HttpSession session = request.getSession(false);
  12. final Assertion assertion = session != null ? (Assertion) session.getAttribute(CONST_CAS_ASSERTION) : null;
  13. if (assertion != null) {
  14. filterChain.doFilter(request, response);
  15. return;
  16. }
  17. final String serviceUrl = constructServiceUrl(request, response);
  18. final String ticket = retrieveTicketFromRequest(request);
  19. final boolean wasGatewayed = this.gateway && this.gatewayStorage.hasGatewayedAlready(request, serviceUrl);
  20. if (CommonUtils.isNotBlank(ticket) || wasGatewayed) {
  21. filterChain.doFilter(request, response);
  22. return;
  23. }
  24. final String modifiedServiceUrl;
  25. logger.debug("no ticket and no assertion found");
  26. if (this.gateway) {
  27. logger.debug("setting gateway attribute in session");
  28. modifiedServiceUrl = this.gatewayStorage.storeGatewayInformation(request, serviceUrl);
  29. } else {
  30. modifiedServiceUrl = serviceUrl;
  31. }
  32. logger.debug("Constructed service url: {}", modifiedServiceUrl);
  33. final String urlToRedirectTo = CommonUtils.constructRedirectUrl(this.casServerLoginUrl,
  34. getProtocol().getServiceParameterName(), modifiedServiceUrl, this.renew, this.gateway);
  35. logger.debug("redirecting to \"{}\"", urlToRedirectTo);
  36. this.authenticationRedirectStrategy.redirect(request, response, urlToRedirectTo);
  37. }</span>

(3)isRequestUrlExcluded方法

第一眼就看到了上面代码红色标识处的isRequestUrlExcluded,这个意思很直白,判断是不是需要忽略/排除的请求URL。

继续接着找到isRequestUrlExcluded这个方法的实现代码:

  1. <span style="color:#24292e;"> private boolean isRequestUrlExcluded(final HttpServletRequest request) {
  2. if (this.ignoreUrlPatternMatcherStrategyClass == null) {
  3. return false;
  4. }
  5. <!--做好自己!eguid原创-->
  6. final StringBuffer urlBuffer = request.getRequestURL();
  7. if (request.getQueryString() != null) {
  8. urlBuffer.append("?").append(request.getQueryString());
  9. }
  10. final String requestUri = urlBuffer.toString();
  11. return this.</span><span style="color:#ff0000;">ignoreUrlPatternMatcherStrategyClass</span><span style="color:#24292e;">.matches(requestUri);
  12. }</span>

看红色标识位置的名字,这里用到了UrlPatternMatcherStrategy这个类,意思很简单直白:‘请求url的匹配策略类’,暂时还不知道这里是正则匹配,往后看:

(4)请求URL的匹配策略类UrlPatternMatcherStrategy

  1. private UrlPatternMatcherStrategy ignoreUrlPatternMatcherStrategyClass = null;

发现该类是在初始化方法中进行初始化的:

  1. <span style="color:#24292e;"> protected void initInternal(final FilterConfig filterConfig) throws ServletException {
  2. if (!isIgnoreInitConfiguration()) {
  3. super.initInternal(filterConfig);
  4. setCasServerLoginUrl(getString(ConfigurationKeys.CAS_SERVER_LOGIN_URL));
  5. setRenew(getBoolean(ConfigurationKeys.RENEW));
  6. setGateway(getBoolean(ConfigurationKeys.GATEWAY));
  7. <!--做好自己!eguid原创-->
  8. final String ignorePattern = getString(ConfigurationKeys.</span><span style="color:#ff0000;">IGNORE_PATTERN</span><span style="color:#24292e;">);
  9. final String ignoreUrlPatternType = getString(ConfigurationKeys.</span><span style="color:#ff0000;">IGNORE_URL_PATTERN_TYPE</span><span style="color:#24292e;">);
  10. if (ignorePattern != null) {
  11. final Class<? extends UrlPatternMatcherStrategy> ignoreUrlMatcherClass = PATTERN_MATCHER_TYPES.get(ignoreUrlPatternType);
  12. if (ignoreUrlMatcherClass != null) {
  13. this.ignoreUrlPatternMatcherStrategyClass = ReflectUtils.newInstance(ignoreUrlMatcherClass.getName());
  14. } else {
  15. try {
  16. logger.trace("Assuming {} is a qualified class name...", ignoreUrlPatternType);
  17. this.ignoreUrlPatternMatcherStrategyClass = ReflectUtils.newInstance(ignoreUrlPatternType);
  18. } catch (final IllegalArgumentException e) {
  19. logger.error("Could not instantiate class [{}]", ignoreUrlPatternType, e);
  20. }
  21. }
  22. if (this.ignoreUrlPatternMatcherStrategyClass != null) {
  23. this.ignoreUrlPatternMatcherStrategyClass.setPattern(ignorePattern);
  24. }
  25. }
  26. final Class<? extends GatewayResolver> gatewayStorageClass = getClass(ConfigurationKeys.GATEWAY_STORAGE_CLASS);
  27. if (gatewayStorageClass != null) {
  28. setGatewayStorage(ReflectUtils.newInstance(gatewayStorageClass));
  29. }
  30. final Class<? extends AuthenticationRedirectStrategy> authenticationRedirectStrategyClass = getClass(ConfigurationKeys.AUTHENTICATION_REDIRECT_STRATEGY_CLASS);
  31. if (authenticationRedirectStrategyClass != null) {
  32. this.authenticationRedirectStrategy = ReflectUtils.newInstance(authenticationRedirectStrategyClass);
  33. }
  34. }
  35. }</span>

虽然使用了反射,但是依然不影响我们找到根本所在,找到ConfigurationKeys这个类里面的变量究竟是什么:

  1. <span style="color:#24292e;">   ConfigurationKey<String> IGNORE_PATTERN = new ConfigurationKey<String>("</span><span style="color:#ff0000;">ignorePattern</span><span style="color:#24292e;">", null);
  2. ConfigurationKey<String> IGNORE_URL_PATTERN_TYPE = new ConfigurationKey<String>("</span><span style="color:#ff0000;">ignoreUrlPatternType</span><span style="color:#24292e;">", "REGEX");</span>

字面上理解这两个常量定义了忽略模式以及忽略模式类型是‘正则’,当然我们还是不确定是不是正则,那么继续往下找

  1. final Class<? extends UrlPatternMatcherStrategy> ignoreUrlMatcherClass = PATTERN_MATCHER_TYPES.get(ignoreUrlPatternType);

我们已经通过ConfigurationKeys类知道ignoreUrlPatternType是个‘REGEX’字符串,那么

  1. PATTERN_MATCHER_TYPES.put("REGEX", RegexUrlPatternMatcherStrategy.class);

那么按照REGEX对应的值找到RegexUrlPatternMatcherStrategy这个类:

(5)确定RegexUrlPatternMatcherStrategy类用于处理正则验证匹配

  1. public final class RegexUrlPatternMatcherStrategy implements UrlPatternMatcherStrategy {
  2. <!--做好自己!eguid原创-->
  3. private Pattern pattern;
  4. public RegexUrlPatternMatcherStrategy() {}
  5. public RegexUrlPatternMatcherStrategy(final String pattern) {
  6. this.setPattern(pattern);
  7. }
  8. public boolean matches(final String url) {
  9. return this.pattern.matcher(url).find();
  10. }
  11. public void setPattern(final String pattern) {
  12. this.pattern = Pattern.compile(pattern);
  13. }
  14. }

该类中用到了Pattern来编译和匹配正则表达式

到这里我们终于可以确定可以用ignorePattern来忽略/排除我们不需要拦截的请求URL,当然必须满足正则表达式。

关于cas-client单点登录客户端拦截请求和忽略/排除不需要拦截的请求URL的问题(不需要修改任何代码,只需要一个配置)的更多相关文章

  1. cas-client单点登录客户端拦截请求和忽略/排除不需要拦截的请求URL的问题

    http://blog.csdn.net/eguid_1/article/details/73611781

  2. [精华][推荐]CAS SSO 单点登录框架学习 环境搭建

    1.了解单点登录  SSO 主要特点是: SSO 应用之间使用 Web 协议(如 HTTPS) ,并且只有一个登录入口. SSO 的体系中有下面三种角色: 1) User(多个) 2) Web 应用( ...

  3. CAS SSO单点登录框架学习

    1.了解单点登录  SSO 主要特点是: SSO 应用之间使用 Web 协议(如 HTTPS) ,并且只有一个登录入口. SSO 的体系中有下面三种角色: 1) User(多个) 2) Web 应用( ...

  4. CAS SSO单点登录框架介绍

    1.了解单点登录  SSO 主要特点是: SSO 应用之间使用 Web 协议(如 HTTPS) ,并且只有一个登录入口. SSO 的体系中有下面三种角色: 1) User(多个) 2) Web 应用( ...

  5. 基于CAS的单点登录实战(2)-- 搭建cas的php客户端

    在这之前已经搭好了CAS服务端 基于CAS的单点登录实战(1)-- 搭建cas服务器 PHP-Client php-Client是官方支持的,去官网下个最新版就好了.phpCAS 接入很简单,解压放到 ...

  6. [精华][推荐]CAS SSO单点登录服务端客户端实例

    1.修改server.xml文件,如下: 注意: 这里使用的是https的认证方式,需要将这个配置放开,并做如下修改: <Connector port="8443" prot ...

  7. Cas(07)——建立使用Cas进行单点登录的应用

    建立使用Cas进行单点登录的应用 目录 1.1加入cas-client-core-xxx.jar到classpath 1.2配置Filter 1.2.1AuthenticationFilter 1.2 ...

  8. CAS实现单点登录SSO执行原理及部署

    一.不落俗套的开始 1.背景介绍 单点登录:Single Sign On,简称SSO,SSO使得在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统. CAS框架:CAS(Centra ...

  9. CAS实现单点登录

    1.简介 SSO单点登录 在多个相互信任的系统中,用户只需要登录一次就可以访问其他受信任的系统. 新浪微博与新浪博客是相互信任的应用系统. *当用户首次访问新浪微博时,新浪微博识别到用户未登录,将请求 ...

随机推荐

  1. MongoDB副本集的常用操作及原理

    本文是对MongoDB副本集常用操作的一个汇总,同时也穿插着介绍了操作背后的原理及注意点. 结合之前的文章:MongoDB副本集的搭建,大家可以在较短的时间内熟悉MongoDB的搭建和管理. 下面的操 ...

  2. GitHub的实践

    GitHub的实践 2017-05-08,晴,来小米已经一周的时间了,感谢领导能给我一周的时间来熟悉 ubuntu.spring boot.maven.docker.github .大家会问,这些不都 ...

  3. SQL SERVER大话存储结构(2)_非聚集索引如何查找到行记录

              如果转载,请注明博文来源: www.cnblogs.com/xinysu/   ,版权归 博客园 苏家小萝卜 所有.望各位支持!      1 行记录如何存储     这里引入两个 ...

  4. WinRAR5.01注册码附注册机

    把下面的注册码复制到"记事本"中,另存为"rarreg.key"文件,放到WinRAR安装目录即完成注册.RAR registration datakjcy8U ...

  5. Java读写Excel之POI超入门

    转自:http://rensanning.iteye.com/blog/1538591 Apache POI 是用Java编写的免费开源的跨平台的 Java API,Apache POI提供API给J ...

  6. THREE笛卡尔右手坐标系详解

    1,正常的笛卡尔右手坐标系,以屏幕右方为+X轴,屏幕上方为+Y轴,垂直屏幕向外为+Z轴,如下图,xy轴组成的平面为屏幕面 但由于THREE里的相机并不总是从屏幕正前方视角,还可以设置坐标系任意一个轴为 ...

  7. Javascript创建类和对象

    现总结一下Javascript创建类和对象的几种方法: 1.原始的创建方法: <script type="text/javascript"> var person = ...

  8. Java静态代理与动态代理模式的实现

    前言:    在现实生活中,考虑以下的场景:小王打算要去租房,他相中了一个房子,准备去找房东洽谈相关事宜.但是房东他很忙,平时上班没时间,总找不到时间去找他,他也没办法.后来,房东想了一个办法,他找到 ...

  9. hdu4081

    hdu4081 题意 给出n个点坐标,每个点有权值,要求得到一颗生成树,且其中有一条道路修建不需要花费,但是要求这条道路所连接的两点的权值之和除以剩下所有道路的距离花费最大. 分析 首先求最小生成树, ...

  10. 使用windows 命令行执行Git clone时出现Host key error

    由于是在java中执行cmd命令调用git clone,导致git读取不到用户的ssh key,需要设置环境变量Home为正确的用户路径: cmd /c set HOME=C:/Users/你的用户名 ...