登录某网站成功后显示CAS服务没启动,然后点网页内链接网页登录后又跳转登录页面回到登录界面,如何解决?

原文及更多文章请见个人博客:http://heartlifes.com背景: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);
}
这个filter会去调用requestCache的一个方法,requestCache是spring中用来缓存浏览器request请求的缓存存储。这个方法如下所示: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里,最终会到SavedRequestAwareAuthenticationSuccessHandler
中判断该跳转到哪个页面: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);
}
}
}

我要回帖

更多关于 网页登录后又跳转登录页面 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信