
åºç¨åºæ¯ï¼å¤ä¸ªç³»ç»ä¸åå±äºä¸ä¸ªç¨æ·ï¼å½ç¨æ·ç»å½äºweb1ç³»ç»ï¼é£ä¹è®¿é®web2ï¼web3. . . . æ¶åï¼ç¨æ·å°±æ é忬¡ç»å½ãå¦ï¼æ·å®ä¸å¤©ç«ï¼ç»åºä¹å¦æ¤ï¼ä¸ä¸ªç³»ç»ç»åºï¼å ¶ä»ç³»ç»çç»å½ä¹éä¹å¤±æï¼è¿å°±æ¯ç»ä¸åç¹ç»å½ç»åºãè¿éé ç½®ä¸ä¸ªwebç³»ç»ï¼ä¸ä¸ªç¨æ·ä¸å¿ç³»ç»ä¸ºæ åãé ç½®hostså®ç°è·¨åï¼127.0.0.1 ssofront.ljtest.xxxx.com #ç¨æ·ä¸å¿127.0.0.1 my.kuaiji.com #web1127.0.0.1 my.zikao.com #web2127.0.0.1 my.xuelxuew.com #web3nginx é ç½®ç¨äºç»ä¸ç»å½é¡µé¢è½¬åserver {listen 80;server_name ssofront.ljtest.xxxx.com;location /ajax/ {proxy_pass http://ssofront.ljtest.xxxx.com:9092/;}location / {root D:/Java/projects/SSO_Single;index index.html;}}å ççææå¾ï¼ç»ä¸ç»å½é¡µé¢ï¼ææçwebç³»ç»ç»å½é½éå®åå°ç¨æ·ä¸å¿çç»ä¸ç»å½é¡µé¢ç»ä¸ç»å½ä¹å访é®åç³»ç»å½web1ç¹å»ç»å½éå®åå°ç¨æ·ä¸å¿ç»ä¸ç»å½ä¹åï¼å访é®web2ï¼web3ç³»ç»é½å·²ç»æ¯ç»å½ç¶æäºãè½å¤å®ç°è¿ç§ææå°±è¯´æç¨æ·ä¸å¿ï¼3个webç³»ç»é½åå«å¨èªå·±çåå䏿åçætokenæ¾å°åèªçcookieä¸äºï¼èä¸4个系ç»é½æ¯è·¨åçï¼æä»¥cookieå¨è¿å个系ç»é´æ¯ä¸å¯å ±äº«çï¼æä»¥å·²ç»è¾¾å°è·¨åç»ä¸ç»å½äºãå¦ä½å®ç°çï¼ï¼æä»¬å ççæµç¨å¾åä½çå®å¦æç宿µç¨å¾è¿ä¸æ¯å¾æ¸ æ°ï¼ä¸å¬æåæï¼å½æä»¬ç¬¬ä¸æ¬¡è®¿é®web1ç³»ç»æ¶ï¼æªç»å½ç¶æï¼å ¶ä»webç³»ç»ä¹æªç»å½è¿ï¼ï¼æ¤æ¶ç»è¿è¿æ»¤å¨ï¼tokenï¼actionå½ç¶ä¸ºnullï¼å°±ä¼æ¥æ¾cookieæ¯å¦åå¨tokenï¼ä¸è¿æ¯å¦åå¾é½æè¿ä¸ªtokenæ¿å°ç¨æ·ä¸å¿å»æ ¡éªï¼ç¬¬ä¸æ¬¡è¯å®æ¿ä¸å°ï¼æä»¥æ ¡éªå¤±è´¥ï¼efftokenæætoken为空ï¼éå®åå°ç¨æ·ä¸å¿ï¼éå®åç±æµè§å¨éæ°ååºå¯ä»¥è·åå°ç¨æ·ä¸å¿çcookieï¼è·åcookieä¸çtokenï¼tokenå»å°SSOæ ¡éªæ¯å¦å¤±æï¼ç¬¬ä¸æ¬¡è®¿é®æä»¥token为空失æï¼è¿åtokenï¼éå®ååweb1ç³»ç»ï¼æ¤æ¶å¾å¸¦ä¸åæ°ï¼è¿åçtoken å actioncallback(ç¨ä»¥æ è¯æ¯ç¨æ·ä¸å¿éå®å忥çï¼é¿å 夿¬¡éå®å)ï¼ï¼å°è¿é就宿äºä¸æ¬¡è¯¢é®ï¼åå¦ä¸ç´æªç»å½ï¼æ¯æ¬¡è®¿é®web1ç³»ç»é½ä¼å»ç¨æ·ä¸å¿è¯¢é®æ¯å¦æå«çç³»ç»ç»å½è¿åï¼æå°±è¿åæætokenæ¾å ¥web1ç³»ç»çsessionåcookieä¸ï¼é£ä¹ä¸æ¬¡è®¿é®å°±æ¿çè¿ä¸ªtokenå»ç¨æ·ä¸å¿æ ¡éªå¤ææ¯å¦å¤±æã彿们å»å°ç¨æ·ä¸å¿ç»å½äºçætokenï¼token伿¾å ¥ç¨æ·ä¸å¿çcookieä¸ï¼ç¶åéå®ååweb1ç³»ç»ï¼ç»è¿è¿æ»¤å¨æ¶æ§è¡ä¸è¿°æ¥éª¤ä¾¿å¯ä»¥æ¿å°ç¨æ·ä¸å¿çæætokenãå ¶ä¸ä»»ä½ä¸ä¸ªç³»ç»ç»åºé½ä¼è°ç¨ç¨æ·ä¸å¿åç¹ç»åºï¼æ¤æ¶token失æï¼å ¶ä»ç³»ç»åæ¬¡è®¿é®æ¶å°±ä¼åæ¬¡è¯¢é®æ¯å¦å¤±æï¼å¤±ææ¸ 空cookieï¼è¿æ ·å°±å®æç»ä¸ç»åºå¦ãå ¶ä»ç³»ç»åç乿¯å¦æ¤ãè¿ä¹è¿åå¨ä¸ä¸ªå°é®é¢å°±æ¯å½ä»ç¨æ·ä¸å¿è¯¢é®åç°æ²¡æç»å½è¿ï¼å¸¦åæ°éå®ååweb1ç³»ç»ï¼æµè§å¨ä¸çurlä¼å ä¸åæ° ?tokenactioncallbackï¼å½æä»¬åªæ¯å·æ°é¡µé¢æ²¡æå ¶ä»æä½ï¼æ¤æ¶è¿æ»¤å¨ä¸actionå¼ä¸ºcallbackä¼è·³è¿å°ç¨æ·ä¸å¿ç询é®ï¼ètokenæ¯å¤±æçæªç»å½ç¶æï¼æä»¥çç¹å»é¡µé¢å·æ°ï¼è¿ä¸ªé®é¢å¤§å®¶å¦ææ³ç好çè§£å³åæ³å¯ä»¥åè¯æä¸ä¸ã主è¦ä»£ç ï¼webç³»ç»ï¼Login.javaRequestMapping(/login)public void login(HttpServletRequest request, HttpServletResponse response){try {//è·åä¸ä¸ä¸ªURLå°åString previousUrl request.getHeader(Referer).toString();response.sendRedirect(LOGIN_URLpreviousUrl);}catch (IOException e) {e.printStackTrace();}}ç»ä¸ç»å½è¿æ»¤å¨public class UnifiedLoginFilter extends OncePerRequestFilter {Value(${tokenExpired.url})private String TOKENEXPIRED_URL;Value(${userCenterToken.url})private String USERCENTERTOKEN_URL;private final static String ACTION_NAME callback;Autowiredprivate UserService userService;Overrideprotected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)throws ServletException, IOException {String action ServletRequestUtils.getStringParameter(request, action, null);HttpSession session request.getSession();String currentUrl request.getRequestURL().toString();//è·åç¨æ·ä¸å¿æætokenString effectiveToken null;String currentToken null;boolean doFilter true;if(ACTION_NAME.equals(action)) {effectiveToken ServletRequestUtils.getStringParameter(request, token, null);} else {currentToken (String) session.getAttribute(SystemConfig.SESSION_TOKEN_KEY);Cookie[] cookies request.getCookies();if (StringUtils.isBlank(currentToken) cookies ! null) {for (int i 0; i cookies.length; i) {Cookie cookie cookies[i];if (cookie ! null SystemConfig.COOKIE_TOKEN_NAME.equals(cookie.getName())) {currentToken cookie.getValue();break;}}}String result HttpUtil.doGet4Json(TOKENEXPIRED_URLcurrentToken);if(StringUtils.isNotBlank(result)) {JSONObject object JSONObject.parseObject(result);effectiveToken object.getString(data);if(StringUtils.isBlank(effectiveToken)) {doFilter false;response.sendRedirect(USERCENTERTOKEN_URLcurrentUrl);}}}if(doFilter) {//ç¨æ·ä¸å¿tokenææif(StringUtils.isNotBlank(effectiveToken)) {if(effectiveToken.equals(currentToken)) {//å½åç³»ç»tokenææï¼ætokenåå ¥sessionsession.setAttribute(SystemConfig.SESSION_TOKEN_KEY, effectiveToken);} else {//å½åç³»ç»token失æï¼æ´æ°tokensetCookie(effectiveToken, request, response);}}//ç¨æ·ä¸å¿token失æelse {removeCookie(request, response);}//éå®å廿urlå°ååæ°if(ACTION_NAME.equals(action) StringUtils.isNotBlank(effectiveToken)) {response.sendRedirect(currentUrl);} else {filterChain.doFilter(request, response);}}}}è¿æ»¤å¨é ç½®web.xmlunifiedLoginFilterorg.springframework.web.filter.DelegatingFilterProxyunifiedLoginFilter/*使ç¨DelegatingFilterProxy代çè¿æ»¤å¨ï¼å¯ä»¥è®©Spring管ç被代ççè¿æ»¤å¨ï¼è¿æ ·å°±å¯ä»¥å¨è¿æ»¤å¨ä¸è®¿é®Spring容å¨ä¸çbeanï¼å±æ§çãç¨æ·ä¸å¿ï¼tokenæ ¡éª UserInfo.javaApiOperation(value éå®åè·åç¨æ·ä¸å¿Token)ApiImplicitParam(name redirectUrl, value åè°å°å, required true, dataType String, paramType query)RequestMapping(value /userCenterToken, method RequestMethod.GET)public void userCenterToken(HttpServletRequest request, HttpServletResponse response) {String redirectUrl ServletRequestUtils.getStringParameter(request, redirectUrl, null);String schoolId this.getSchoolId(request);String token null;Cookie[] cookies request.getCookies();if(null ! cookies) {for (int i 0; i cookies.length; i) {Cookie cookie cookies[i];if (cookie ! null config.getCookieTokenName().equals(cookie.getName())) {token cookie.getValue();break;}}}try {String effectiveToken getEffectiveToken(token,schoolId);response.sendRedirect(redirectUrl?tokeneffectiveTokenactioncallback);} catch (Exception e) {TRACER.error(, e);e.printStackTrace();}}ApiOperation(value æ ¡éªTokenæ¯å¦å¤±æ)ApiImplicitParam(name token, value ç¨æ· Token, required true, dataType String, paramType query)RequestMapping(value /tokenExpired, method RequestMethod.GET)ResponseBodypublic ResponseEntity tokenExpired(HttpServletRequest request, HttpServletResponse response) {try {String token ServletRequestUtils.getStringParameter(request, token, null);String schoolId this.getSchoolId(request);String effectiveToken getEffectiveToken(token,schoolId);return this.success(effectiveToken);} catch (Throwable t) {TRACER.error(, t);return this.fail(TransactionStatus.INTERNAL_SERVER_ERROR);}}private String getEffectiveToken(String token, String schoolId) throws Exception {String effectiveToken ;HashMap map new HashMap(1);map.put(token, token);HttpPlainResult result httpConnManager.invoke(HttpMethod.GET, config.getSsoHost()/inner/tokenExpired, map,schoolId);TRACER.info(result.getResult());HttpResultDetail entry HttpResultHandler.handle(result, TokenStatus.class);if (entry.isOK()) {TokenStatus tokenStatus entry.getResult();if (!tokenStatus.getExpired()) {effectiveToken token;}}return effectiveToken;}ç»ä¸ç»å½ Login.javaHttpPlainResult result httpConnManager.invoke(HttpMethod.POST, config.getSsoHost() â/inner/loginâ, map, schoolId);TRACER.info(result.getResult());HttpResultDetail entry ââHttpResultHandler.handle(result,Token.class);if(entry.isOK()){ClientTypeEnum clientTypeEnum ClientTypeEnum.convertString2ClientType(clientType);if(clientTypeEnum ClientTypeEnum.WEB){String token entry.getResult().getToken();Cookie token_cookie new Cookie(config.getCookieTokenName(),token);token_cookie.setMaxAge(config.getCookieTokenTimeout());token_cookie.setDomain(request.getHeader(Host).split(:)[0]);response.addCookie(token_cookie);return this.success(redirectUrl,token_cookie);}else{return this.success(entry.getResult(), entry.getResponseStatus());}}else if(entry.isClientError()){return this.error(entry.getResponseMessage(), entry.getResponseStatus());}else if(entry.isServerError()){return thââis.fail(entry.getResponseMessage(), entry.getResponseStatus());}ç»ä¸ç»åº Logout.javaHttpPlainResult result httpConnManager.invoke(HttpMethod.POST, config.getSsoHost()â/inner/logoutâ, map,schoolId);TRACER.info(result.getResult());HttpResultDetail entry HttpResultHandler.handle(result,String.class);if(entry.isOK()){Cookie token_cookie new Cookie(config.getCookieTokenName(),null);token_cookie.setMaxAge(0);token_cookie.setDomain(request.getHeader(âHostâ).split(â:â)[0]);response.addCookie(token_cookie);return this.success(entry.getResult(), entry.getResponseStatus());}else if(entry.isClientError()){return this.error(entry.getResponseMessage(), entry.getResponseStatus());}else if(entry.isServerError()){return this.fail(entry.getResponseMessage(), entry.getResponseStatus());}作者molashaonian