cas cs程序如何cas单点登录录

headays 的BLOG
用户名:headays
访问量:3055
注册日期:
阅读量:5863
阅读量:12276
阅读量:323999
阅读量:1033915
51CTO推荐博文
& &在网上找了很多的关于CAS的文章来看,发现这篇文章对CAS的整个登陆流程解析的比较清楚,转载过来分享一下。文章来源:首先,cas 服务端的执行流程是WEB-INF/login-webflow.xml定义的,可以大概看看。我用的代码是cas-server-3.5.2-release.zip和cas-client-3.2.1-release.zip。(1)直接访问server端login页面请求:GET /cas/login HTTP/1.1...省略..响应:HTTP/1.1 200 OKServer: Apache-Coyote/1.1Pragma: no-cacheExpires: Thu, 01 Jan :00 GMTCache-Control: no-cacheCache-Control: no-storeSet-Cookie: JSESSIONID=2DA394C7C644AF16FD18; Path=/casContent-Type: text/charset=UTF-8Content-Length: 1993Date: Wed, 30 Oct :49 GMT内容就是登陆表单,省略对于Server端流程来说,走的是&decision-state id="ticketGrantingTicketExistsCheck"&&if test="flowScope.ticketGrantingTicketId != null" then="hasServiceCheck" else="gatewayRequestCheck" /&&/decision-state&TGT不存在,走gatewayRequestCheck&decision-state id="gatewayRequestCheck"&&if test="requestParameters.gateway != '' and requestParameters.gateway != null and flowScope.service != null" then="gatewayServicesManagementCheck" else="serviceAuthorizationCheck" /&&/decision-state&走serviceAuthorizationCheck&action-state id="serviceAuthorizationCheck"&&evaluate expression="serviceAuthorizationCheck"/&&transition to="generateLoginTicket"/&&/action-state&执行认证check,然后转到generateLoginTicket&action-state id="generateLoginTicket"&&evaluate expression="generateLoginTicketAction.generate(flowRequestContext)" /&&transition on="generated" to="viewLoginForm" /&&/action-state&生成登录小票,转到login表单&view-state id="viewLoginForm" view="casLoginView" model="credentials"&&binder&&binding property="username" /&&binding property="password" /&&/binder&&on-entry&&set name="mandName" value="'credentials'" /&&/on-entry&&transition on="submit" bind="true" validate="true" to="realSubmit"&&evaluate expression="authenticationViaFormAction.doBind(flowRequestContext, flowScope.credentials)" /&&/transition&&/view-state&对应的jsp页面是WEB-INF\view\jsp\default\ui\casLoginView.jsp--------------------------------------------------------------------------(2)输入用户名、密码,登录请求:POST /cas/jsessionid=2DA394C7C644AF16FD18 HTTP/1.1Content-Type: application/x-www-form-urlencoded...部分省略...Cookie: JSESSIONID=2DA394C7C644AF16FD18username=admin&password=1&warn=true&=LT-3-Ahdqm03UKMR9vwuy7A5ZSCMa9zJkNi&execution=e1s1&_eventId=submit&x=53&y=55其中的LT-3-Ahdqm03UKMR9vwuy7A5ZSCMa9zJkNi就是登录小票,后台会比较“提交的值”和“后台保存的是否一致”。这个类似于验证码,没啥说的。响应:HTTP/1.1 200 OKServer: Apache-Coyote/1.1Pragma: no-cacheExpires: Thu, 01 Jan :00 GMTCache-Control: no-cacheCache-Control: no-storeSet-Cookie: CASPRIVACY= Path=/cas/; SecureSet-Cookie: CASTGC=TGT-2-DmMvVs9Wy01ScbnMtgtLzgcyX5X14TGcM1f5iGuWIBrlDwTg4Q-cas01.example. Path=/cas/Content-Type: text/charset=UTF-8Content-Length: 1602Date: Wed, 30 Oct :03 GMT后台设置了两个cookie,一个是CASPRIVACY=true,不知道干嘛用的一个是CASTGC,这个就是TicketGrantingTicket Cookie,就是说,你想买通票,你还得先买门票进去的意思,tgc就是门票。这样,客户端浏览器就拥有了TGC门票。下次再访问cas server时就会带着这个门票来了。后台执行流程:由上面viewLoginForm的定义,表单提交后,会执行authenticationViaFormAction.doBind方法,然后跳到realSubmit&action-state id="realSubmit"&&evaluate expression="authenticationViaFormAction.submit(flowRequestContext, flowScope.credentials, messageContext)" /&&transition on="warn" to="warn" /&&transition on="success" to="sendTicketGrantingTicket" /&&transition on="error" to="generateLoginTicket" /&&transition on="accountDisabled" to="casAccountDisabledView" /&&transition on="mustChangePassword" to="casMustChangePassView" /&&transition on="accountLocked" to="casAccountLockedView" /&&transition on="badHours" to="casBadHoursView" /&&transition on="badWorkstation" to="casBadWorkstationView" /&&transition on="passwordExpired" to="casExpiredPassView" /&&/action-state&执行authenticationViaFormAction.submit方法,看一下代码:public final String submit(final RequestContext context, final Credentials credentials, final MessageContext messageContext) throws Exception {// Validate login ticketfinal String authoritativeLoginTicket = WebUtils.getLoginTicketFromFlowScope(context);final String providedLoginTicket = WebUtils.getLoginTicketFromRequest(context);if (!authoritativeLoginTicket.equals(providedLoginTicket)) {this.logger.warn("Invalid login ticket " + providedLoginTicket);final String code = "INVALID_TICKET";messageContext.addMessage(new MessageBuilder().error().code(code).arg(providedLoginTicket).defaultText(code).build());return "error";}final String ticketGrantingTicketId = WebUtils.getTicketGrantingTicketId(context);final Service service = WebUtils.getService(context);if (StringUtils.hasText(context.getRequestParameters().get("renew")) && ticketGrantingTicketId != null && service != null) {try {final String serviceTicketId = this.centralAuthenticationService.grantServiceTicket(ticketGrantingTicketId, service, credentials);WebUtils.putServiceTicketInRequestScope(context, serviceTicketId);putWarnCookieIfRequestParameterPresent(context);return "warn";} catch (final TicketException e) {if (isCauseAuthenticationException(e)) {populateErrorsInstance(e, messageContext);return getAuthenticationExceptionEventId(e);}this.centralAuthenticationService.destroyTicketGrantingTicket(ticketGrantingTicketId);if (logger.isDebugEnabled()) {logger.debug("Attempted to generate a ServiceTicket using renew=true with different credentials", e);}}}try {WebUtils.putTicketGrantingTicketInRequestScope(context, this.centralAuthenticationService.createTicketGrantingTicket(credentials));putWarnCookieIfRequestParameterPresent(context);return "success";} catch (final TicketException e) {populateErrorsInstance(e, messageContext);if (isCauseAuthenticationException(e))return getAuthenticationExceptionEventId(e);return "error";}}service就是指子系统的URL,由于直接访问的server端login,所以URL中没有service参数,所以grantServiceTicket不会执行。最后,会createTicketGrantingTicket,然后放到request中。返回success,跳转到sendTicketGrantingTicket&action-state id="sendTicketGrantingTicket"&&evaluate expression="sendTicketGrantingTicketAction" /&&transition to="serviceCheck" /&&/action-state&这里是把TicketGrantingTicket写到Cookie。然后跳到serviceCheck&!--&decision-state id="serviceCheck"&&if test="flowScope.service != null" then="generateServiceTicket" else="getSubSystemUrl" /&&/decision-state& --&&decision-state id="serviceCheck"&&if test="flowScope.service != null" then="getSubSystemUrl" else="getSubSystemUrl" /&&/decision-state&&action-state id="generateServiceTicket"&&evaluate expression="generateServiceTicketAction" /&&transition on="success" to ="warn" /&&transition on="error" to="generateLoginTicket" /&&transition on="gateway" to="gatewayServicesManagementCheck" /&&/action-state&&action-state id="getSubSystemUrl"&&evaluate expression="getSubSystemUrlAction.get(flowRequestContext, flowScope.credentials)" /&&transition to ="viewGenericLoginSuccess" /&&/action-state&这段被我改过,原来是:有service到generateServiceTicket,没有直接到viewGenericLoginSuccess我改成了,都跳到getSubSystemUrl。这个action是我自己加的,目的是去数据库取得子系统URL,并取得用户对每个子系统的权限。然后跳转到viewGenericLoginSuccess&end-state id="viewGenericLoginSuccess" view="casLoginGenericSuccessView" /&viewGenericLoginSuccess,也就是登录成功页面,就是服务端WEB-INF\view\jsp\default\ui\casGenericSuccess.jsp这个页面。我在这里显示了几个子系统的链接。这里的view写的都是id,实际对应的文件在WEB-INF\classes\default_views.properties中定义。--------------------------------------------------------------------------(3)然后点击页面上的链接,访问子系统请求:GET /UserManage/ HTTP/1.1响应:HTTP/1.1 302 Moved TemporarilyServer: Apache-Coyote/1.1Location: http://10.0.103.137:8080/cas/login?service=http%3A%2F%2F10.0.103.137%3A8080%2FUserManage%2FContent-Length: 0Date: Wed, 30 Oct :22 GMT由于子系统增加了CAS client的Filter。&filter&&filter-name&CAS Authentication Filter&/filter-name&&filter-class&org.jasig.cas.client.authentication.AuthenticationFilter&/filter-class&&!-- CAS login 服务地址--&&init-param&¶m-name&casServerLoginUrl&/param-name&¶m-value&http://10.0.103.137:8080/cas/login&/param-value&&/init-param&&!-- 客户端应用服务地址--&&init-param&¶m-name&serverName&/param-name&¶m-value&http://10.0.103.137:8080&/param-value&&/init-param&&init-param&¶m-name&renew&/param-name&¶m-value&false&/param-value&&/init-param&&init-param&¶m-name&gateway&/param-name&¶m-value&false&/param-value&&/init-param&&/filter&看一下AuthenticationFilter的代码: & public final void doFilter(final ServletRequest servletRequest, final ServletResponse servletResponse, final FilterChain filterChain) throws IOException, ServletException {final HttpServletRequest request = (HttpServletRequest) servletRfinal HttpServletResponse response = (HttpServletResponse) servletRfinal HttpSession session = request.getSession(false);final Assertion assertion = session != null ? (Assertion) session.getAttribute(CONST_CAS_ASSERTION) :if (assertion != null) {filterChain.doFilter(request, response);}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);}final String modifiedServiceUlog.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 = serviceU}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 + "\"");}response.sendRedirect(urlToRedirectTo);}从Session取assertion,就是登录信息,如果有,就继续执行其他Filter。然后看有没有ticket,也就是通票。有的话,继续执行其他Filter。else就拼接URL,跳转。http://10.0.103.137:8080/cas/login?service=http%3A%2F%2F10.0.103.137%3A8080%2FUserManage%2F(4)跳转到server端了请求:GET /cas/login?service=http%3A%2F%2F10.0.103.137%3A8080%2FUserManage%2F HTTP/1.1Cookie: CASTGC=TGT-2-DmMvVs9Wy01ScbnMtgtLzgcyX5X14TGcM1f5iGuWIBrlDwTg4Q-cas01.example. JSESSIONID=2DA394C7C644AF16FD18可以看到,浏览器自动把CASTGC带过来了。响应:HTTP/1.1 302 Moved TemporarilyServer: Apache-Coyote/1.1Pragma: no-cacheExpires: Thu, 01 Jan :00 GMTCache-Control: no-cacheCache-Control: no-storeLocation: http://10.0.103.137:8080/UserManage/?ticket=ST-1-0dnlMstfctMYVcat5wfy-cas01.example.orgContent-Length: 0Date: Wed, 30 Oct :22 GMT又跳回了子系统,但是带着ticket过来的后台流程:&decision-state id="ticketGrantingTicketExistsCheck"&&if test="flowScope.ticketGrantingTicketId != null" then="hasServiceCheck" else="gatewayRequestCheck" /&&/decision-state&CASTGC有了,所以走hasServiceCheck&decision-state id="hasServiceCheck"&&if test="flowScope.service != null" then="renewRequestCheck" else="getSubSystemUrl" /&&/decision-state&service参数也有了,所以走renewRequestCheck&decision-state id="renewRequestCheck"&&if test="requestParameters.renew != '' and requestParameters.renew != null" then="serviceAuthorizationCheck" else="generateServiceTicket" /&&/decision-state&renew客户端配置的是false,所以请求里无此参数。走generateServiceTicket&action-state id="generateServiceTicket"&&evaluate expression="generateServiceTicketAction" /&&transition on="success" to ="warn" /&&transition on="error" to="generateLoginTicket" /&&transition on="gateway" to="gatewayServicesManagementCheck" /&&/action-state&看下代码:protected Event doExecute(final RequestContext context) {final Service service = WebUtils.getService(context);final String ticketGrantingTicket = WebUtils.getTicketGrantingTicketId(context);try {final String serviceTicketId = this.centralAuthenticationService.grantServiceTicket(ticketGrantingTicket,service);WebUtils.putServiceTicketInRequestScope(context,serviceTicketId);return success();} catch (final TicketException e) {if (isGatewayPresent(context)) {return result("gateway");}}return error();}根据ticketGrantingTicket和service,生成通票,并放到request中。成功跳到warn&decision-state id="warn"&&if test="flowScope.warnCookieValue" then="showWarningView" else="redirect" /&&/decision-state&跳转时,不显示提醒页面,所以直接走redirect.&action-state id="redirect"&&evaluate expression="flowScope.service.getResponse(requestScope.serviceTicketId)" result-type="org.jasig.cas.authentication.principal.Response" result="requestScope.response" /&&transition to="postRedirectDecision" /&&/action-state&&decision-state id="postRedirectDecision"&&if test="requestScope.response.responseType.name() == 'POST'" then="postView" else="redirectView" /&&/decision-state&这个看不太懂,反正最后执行redirectView了。&end-state id="redirectView" view="externalRedirect:${requestScope.response.url}" /&执行跳转,哦了(5)又回到客户端了请求:GET /UserManage/?ticket=ST-1-0dnlMstfctMYVcat5wfy-cas01.example.org HTTP/1.1响应:HTTP/1.1 302 Moved TemporarilyServer: Apache-Coyote/1.1Set-Cookie: JSESSIONID=3AE; Path=/UserManageLocation: http://10.0.103.137:8080/UserManage/;jsessionid=3AEContent-Length: 0Date: Wed, 30 Oct :24 GMT这个有点莫名其妙,又跳转了。这时,是客户端的CAS Validation Filter在作怪。&filter&&filter-name&CAS Validation Filter&/filter-name&&filter-class&org.jasig.cas.client.validation.Cas20ProxyReceivingTicketValidationFilter&/filter-class&&init-param&¶m-name&casServerUrlPrefix&/param-name&¶m-value&http://10.0.103.137:8080/cas/&/param-value&&/init-param&&!-- 客户端应用服务地址--&&init-param&¶m-name&serverName&/param-name&¶m-value&http://10.0.103.137:8080&/param-value&&/init-param&&/filter&它发现URL中有ticket了,马上就拿它去服务端check一下,看是否有效,是否过期什么的。这里用的是Cas20ProxyReceivingTicketValidationFilter,它继承了AbstractTicketValidationFilter看看它的doFilter代码:public final void doFilter(final ServletRequest servletRequest, final ServletResponse servletResponse, final FilterChain filterChain) throws IOException, ServletException {if (!preFilter(servletRequest, servletResponse, filterChain)) {}final HttpServletRequest request = (HttpServletRequest) servletRfinal HttpServletResponse response = (HttpServletResponse) servletRfinal String ticket = CommonUtils.safeGetParameter(request, getArtifactParameterName());if (CommonUtils.isNotBlank(ticket)) {if (log.isDebugEnabled()) {log.debug("Attempting to validate ticket: " + ticket);}try {final Assertion assertion = this.ticketValidator.validate(ticket, constructServiceUrl(request, response));if (log.isDebugEnabled()) {log.debug("Successfully authenticated user: " + assertion.getPrincipal().getName());}request.setAttribute(CONST_CAS_ASSERTION, assertion);if (this.useSession) {request.getSession().setAttribute(CONST_CAS_ASSERTION, assertion);}onSuccessfulValidation(request, response, assertion);if (this.redirectAfterValidation) {log. debug("Redirecting after successful ticket validation.");response.sendRedirect(constructServiceUrl(request, response));}} catch (final TicketValidationException e) {response.setStatus(HttpServletResponse.SC_FORBIDDEN);log.warn(e, e);onFailedValidation(request, response);if (this.exceptionOnValidationFailure) {throw new ServletException(e);}}}filterChain.doFilter(request, response);}取ticket,然后final Assertion assertion = this.ticketValidator.validate(ticket, constructServiceUrl(request, response))看看,直接就返回了assertion,这就是登录者信息,包括用户名什么的。然后放到request和session里了。validate方法,实际是调用的AbstractUrlBasedTicketValidator的validate方法,看看final String validationUrl = constructValidationUrl(ticket, service);if (log.isDebugEnabled()) {log.debug("Constructing validation url: " + validationUrl);}try {log.debug("Retrieving response from server.");final String serverResponse = retrieveResponseFromServer(new URL(validationUrl), ticket);if (serverResponse == null) {throw new TicketValidationException("The CAS server returned no response.");}if (log.isDebugEnabled()) {log.debug("Server response: " + serverResponse);}return parseResponseFromServer(serverResponse);} catch (final MalformedURLException e) {throw new TicketValidationException(e);}构建一个URL,然后读取响应。实际调用的AbstractCasProtocolUrlBasedTicketValidator的retrieveResponseFromServer方法protected final String retrieveResponseFromServer(final URL validationUrl, final String ticket) {if (this.hostnameVerifier != null) {return CommonUtils.getResponseFromServer(validationUrl, this.hostnameVerifier, getEncoding());} else {return CommonUtils.getResponseFromServer(validationUrl, getEncoding());}}不知道走的那个,但都是getResponseFromServer方法,看看先。public static String getResponseFromServer(final URL constructedUrl, final HostnameVerifier hostnameVerifier, final String encoding) {URLConnection conn =try {conn = constructedUrl.openConnection();if (conn instanceof HttpsURLConnection) {((HttpsURLConnection)conn).setHostnameVerifier(hostnameVerifier);}final BufferedRif (CommonUtils.isEmpty(encoding)) {in = new BufferedReader(new InputStreamReader(conn.getInputStream()));} else {in = new BufferedReader(new InputStreamReader(conn.getInputStream(), encoding));}Sfinal StringBuilder stringBuffer = new StringBuilder(255);while ((line = in.readLine()) != null) {stringBuffer.append(line);stringBuffer.append("\n");}return stringBuffer.toString();} catch (final Exception e) {LOG.error(e.getMessage(), e);throw new RuntimeException(e);} finally {if (conn != null && conn instanceof HttpURLConnection) {((HttpURLConnection)conn).disconnect();}}}就是直接访问URL,读取数据。-------------------------代码看完,看抓包数据吧。实际上,上面带着ticket跳回客户端后,Filter发起了一个访问请求:GET /cas/serviceValidate?ticket=ST-1-0dnlMstfctMYVcat5wfy-cas01.example.org&service=http%3A%2F%2F10.0.103.137%3A8080%2FUserManage%2F%3Bjsessionid%3D3AE HTTP/1.1User-Agent: Java/1.6.0_26看,User-Agent是Java哦~~响应:HTTP/1.1 200 OKServer: Apache-Coyote/1.1Content-Type: text/charset=UTF-8Content-Language: zh-CNContent-Length: 177Date: Wed, 30 Oct :24 GMT&cas:serviceResponse xmlns:cas='http://www.yale.edu/tp/cas'&&cas:authenticationSuccess&&cas:user&admin&/cas:user&&/cas:authenticationSuccess&&/cas:serviceResponse&可以看到,服务端给返回的xml数据,只有用户名。实际上,想返回更多信息也是可以的,需要修改服务端配置,具体方法请搜索,大概是:cas 登录 返回更多信息服务端/serviceValidate这个请求是&servlet&&servlet-name&cas&/servlet-name&&servlet-class& &org.jasig.cas.web.init.SafeDispatcherServlet&/servlet-class&&/servlet&这个Servlet响应的,但没看太明白,反正最后调到了ServiceValidateController的handleRequestInternal方法里里面有一句:final Assertion assertion = this.centralAuthenticationService.validateServiceTicket(serviceTicketId, service);实际是调用CentralAuthenticationServiceImpl的validateServiceTicket方法这个类有@NotNullprivate TicketRegistry ticketR/** New Ticket Registry for storing and retrieving services tickets. Can point to the same one as the ticketRegistry variable. */@NotNullprivate TicketRegistry serviceTicketR实际上,ticket信息就是保存在这两个变量里的。里面有这样的代码:final ServiceTicket serviceTicket = (ServiceTicket) this.serviceTicketRegistry.getTicket(serviceTicketId, ServiceTicket.class);final List&Authentication& chainedAuthenticationsList = serviceTicket.getGrantingTicket().getChainedAuthentications();final Authentication authentication = chainedAuthenticationsList.get(chainedAuthenticationsList.size() - 1);final Principal principal = authentication.getPrincipal();所以,能拿到Ticket或grant ticket的话,就可以拿到当前用户信息。后面看不动了,大概就是把用户信息写到响应里吧。(6)跳转到之前访问的子系统URL请求:GET /UserManage/;jsessionid=3AE HTTP/1.1Cookie: JSESSIONID=3AE实际上,到前一步,用户信息已经去到,认证过程已经完毕了,单点登录已经实现。后面就是正常访问子系统了。但,每次请求,AuthenticationFilter仍然会检查一下。看一下AuthenticationFilter的代码: & public final void doFilter(final ServletRequest servletRequest, final ServletResponse servletResponse, final FilterChain filterChain) throws IOException, ServletException {final HttpServletRequest request = (HttpServletRequest) servletRfinal HttpServletResponse response = (HttpServletResponse) servletRfinal HttpSession session = request.getSession(false);final Assertion assertion = session != null ? (Assertion) session.getAttribute(CONST_CAS_ASSERTION) :if (assertion != null) {filterChain.doFilter(request, response);}.....由于已经登录,assertion不为空,所以直接跳过了。对性能影响不大。(7)执行logout时,实际是访问server端的logout请求:GET /cas/logout HTTP/1.1Cookie: CASTGC=TGT-2-DmMvVs9Wy01ScbnMtgtLzgcyX5X14TGcM1f5iGuWIBrlDwTg4Q-cas01.example. JSESSIONID=0FFF14E149CF9C55644C响应:HTTP/1.1 200 OKServer: Apache-Coyote/1.1Pragma: no-cacheExpires: Thu, 01 Jan :00 GMTCache-Control: no-cacheCache-Control: no-storeSet-Cookie: CASTGC=""; Expires=Thu, 01-Jan-:10 GMT; Path=/cas/Set-Cookie: CASPRIVACY=""; Expires=Thu, 01-Jan-:10 GMT; Path=/cas/Set-Cookie: JSESSIONID=6DA0ACAEBA3A801CB897E98CE5E92AFC; Path=/casContent-Type: text/charset=UTF-8Content-Language: zh-CNContent-Length: 728Date: Wed, 30 Oct :39 GMT设置Cookie过期。Session总是新起一个。然后内容里有:&script&window.location="/cas/login";&/script&同时,会通知所有已登录的子系统,进行退出操作请求:POST /UserManage/ HTTP/1.1Content-Type: application/x-www-form-urlencodedCache-Control: no-cachePragma: no-cacheUser-Agent: Java/1.6.0_26Host: 10.0.103.137:8080Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2Connection: keep-aliveContent-Length: 484logoutRequest=%3Csamlp%3ALogoutRequest+xmlns%3Asamlp%3D%22urn%3Aoasis%3Anames%3Atc%3ASAML%3A2.0%3Aprotocol%22+ID%3D%22LR-2-0EQR24uNI0TlMr52CzUYMuf1fOAsQg1O447%22+Version%3D%222.0%22+IssueInstant%3D%-30T11%3A31%3A39Z%22%3E%3Csaml%3ANameID+xmlns%3Asaml%3D%22urn%3Aoasis%3Anames%3Atc%3ASAML%3A2.0%3Aassertion%22%3E%40NOT_USED%40%3C%2Fsaml%3ANameID%3E%3Csamlp%3ASessionIndex%3EST-2-nfx6OgRedoAMqowQayXr-cas01.example.org%3C%2Fsamlp%3ASessionIndex%3E%3C%2Fsamlp%3ALogoutRequest%3E响应:HTTP/1.1 200 OKServer: Apache-Coyote/1.1Content-Length: 0Date: Wed, 30 Oct :39 GMT响应是由客户端的SingleSignOutFilter做出的。public void doFilter(final ServletRequest servletRequest, final ServletResponse servletResponse, final FilterChain filterChain) throws IOException, ServletException {final HttpServletRequest request = (HttpServletRequest) servletRif (handler.isTokenRequest(request)) {handler.recordSession(request);} else if (handler.isLogoutRequest(request)) {handler.destroySession(request);// Do not continue up filter chain} else {log.trace("Ignoring URI " + request.getRequestURI());}filterChain.doFilter(servletRequest, servletResponse);}(8)奇怪的一点,退出后,在登录页面,马上进行登录,提交后,服务端还会执行一次跳转。HTTP/1.1 302 Moved TemporarilyServer: Apache-Coyote/1.1Pragma: no-cacheExpires: Thu, 01 Jan :00 GMTCache-Control: no-cacheCache-Control: no-storeSet-Cookie: JSESSIONID=46B50E24FD7; Path=/casLocation: http://10.0.103.137:8080/cas/loginContent-Length: 0Date: Wed, 30 Oct :07 GMT非得重新生成一个session才干~~导致登录页面又刷了一下,这时再登录就OK了。奇怪,奇怪~~原因不明,调查中~~----------------我靠:登录成功后,马上点退出,就有此问题等几秒,再点退出,就无此问题。原因是,登录成功后,会马上咔嚓掉session,默认是2秒后挂掉。马上点退出,Session还没挂,所以不会重建Session,所以,登录页面提交时,是带着这个Session的ID去的,而此时Session挂掉了,故引起页面刷新。而等几秒再退出,会创建新session,故后面无问题。更多信息请看
了这篇文章
类别:┆阅读(0)┆评论(0)

参考资料

 

随机推荐