关于cas-client单点登录客户端拦截请求和忽略/排除不需要拦截的请求URL的问题(不需要修改任何代码,只需要一个配置)
前言:今天在网上无意间看到cas单点登录排除请求的问题,发现很多人在讨论如何通过改写AuthenticationFilter类来实现忽略/排除请求URL的功能;突发奇想搜了一下,还真蛮多人都是这么干的,原谅我是个耿直的boy,当时我笑的饭都喷出来了,只需要一个配置的问题,被你们搞的这么麻烦;虽然很想回复他们“你们这帮人用别人的东西都不看源码的吗?”,转念一想,这也要怪作者不给力,文档里压根没有提到这个配置,在这里用少量篇幅讲解如何配置排除不需要拦截的请求URL,后面用大量篇幅介绍我是如何从源码中得知这个配置的,希望对大家有用!做好自己!--eguid始终坚持原创的开源技术文章分享,博客园与本博客保持同步更新。欢迎大家加群一起交流:608423839
1、cas-client单点登录配置
http://blog.csdn.net/eguid_1/article/details/51278622,cas-client完整配置。
没有实现忽略/排除请求URL的cas-client登录验证过滤器
- <filter>
- <filter-name>casAuthenticationFilter</filter-name>
- <filter-class>org.jasig.cas.client.authentication.AuthenticationFilter</filter-class>
- <init-param>
- <param-name>casServerLoginUrl</param-name>
- <param-value>https://cas.eguid.cc/cas-server/</param-value>
- </init-param>
- <init-param>
- <param-name>serverName</param-name>
- <param-value>http://client.eguid.cc/</param-value>
- </init-param>
- </filter>
- <filter-mapping>
- <filter-name>casAuthenticationFilter</filter-name>
- <url-pattern>/*</url-pattern>
- </filter-mapping>
这个配置依然是可用的,当然我们要实现忽略/排除请求URL的功能,那么我们该怎么做呢?
2、忽略/排除多个请求URL
- <filter>
- <filter-name>casAuthenticationFilter</filter-name>
- <filter-class>org.jasig.cas.client.authentication.AuthenticationFilter</filter-class>
- <init-param>
- <param-name>casServerLoginUrl</param-name>
- <param-value>http://cas.eguid.cc/cas-server/</param-value>
- </init-param>
- <init-param>
- <param-name>serverName</param-name>
- <param-value>http://cilent.eguid.cc/</param-value>
- <param-name>ignorePattern</param-name>
- <param-value>/js/*|/img/*|/view/*|/css/*</param-value>
- </init-param>
- </filter><!--做好自己!eguid原创-->
- <filter-mapping>
- <filter-name>casAuthenticationFilter</filter-name>
- <url-pattern>/*</url-pattern>
- </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方法
- <span style="color:#24292e;"> public final void doFilter(final ServletRequest servletRequest, final ServletResponse servletResponse,
- final FilterChain filterChain) throws IOException, ServletException {
- <!--做好自己!eguid原创-->
- final HttpServletRequest request = (HttpServletRequest) servletRequest;
- final HttpServletResponse response = (HttpServletResponse) servletResponse;
- if (</span><span style="color:#ff0000;">isRequestUrlExcluded</span><span style="color:#24292e;">(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;
- if (assertion != null) {
- filterChain.doFilter(request, response);
- return;
- }
- final String serviceUrl = constructServiceUrl(request, response);
- final String ticket = retrieveTicketFromRequest(request);
- final boolean wasGatewayed = this.gateway && this.gatewayStorage.hasGatewayedAlready(request, serviceUrl);
- 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);
- final String urlToRedirectTo = CommonUtils.constructRedirectUrl(this.casServerLoginUrl,
- getProtocol().getServiceParameterName(), modifiedServiceUrl, this.renew, this.gateway);
- logger.debug("redirecting to \"{}\"", urlToRedirectTo);
- this.authenticationRedirectStrategy.redirect(request, response, urlToRedirectTo);
- }</span>
(3)isRequestUrlExcluded方法
第一眼就看到了上面代码红色标识处的isRequestUrlExcluded,这个意思很直白,判断是不是需要忽略/排除的请求URL。
继续接着找到isRequestUrlExcluded这个方法的实现代码:
- <span style="color:#24292e;"> private boolean isRequestUrlExcluded(final HttpServletRequest request) {
- if (this.ignoreUrlPatternMatcherStrategyClass == null) {
- return false;
- }
- <!--做好自己!eguid原创-->
- final StringBuffer urlBuffer = request.getRequestURL();
- if (request.getQueryString() != null) {
- urlBuffer.append("?").append(request.getQueryString());
- }
- final String requestUri = urlBuffer.toString();
- return this.</span><span style="color:#ff0000;">ignoreUrlPatternMatcherStrategyClass</span><span style="color:#24292e;">.matches(requestUri);
- }</span>
看红色标识位置的名字,这里用到了UrlPatternMatcherStrategy这个类,意思很简单直白:‘请求url的匹配策略类’,暂时还不知道这里是正则匹配,往后看:
(4)请求URL的匹配策略类UrlPatternMatcherStrategy
- private UrlPatternMatcherStrategy ignoreUrlPatternMatcherStrategyClass = null;
发现该类是在初始化方法中进行初始化的:
- <span style="color:#24292e;"> protected void initInternal(final FilterConfig filterConfig) throws ServletException {
- if (!isIgnoreInitConfiguration()) {
- super.initInternal(filterConfig);
- setCasServerLoginUrl(getString(ConfigurationKeys.CAS_SERVER_LOGIN_URL));
- setRenew(getBoolean(ConfigurationKeys.RENEW));
- setGateway(getBoolean(ConfigurationKeys.GATEWAY));
- <!--做好自己!eguid原创-->
- final String ignorePattern = getString(ConfigurationKeys.</span><span style="color:#ff0000;">IGNORE_PATTERN</span><span style="color:#24292e;">);
- final String ignoreUrlPatternType = getString(ConfigurationKeys.</span><span style="color:#ff0000;">IGNORE_URL_PATTERN_TYPE</span><span style="color:#24292e;">);
- if (ignorePattern != null) {
- final Class<? extends UrlPatternMatcherStrategy> ignoreUrlMatcherClass = PATTERN_MATCHER_TYPES.get(ignoreUrlPatternType);
- if (ignoreUrlMatcherClass != null) {
- this.ignoreUrlPatternMatcherStrategyClass = ReflectUtils.newInstance(ignoreUrlMatcherClass.getName());
- } else {
- try {
- logger.trace("Assuming {} is a qualified class name...", ignoreUrlPatternType);
- this.ignoreUrlPatternMatcherStrategyClass = ReflectUtils.newInstance(ignoreUrlPatternType);
- } catch (final IllegalArgumentException e) {
- logger.error("Could not instantiate class [{}]", ignoreUrlPatternType, e);
- }
- }
- if (this.ignoreUrlPatternMatcherStrategyClass != null) {
- this.ignoreUrlPatternMatcherStrategyClass.setPattern(ignorePattern);
- }
- }
- final Class<? extends GatewayResolver> gatewayStorageClass = getClass(ConfigurationKeys.GATEWAY_STORAGE_CLASS);
- if (gatewayStorageClass != null) {
- setGatewayStorage(ReflectUtils.newInstance(gatewayStorageClass));
- }
- final Class<? extends AuthenticationRedirectStrategy> authenticationRedirectStrategyClass = getClass(ConfigurationKeys.AUTHENTICATION_REDIRECT_STRATEGY_CLASS);
- if (authenticationRedirectStrategyClass != null) {
- this.authenticationRedirectStrategy = ReflectUtils.newInstance(authenticationRedirectStrategyClass);
- }
- }
- }</span>
虽然使用了反射,但是依然不影响我们找到根本所在,找到ConfigurationKeys这个类里面的变量究竟是什么:
- <span style="color:#24292e;"> ConfigurationKey<String> IGNORE_PATTERN = new ConfigurationKey<String>("</span><span style="color:#ff0000;">ignorePattern</span><span style="color:#24292e;">", null);
- ConfigurationKey<String> IGNORE_URL_PATTERN_TYPE = new ConfigurationKey<String>("</span><span style="color:#ff0000;">ignoreUrlPatternType</span><span style="color:#24292e;">", "REGEX");</span>
字面上理解这两个常量定义了忽略模式以及忽略模式类型是‘正则’,当然我们还是不确定是不是正则,那么继续往下找
- final Class<? extends UrlPatternMatcherStrategy> ignoreUrlMatcherClass = PATTERN_MATCHER_TYPES.get(ignoreUrlPatternType);
我们已经通过ConfigurationKeys类知道ignoreUrlPatternType是个‘REGEX’字符串,那么
- PATTERN_MATCHER_TYPES.put("REGEX", RegexUrlPatternMatcherStrategy.class);
那么按照REGEX对应的值找到RegexUrlPatternMatcherStrategy这个类:
(5)确定RegexUrlPatternMatcherStrategy类用于处理正则验证匹配
- public final class RegexUrlPatternMatcherStrategy implements UrlPatternMatcherStrategy {
- <!--做好自己!eguid原创-->
- private Pattern pattern;
- public RegexUrlPatternMatcherStrategy() {}
- public RegexUrlPatternMatcherStrategy(final String pattern) {
- this.setPattern(pattern);
- }
- public boolean matches(final String url) {
- return this.pattern.matcher(url).find();
- }
- public void setPattern(final String pattern) {
- this.pattern = Pattern.compile(pattern);
- }
- }
该类中用到了Pattern来编译和匹配正则表达式
到这里我们终于可以确定可以用ignorePattern来忽略/排除我们不需要拦截的请求URL,当然必须满足正则表达式。
关于cas-client单点登录客户端拦截请求和忽略/排除不需要拦截的请求URL的问题(不需要修改任何代码,只需要一个配置)的更多相关文章
- cas-client单点登录客户端拦截请求和忽略/排除不需要拦截的请求URL的问题
http://blog.csdn.net/eguid_1/article/details/73611781
- [精华][推荐]CAS SSO 单点登录框架学习 环境搭建
1.了解单点登录 SSO 主要特点是: SSO 应用之间使用 Web 协议(如 HTTPS) ,并且只有一个登录入口. SSO 的体系中有下面三种角色: 1) User(多个) 2) Web 应用( ...
- CAS SSO单点登录框架学习
1.了解单点登录 SSO 主要特点是: SSO 应用之间使用 Web 协议(如 HTTPS) ,并且只有一个登录入口. SSO 的体系中有下面三种角色: 1) User(多个) 2) Web 应用( ...
- CAS SSO单点登录框架介绍
1.了解单点登录 SSO 主要特点是: SSO 应用之间使用 Web 协议(如 HTTPS) ,并且只有一个登录入口. SSO 的体系中有下面三种角色: 1) User(多个) 2) Web 应用( ...
- 基于CAS的单点登录实战(2)-- 搭建cas的php客户端
在这之前已经搭好了CAS服务端 基于CAS的单点登录实战(1)-- 搭建cas服务器 PHP-Client php-Client是官方支持的,去官网下个最新版就好了.phpCAS 接入很简单,解压放到 ...
- [精华][推荐]CAS SSO单点登录服务端客户端实例
1.修改server.xml文件,如下: 注意: 这里使用的是https的认证方式,需要将这个配置放开,并做如下修改: <Connector port="8443" prot ...
- Cas(07)——建立使用Cas进行单点登录的应用
建立使用Cas进行单点登录的应用 目录 1.1加入cas-client-core-xxx.jar到classpath 1.2配置Filter 1.2.1AuthenticationFilter 1.2 ...
- CAS实现单点登录SSO执行原理及部署
一.不落俗套的开始 1.背景介绍 单点登录:Single Sign On,简称SSO,SSO使得在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统. CAS框架:CAS(Centra ...
- CAS实现单点登录
1.简介 SSO单点登录 在多个相互信任的系统中,用户只需要登录一次就可以访问其他受信任的系统. 新浪微博与新浪博客是相互信任的应用系统. *当用户首次访问新浪微博时,新浪微博识别到用户未登录,将请求 ...
随机推荐
- iOS开发tips-UINavigationBar的切换
概述 在iOS系统中,如果控制器是以push方式进行管理的话,那么事实上多个控制器是共享的同一个导航栏.当然iOS系统的设计无可厚非,但是国内的应用经常会遇到很多个性的设计,就比如说A push到 B ...
- Python之函数知识
Python函数分类 a,内置函数 b,自定义函数 c,导入函数 一个函数就相当于一个功能块,比如获取数据库,更新数据库,函数其实就是代码的分块,调用函数来执行代码块 一块就代表一个功能 内置函数有以 ...
- hdu1150 Machine Schedule 经典二分匹配题目
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1150 很经典的二分题目 就是求最小点覆盖集 二分图最小点覆盖集=最大匹配数 代码: #include& ...
- [刷题]算法竞赛入门经典 3-7/UVa1368 3-8/UVa202 3-9/UVa10340
书上具体所有题目:http://pan.baidu.com/s/1hssH0KO 都是<算法竞赛入门经典(第二版)>的题目,标题上没写(第二版) 题目:算法竞赛入门经典 3-7/UVa13 ...
- MySQL数据库操作常用命令
MySQL数据库操作常用命令DOS连接数据库1.安装MySQL配置好环境2.运行cmd命令net start mysql3.找到mysql文件根目录输入命令mysql -h localhost -u ...
- Spring+SpringMVC+MyBatis深入学习及搭建(一)——MyBatis的基础知识
转载请注明出处:http://www.cnblogs.com/Joanna-Yan/p/6812311.html 1.对原生态jdbc程序中问题总结 1.1 jdbc程序 需求:使用jdbc查询mys ...
- 编程语言与C语言的简介
1.什么是程序 指挥计算机执行我们想要它做的动作,而依照顺序执行的一组指令 2.程序的作用是什么 指挥计算机工作 3.程序的特征 1.程序是一行一行的执行 2.是一种与计算机沟通的语言 3.程序是由特 ...
- EntityFramework6.X 之LocalDB&ConnectionString
LocalDB 面向开发人员的SQL Server Express的执行模式,它的安装将复制启动SQL Server数据库引擎所需的最少文件集且使用特定连接字符串来启动连接,它是可以创建和打开SQL ...
- 从 art-template 模版维护到动态加载的思考
自己用 art-template 有些年头了,最近在培养团队学习 art-template 使用,发现有一个痛点比较难解决. 比如有一个模版,我们可以直接写在页面中,像这样: <script i ...
- Dubbo工程结构和Maven打包
Dubbo 工程结构 待续 Dubbo pom版本设置 在升级Dubbo的pom版本时需要对每一个工程中子工程pom,子子工程pom进行修改,这是一个复杂繁琐的工作.为此有人手动一个个修改,好一点的用 ...