Naive_3
Do.7
采纳率59.1%
2017-02-17 09:33 阅读 4.0k

cas单点登录用户超时无法正确跳转到登录界面

2

前台使用的是Ajax请求一个页面,然后填充到主页面。

 jQuery.post("xxxx.action" + new Date().getTime(), function sgBack(data) {
        jQuery("#xxx").html(data);
        });

当用户长时间未登录 失效点击按钮的时候是不进xxxx.action。而是由单点登录
response.sendRedirect(url);到登录界面。
问题是前台把登录界面给 塞到 jQuery("#xxx").html(data);并没有直接跳转到登录界面。
求教怎么让页面主体跳转到登录页面!

  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 复制链接分享

2条回答 默认 最新

  • JE_GE JE_GE 2017-02-17 15:07
    点赞 评论 复制链接分享
  • dabocaiqq dabocaiqq 2017-02-17 21:08

    1 错误场景

    cas session 超时问题:XMLHttpRequest cannot loadhttps://www.hf.com:8443/cas/login?service=http%3A%2F%2Flocalhost%3A8080%2Fvms%2Fcheck%2FfindPendingCheck%2F. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8080' is therefore not allowed access.
    部署问题:用nginx封装,service携带不过来。
    2 cas 针对session超时设置

    cas对于session超时设置,可以设置文件cas\WEB-INF\spring-configuration\ticketExpirationPolicies.xml 进行设置,如下所示:
    [html] view plaincopyprint?












    [html] view plaincopyprint?


    <!-- This argument is the number of times that a ticket can be used before its considered expired. -->

    index="0"
    value="1" />

    <!-- This argument is the time a ticket can exist before its considered expired.  -->  
    <constructor-arg  
        index="1"  
        value="20000" />  
    
    上述两个bean中,设置为20000毫秒(设置超时单位为毫秒),上述另个bean的机制就如同session机制一样,当用户没有与服务器的交互超过20秒,点击url,便会自动转到登录界面。单只是设置这一点是不够的,会有问题的。
    问题:当你的项目中也有对session的设置,以及对session时间的设置的时候,只设置cas的session超时是不管事的。
    

    3 配置完毕,对于ajax请求出现的错误

    问 题的解决:所以我们需要把项目中session超时的时间和cas session超时的时间设置为一致,因为cas对session超时的处理,是在cas-client-core-3.2.1.jar 包中,而cas的客户端是和项目放在一起的,所以对session处理机制是一样的。

    当然上述的处理一般情况下是没有问题的,但当遇到ajax请求,就不可以了,会报如下错误:
    

    XMLHttpRequest cannot load https://www.hf.com:8443/cas/login?service=http%3A%2F%2Flocalhost%3A8080%2Fvms%2Fcheck%2FfindPendingCheck%2F. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8080' is therefore not allowed access.
    千 万别被Origin蒙蔽,开始定位错误定位在跨域问题,因为网上查找说也是跨域问题,而实际上对于非ajax请求,cas拦截处理后是可以跳转到登录页面 的,这说明了是可以请求给cas的,只不过cas对ajax的请求无法做出session失效的处理,这怎么办呢?只能去改CAS源码了。不知道是cas 矮,还是自己太矮了。。。
    4 修改CAS源码,解决上述问题

    经过查看错误日志,找到cas打印日志的地方,找到cas处理session的方法,修改的是/CAS_Client/src/org/jasig/cas/client/authentication/AuthenticationFilter.java这个java类。修改的doFilter方法如下所示。
    [java] view plaincopyprint?
    public final void doFilter(final ServletRequest servletRequest, final ServletResponse servletResponse, final FilterChain filterChain) throws IOException, ServletException {

    final HttpServletRequest request = (HttpServletRequest) servletRequest;

    final HttpServletResponse response = (HttpServletResponse) servletResponse;

    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 = CommonUtils.safeGetParameter(request,getArtifactParameterName());  
      final boolean wasGatewayed = this.gatewayStorage.hasGatewayedAlready(request, serviceUrl);  
    
      if (CommonUtils.isNotBlank(ticket) || wasGatewayed) {  
          filterChain.doFilter(request, response);  
          return;  
      }  
    
      final String modifiedServiceUrl;  
    
      log.debug("no ticket and no assertion found");  
      if (this.gateway) {  
          log.debug("setting gateway attribute in session");  
          modifiedServiceUrl = this.gatewayStorage.storeGatewayInformation(request, serviceUrl);  
      } else {  
          modifiedServiceUrl = serviceUrl;  
      }  
      if (log.isDebugEnabled()) {  
          log.debug("Constructed service url: " + modifiedServiceUrl);  
      }  
    
      final String urlToRedirectTo = CommonUtils.constructRedirectUrl(this.casServerLoginUrl, getServiceParameterName(), modifiedServiceUrl, this.renew, this.gateway);  
    
      if (log.isDebugEnabled()) {  
          log.debug("redirecting to \"" + urlToRedirectTo + "\"");  
      }  
    
      log.debug("判断拼接的过程,参数, 最终拼接好的地址为: \"" + urlToRedirectTo + "\"");  
    
      //response.sendRedirect(urlToRedirectTo);  
      String url = request.getRequestURL().toString();  
      log.debug("url------request.getRequestURL().toString()=---------:" + url);  
      String contextPath = request.getContextPath();  
      log.debug("contextPath ---------request.getContextPath()=-------:" + contextPath);  
    
      url = url.substring(0, (url.indexOf(contextPath)+contextPath.length()));  
      log.debug("url = ------session消失,截取到项目的url---" + url);  
      String urls = urlToRedirectTo;  
    
      //判断是否是第一次转到.  
      if("".equals(url)||url==null||url.length()==0){  
    
        log.debug("url--第一次为空,不截取-----" + url);  
        urls = urlToRedirectTo;  
        //response.sendRedirect(urlToRedirectTo);  
      }else{  
        urls = urls.substring(0, (urls.indexOf("service=")+8)) + URLEncoder.encode(url,"UTF-8");  
      }  
    
      log.debug("urls --最终输入到浏览器的地址是-----------" + urls);  
    

    response.setContentType("text/html;charset=UTF-8");

    response.getWriter().write("window.location.href=&#39;&quot;+urls+&quot;/&#39;");

    }

    这样不但解决了cas对ajax地址处理,并且解决了另一个问题,因为最初的改动不是上述的代码,中间出现了一个小插曲,部署的时候出现的bug,登录时service参数携带不过来。当我们把项目部署到linux上时,用nginx代理,并配置tomcat的sever.xml文件封装项目名称, 则样,域名“封装”了ip+端口号+项目名称,用户不需要再输入项目名称了。所以代码中对用户第一次登录做判断,判断是否是第一次登录还是session失效调用的这个方法,这样就解决了nginx代理出现的问题了。
    

    5 总结

    1)TGT时间:

    在ticketExpirationPolicies.xml中,

    <!-- This argument is the time a ticket can exist before its considered expired. -->

    <constructor-arg

    index="0"

    value="7200000" />

    这里进行设置的时间是TGT(ticket granting ticket)的时间,如果TGT时间到期,则需要进行重新登录。这里时间单位是毫秒,默认是两小时。

    如果进行了rememberMe配置,则是在

    <!-- 一般情况下的 cas session 实效时间 -->

    <bean class="org.jasig.cas.ticket.support.TimeoutExpirationPolicy">
    
           <constructor-arg index="0" value="60000" />
    
    </bean>
    

    <!-- 全天免登录 情况下 cas session的实效时间 -->

    <bean class="org.jasig.cas.ticket.support.TimeoutExpirationPolicy">
    
           <constructor-arg index="0" value="1209600000" />
    
    </bean>
    

    中的sessionExpirationPolicy进行配置。

    2)rememberMe时间(记住登录状态时间)

    在上面的rememberMeExpirationPolicy中进行配置。时间单位是毫秒。然后在ticketGrantingTicketCookieGenerator.xml中的

    <bean id="ticketGrantingTicketCookieGenerator" class="org.jasig.cas.web.support.CookieRetrievingCookieGenerator"

    p:cookieSecure="false"

    p:cookieMaxAge="-1"

    p:cookieName="CASTGC"

    p:cookiePath="/cas"

    p:rememberMeMaxAge="1209600"/>

    p:rememberMeMaxAge进行配置,两者时间保持一致,注意这里的时间单位是秒。

    点赞 评论 复制链接分享

相关推荐