Cas 4.2.7 OAuth + Rest implement SSO, 4.2.7oauth
For details about Cas authentication principles and Rest usage, refer to the previous article. This article focuses on the problems encountered when using the Rest interface to log on to the system and other single-point logon systems, as well as the ideas and processes for solving the problems. I. When you use the Rest interface to log on to other systems that use Cas single-point logon, Cas determines that the current user has not logged on and requires logon. After analysis, it is found that when accessing other Cas single-point logon systems, Cas cannot obtain the TGC in the Cookie of the current client. That is to say, using the Rest interface to log on to Cas cannot write TGC to the client Cookie. The parsing of TGC is not detailed here. Applicable scenarios
- Some systems use the authorization-free login method to access the CAS single-point logon system, and want to switch to other systems using SSO.
- Some business systems have their own login pages. In their login logic, they call the Rest interface of Cas to achieve login, and want to use SSO to switch to other systems.
II. The problem solving process continues to be tracked to the retrieveCookieValue method of the CookieRetrievingCookieGenerator class:
try { final Cookie cookie = org.springframework.web.util.WebUtils.getCookie( request, getCookieName()); return cookie == null ? null : this.casCookieValueManager.obtainCookieValue(cookie, request); } catch (final Exception e) { logger.debug(e.getMessage(), e); } return null;
Code Description: The logic is relatively simple. If you are interested in obtaining the TGC (getCookieName () method from the cookie, you can trace it.) If the TGC is not empty, call this. casCookieValueManager. the obtainCookieValue (cookie, request) method parses TGC to get TGT, and the problem becomes clearer. TGT is obtained based on TGC.
Trace defacascascookievaluemanager (why defacascascookievaluemanager implementation class, if you are interested, you can trace it) in the obtainCookieValue method of the class:
final String cookieValue = this.cipherExecutor.decode(cookie.getValue()); LOGGER.debug("Decoded cookie value is [{}]", cookieValue); if (StringUtils.isBlank(cookieValue)) { LOGGER.debug("Retrieved decoded cookie value is blank. Failed to decode cookie [{}]", cookie.getName()); return null; } final String[] cookieParts = cookieValue.split(String.valueOf(COOKIE_FIELD_SEPARATOR)); if (cookieParts.length != COOKIE_FIELDS_LENGTH) { throw new IllegalStateException("Invalid cookie. Required fields are missing"); } final String value = cookieParts[0]; final String remoteAddr = cookieParts[1]; final String userAgent = cookieParts[2]; if (StringUtils.isBlank(value) || StringUtils.isBlank(remoteAddr) || StringUtils.isBlank(userAgent)) { throw new IllegalStateException("Invalid cookie. Required fields are empty"); } if (!remoteAddr.equals(request.getRemoteAddr())) { throw new IllegalStateException("Invalid cookie. Required remote address does not match " + request.getRemoteAddr()); } if (!userAgent.equals(request.getHeader("user-agent"))) { throw new IllegalStateException("Invalid cookie. Required user-agent does not match " + request.getHeader("user-agent")); } return value;
Code Description: decrypt TGC and obtain a string separated by the @ symbol. After the string is separated, TGT, Client IP address, and client proxy information are obtained. The Client IP address and client proxy information decrypted from TGC are compared with the client IP address and client proxy information of the current request, if they are not equal, an exception is thrown (Cas security policy ).
- Return to the root cause of the problem. When the business system calls the Cas Rest interface to log on, and then switches to another single sign-on system, it first requests the Cas login authorization page. When the program calls this. ticketGrantingTicketCookieGenerator. when retrieveCookieValue (request) obtains TGT, The TGC of the client cannot be parsed because it is null.
- Thinking: Since the Rest interface is called to implement login, TGT information is returned. Can I request the Cas login authorization page again and pass in TGT information, then, modify the source code to encrypt TGT into TGC and add it to the cookie of the client. Cas considers the current user as logged in and redirects back to the service address.
- The Cas login authorization page needs to be transformed to obtain the passed TGT information, or you need to go to the doExecute method of the InitialFlowSetupAction class for processing
Before transformation:
WebUtils.putTicketGrantingTicketInScopes(context, this.ticketGrantingTicketCookieGenerator.retrieveCookieValue(request));
After Transformation:
String cookie = this. ticketGrantingTicketCookieGenerator. retrieveCookieValue (request); // Add the tgt if (cookie = null & request. getRequestURI (). contains ("/login") {String tgt = request. getParameter ("tgt"); if (StringUtils. isNotBlank (tgt) {HttpServletResponse response = WebUtils. getHttpServletResponse (context); // TGT generate TGC and add this. ticketGrantingTicketCookieGenerator. addCookie (request, response, tgt); // The tgt value is directly sent to cookie = tgt ;}} WebUtils. putTicketGrantingTicketInScopes (context, cookie );
Change on-start configuration in login-flow.xml to custom initialFlowSetupExAction
<on-start> <evaluate expression="initialFlowSetupExAction"/> </on-start>
About this. ticketGrantingTicketCookieGenerator. addCookie (request, response, tgt); if you are interested in this method, you can trace it. Client Transformation: Call the Cas Rest interface login successful, parse the returned TGT, and redirect to the Cas login page with service and tgt parameters can be example: https://cas.xxxx.com/cas/login? Service = https://xxx.xxxx.com & tgt = TGT-817-6QBDc0n7Impr0EguA3mFpaViSeTOEzsMbefbW629nZRihFznoH-cas01.example.org hope you don't give advice, have any errors, questions and more exchanges. Copyright Disclaimer: This article is an original article by the blogger. The source must be indicated for reprinting. Http://www.cnblogs.com/bryanx/p/8588270.html