文档章节

spring-oauth集成cas单点登录,登陆完成进入授权页面后,按回退按钮进入404页面的问题

j
 janwenjohn
发布于 2015/07/21 13:33
字数 776
阅读 261
收藏 4

本文转自我的博客,转载请申明地址:http://www.heartlifes.com/archives/7/

背景:###

1.项目中使用耶鲁的cas做单点登录。 2.使用spring-oauth包实现oauth2服务 3.使用spring-cas做spring-security及cas的集成

现象:###

开发报了个bug,大致流程就是 系统调用/oauth/authorize接口,被spring-security拦截进入cas登录界面后,用户输入用户名密码做登录,登录成功后,浏览器跳转到授权界面,这时候用户点了回退按钮(这个用户好无聊),进入了404的错误界面

原因:###

撸了一把spring的源码后发现,spring-security的默认拦截器堆栈中,有个拦截器叫RequestCacheAwareFilter 官方文档解释说这个拦截器是用来还原被登录操作打断的用户界面跳转用的,什么意思呢,就是说: 1.你的系统用spring-security提供的登录方法 2.用户点了你系统的某个链接xxx,这个xxx在spring-security中是个需要被安全控制的连接 3.spring-security拦截这个xxx链接,并且跳到了登录界面 4.用户登录完了后,RequestCacheAwareFilter这个拦截器,再把xxx返回给浏览器

但是,我们这里是集成了cas做登录的,那么,悲剧发生了。

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        HttpServletRequest wrappedSavedRequest =
            requestCache.getMatchingRequest((HttpServletRequest)request, (HttpServletResponse)response);
        chain.doFilter(wrappedSavedRequest == null ? request : wrappedSavedRequest, response);
}</code></pre>
这个filter会去调用requestCache的一个方法,requestCache是spring中用来缓存浏览器request请求的缓存存储。这个方法如下所示:
<pre><code>public HttpServletRequest getMatchingRequest(HttpServletRequest request,
			HttpServletResponse response) {
		DefaultSavedRequest saved = (DefaultSavedRequest) getRequest(request,
				response);
		if (saved == null) {
			return null;
		}
		if (!saved.doesRequestMatch(request, portResolver)) {
			logger.debug("saved request doesn't match");
			return null;
		}
		removeRequest(request, response);
		return new SavedRequestAwareWrapper(saved, request);
	}

有一行叫remveRequest,这行代码会把存在requestCache中的请求路径给清除。而这个请求路径就是用户在按回退按钮时,浏览器要跳转的路径。具体看以下逻辑:

当用户按回退按钮时,其实是回到了spring-cas提供的j_spring_cas_security_check这个url里,最终会到<pre><code>SavedRequestAwareAuthenticationSuccessHandler</code></pre>中判断该跳转到哪个页面:

SavedRequest savedRequest = requestCache.getRequest(request, response);
        if (savedRequest == null) {
            super.onAuthenticationSuccess(request, response, authentication);
            return;
        }
        String targetUrlParameter = getTargetUrlParameter();
        if (isAlwaysUseDefaultTargetUrl() || (targetUrlParameter != null && StringUtils.hasText(request.getParameter(targetUrlParameter)))) {
            requestCache.removeRequest(request, response);
            super.onAuthenticationSuccess(request, response, authentication);
            return;
        }
        clearAuthenticationAttributes(request);
        // Use the DefaultSavedRequest URL
        String targetUrl = savedRequest.getRedirectUrl();
        logger.debug("Redirecting to DefaultSavedRequest Url: " + targetUrl);
        getRedirectStrategy().sendRedirect(request, response, targetUrl);

可以看到,如果requestCache的请求路径是空,那么就会跳转到默认路径,这个路径如果你没有在spring中配置的话,默认就是你应用访问上下文的跟路径,如果跟路径下没有首页的话,那就自然报404错误了。

解决:###

没什么好的解决方式,目前我们只是粗暴的将RequestCache的实现类HttpSessionRequestCache重写了一把,加入一段判断逻辑:

public void removeRequest(HttpServletRequest currentRequest,
			HttpServletResponse response) {
		HttpSession session = currentRequest.getSession(false);
		if (session != null) {
			logger.debug("Removing DefaultSavedRequest from session if present");
			Object obj = session.getAttribute(SAVED_REQUEST);
			if (obj instanceof DefaultSavedRequest) {
				DefaultSavedRequest savedRequest = (DefaultSavedRequest) obj;
				String requestURI = savedRequest.getRequestURI();
				System.out.println("requestCache....requestURI...."
						+ savedRequest.getRequestURI());
				if (requestURI.contains("/api/oauth/")) {
					return;
				}
			}
			session.removeAttribute(SAVED_REQUEST);
		}
	}

© 著作权归作者所有

j
粉丝 0
博文 10
码字总数 5840
作品 0
闸北
私信 提问
Spring Security OAuth2 SSO

通常公司肯定不止一个系统,每个系统都需要进行认证和权限控制,不可能每个每个系统都自己去写,这个时候需要把登录单独提出来 登录和授权是统一的 业务系统该怎么写还怎么写 最近学习了一下...

不要乱摸
2018/07/11
0
0
Spring cloud oauth2.0学习总结

因为项目需要,调研并使用了Spring cloud oauth2.0,网上关于oauth2.0的介绍很多,包括交互的流程等等。这里,我不再介绍这些,直接深入讲解,并附上实践代码。希望能对大家有帮助。 相关链接...

菜鸟很菜
2017/04/14
0
0
(十)Java B2B2C多用户商城 springcloud架构-SSO单点登录之OAuth2.0登录认证(1)

之前写了很多关于spring cloud的文章,今天我们对OAuth2.0的整合方式做一下笔记,首先我从网上找了一些关于OAuth2.0的一些基础知识点,帮助大家回顾一下知识点: 一、oauth中的角色 client:...

park
01/25
0
0
JAVA 多用户商城系统b2b2c-SSO单点登录之OAuth2.0登录认证

之前写了很多关于spring cloud的文章,需要JAVA Spring Cloud大型企业分布式微服务云构建的B2B2C电子商务平台源码 一零三八七七四六二六 ,今天我们对OAuth2.0的整合方式做一下笔记,首先我从...

明理萝
04/11
27
1
Spring Cloud云架构 - SSO单点登录之OAuth2.0登录认证(1)

今天我们对OAuth2.0的整合方式做一下笔记,首先我从网上找了一些关于OAuth2.0的一些基础知识点,帮助大家回顾一下知识点: 一、oauth中的角色 client:调用资源服务器API的应用 Oauth 2.0 Pr...

明理萝
2018/06/07
122
2

没有更多内容

加载失败,请刷新页面

加载更多

代理模式之JDK动态代理 — “JDK Dynamic Proxy“

动态代理的原理是什么? 所谓的动态代理,他是一个代理机制,代理机制可以看作是对调用目标的一个包装,这样我们对目标代码的调用不是直接发生的,而是通过代理完成,通过代理可以有效的让调...

code-ortaerc
今天
5
0
学习记录(day05-标签操作、属性绑定、语句控制、数据绑定、事件绑定、案例用户登录)

[TOC] 1.1.1标签操作v-text&v-html v-text:会把data中绑定的数据值原样输出。 v-html:会把data中值输出,且会自动解析html代码 <!--可以将指定的内容显示到标签体中--><标签 v-text=""></......

庭前云落
今天
8
0
VMware vSphere的两种RDM磁盘

在VMware vSphere vCenter中创建虚拟机时,可以添加一种叫RDM的磁盘。 RDM - Raw Device Mapping,原始设备映射,那么,RDM磁盘是不是就可以称作为“原始设备映射磁盘”呢?这也是一种可以热...

大别阿郎
今天
12
0
【AngularJS学习笔记】02 小杂烩及学习总结

本文转载于:专业的前端网站☞【AngularJS学习笔记】02 小杂烩及学习总结 表格示例 <div ng-app="myApp" ng-controller="customersCtrl"> <table> <tr ng-repeat="x in names | orderBy ......

前端老手
昨天
16
0
Linux 内核的五大创新

在科技行业,创新这个词几乎和革命一样到处泛滥,所以很难将那些夸张的东西与真正令人振奋的东西区分开来。Linux内核被称为创新,但它又被称为现代计算中最大的奇迹,一个微观世界中的庞然大...

阮鹏
昨天
20
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部