spring-oauth集成cas单点登录,登陆完成进入授权页面后,按回退按钮进入404页面的问题
2015-07-21 00:00
561 查看
本文转自我的博客,转载请申明地址:http://www.heartlifes.com/archives/7/
2.使用spring-oauth包实现oauth2服务
3.使用spring-cas做spring-security及cas的集成
系统调用/oauth/authorize接口,被spring-security拦截进入cas登录界面后,用户输入用户名密码做登录,登录成功后,浏览器跳转到授权界面,这时候用户点了回退按钮(这个用户好无聊),进入了404的错误界面
官方文档解释说这个拦截器是用来还原被登录操作打断的用户界面跳转用的,什么意思呢,就是说:
1.你的系统用spring-security提供的登录方法
2.用户点了你系统的某个链接xxx,这个xxx在spring-security中是个需要被安全控制的连接
3.spring-security拦截这个xxx链接,并且跳到了登录界面
4.用户登录完了后,RequestCacheAwareFilter这个拦截器,再把xxx返回给浏览器
但是,我们这里是集成了cas做登录的,那么,悲剧发生了。
有一行叫remveRequest,这行代码会把存在requestCache中的请求路径给清除。而这个请求路径就是用户在按回退按钮时,浏览器要跳转的路径。具体看以下逻辑:
当用户按回退按钮时,其实是回到了spring-cas提供的j_spring_cas_security_check这个url里,最终会到<pre><code>SavedRequestAwareAuthenticationSuccessHandler</code></pre>中判断该跳转到哪个页面:
可以看到,如果requestCache的请求路径是空,那么就会跳转到默认路径,这个路径如果你没有在spring中配置的话,默认就是你应用访问上下文的跟路径,如果跟路径下没有首页的话,那就自然报404错误了。
背景:###
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); } }
相关文章推荐
- ASP.NET实现单点登陆(SSO)适用于多种情况
- jasig-cas 学习历程
- 配置完 Exchange Server 2010 CAS Array后需要做的
- 单点登录(SSO)的实现—通行证的基本原理
- CAS实现单点登录(SSO)经典完整教程(1)
- CAS实现单点登录(SSO)经典完整教程(2)
- SSO单点登录Spring-Security+CAS+使用手册.doc
- 单点登录 sso
- ZCS与CAS(Central Authentication Service)单点登录系统的集成
- 原创cas支持客户端应用验证
- 单点登录(cas)、缓存技术与负载均衡
- 分享Cisco 642-591题库
- CAS单点退出代码走读
- 关于CAS4.0单点登录配置的几个坑
- Enterprise Simple Sign-On Middleware的现状和前景
- Single Sign On , 简称 SSO
- JAVA CAS原理深度分析
- 修改SSO管理员密码
- vmware vc sso 配置