單點登陸流程圖html
系統登錄攔截器前端
// // Source code recreated from a .class file by IntelliJ IDEA // (powered by Fernflower decompiler) // package com.jdcloud.policycloudapi.sso; import com.alibaba.fastjson.JSON; import com.jdcloud.policycloudapi.domain.response.RetResponse; import com.jdcloud.policycloudapi.domain.vo.LoginUser; import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; public class SsoClientInterceptor implements HandlerInterceptor { private Logger log = LoggerFactory.getLogger(this.getClass()); private SsoProperties ssoProperties; private RemoteService remoteService; public SsoClientInterceptor(SsoProperties ssoProperties, RemoteService remoteService) { this.ssoProperties = ssoProperties; this.remoteService = remoteService; } public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws IOException { String tokenParam = null; Cookie[] cookies = request.getCookies(); if (cookies != null) { for(int i = 0; i < cookies.length; ++i) { if (cookies[i].getName().equals("gunsToken")) { tokenParam = cookies[i].getValue(); break; } } } if(!StringUtils.isNotBlank(tokenParam)){ tokenParam=request.getParameter("gunsToken"); } if (StringUtils.isNotBlank(tokenParam)) { //驗證tokenParam是否正確 Integer userId = this.remoteService.validateToken(tokenParam, HttpUtil.getRequestContextPath(request)); if (userId != null) { request.setAttribute("SESSION_LOGIN_FLAG", tokenParam); // 調用接口獲取user,以及user權限列表 LoginUser loginUser=remoteService.getLoginUser(userId,tokenParam); // log.info("loginUser:"+ JSON.toJSONString(loginUser)); // RestTemplateUtils restTemplateUtils=new RestTemplateUtils(); // LoginUser loginUser = restTemplateUtils.getLoginUser(tokenParam); request.setAttribute(SsoConstants.LOGIN_USER_SESSION, loginUser); return true; } else { // this.redirectSsoServer(request, response); return responseFalse(response); } } else { // this.redirectSsoServer(request, response); return responseFalse(response); } // return true; } private boolean responseFalse(HttpServletResponse response) throws IOException { response.setCharacterEncoding("UTF-8"); response.setContentType("application/json; charset=utf-8"); PrintWriter out = null; out = response.getWriter(); out.write(JSON.toJSONString(RetResponse.retFail())); out.flush(); out.close(); return false; } private void redirectSsoServer(HttpServletRequest request, HttpServletResponse response) { String redirectUrl = this.ssoProperties.getServerUrl() + "?" + "redirectUrl" + "=" + HttpUtil.encodeUrl(HttpUtil.getRequestFullPathNoParam(request)); try { response.sendRedirect(redirectUrl); } catch (IOException var5) { this.log.error("跳轉到服務器出錯!", var5); } } public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { } public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { } }
SSO服務器登陸驗證代碼java
package com.stylefeng.sso.server.modular.controller; import com.stylefeng.guns.core.base.controller.BaseController; import com.stylefeng.guns.core.util.ToolUtil; import com.stylefeng.sso.plugin.constants.SsoConstants; import com.stylefeng.sso.plugin.service.AuthService; import com.stylefeng.sso.server.common.Rests; import com.stylefeng.sso.server.modular.entity.SysUser; import com.stylefeng.sso.server.modular.service.SysUserService; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.ResponseBody; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import static com.stylefeng.sso.plugin.constants.SsoConstants.LOGOUT_URL; /** * 登陸驗證控制器 * * @author stylefeng * @Date 2018/2/3 22:23 */ @Controller @Slf4j public class AuthController extends BaseController { private static final String LOGIN_TIPS = "tips"; @Autowired AuthService authService; @Autowired private SysUserService sysUserService; private boolean isMobile(HttpServletRequest request) { String userAgent = request.getHeader("User-Agent"); userAgent = userAgent.toLowerCase(); if (userAgent.contains("iphone") || userAgent.contains("android") || userAgent.contains("ipad") || userAgent.contains("ipod")) { return true; } return false; } @RequestMapping (value = "/login", method = RequestMethod.GET) public String toLogin(HttpServletRequest request) { return isMobile(request)? "/login_m.html" : "/login.html"; } @Value ("${spring.profiles.active}") private String profile; @RequestMapping (value = "/login", method = RequestMethod.POST) public String doLogin(HttpServletRequest request, HttpServletResponse response, Model model) { String returnUrl = isMobile(request)? "/login_m.html" : "/login.html"; String tokenParam = null; Cookie[] cookies = request.getCookies(); if (cookies != null) { for (int i = 0; i < cookies.length; i++) { if (cookies[i].getName().equals("gunsToken")) { tokenParam = cookies[i].getValue(); break; } } } String redirectUrl = request.getParameter(SsoConstants.REDIRECT_PARAM_NAME); // 若是cookie中能取到token,則認爲從其餘頁面登陸,不繼續登陸流程,跳回原地址 // if (StringUtils.isNotBlank(tokenParam) && StringUtils.isNotBlank(redirectUrl)){ // log.info("用戶已經處於登陸狀態,不繼續登陸流程,跳回原地址: {}", redirectUrl); // try { // response.sendRedirect(redirectUrl); // return null; // } catch (IOException e) { // log.warn("已經登陸,跳回原地址失敗", e); // model.addAttribute(LOGIN_TIPS, "網絡異常!"); // return "/login.html"; // } // } String userName = request.getParameter("userName"); String password = request.getParameter("password"); // 登陸失敗是記錄redirectUrl model.addAttribute(SsoConstants.REDIRECT_PARAM_NAME, redirectUrl); if (ToolUtil.isEmpty(userName) || ToolUtil.isEmpty(password) || ToolUtil.isEmpty(redirectUrl)) { model.addAttribute(LOGIN_TIPS, "請求信息不完整!"); return returnUrl; } else { /** * 判斷用戶帳號密碼是否正確 */ Integer userId = authService.checkUserLogin(userName, password); if (userId != null) { //若是帳號密碼正確,跳轉回業務系統的url String token = ""; try { /*SysUser sysUser = sysUserService.getSysUser(userId); sysUserService.insertLoginUserIntoRedisDto(sysUser, token);*/ token = authService.createToken(userId); } catch (Exception e) { log.warn("createToken失敗",e); model.addAttribute(LOGIN_TIPS, "登陸失敗,請稍後再試!"); return returnUrl; } if (profile.equals("dev")) { Cookie localhost = new Cookie(SsoConstants.TOKEN_PARAM_NAME, token); localhost.setDomain("jdcloud.com"); localhost.setPath("/"); localhost.setMaxAge(36000); response.addCookie(localhost); } else { Cookie cookie = new Cookie(SsoConstants.TOKEN_PARAM_NAME, token); cookie.setPath("/"); response.addCookie(cookie); } try { // String redirect=redirectUrl+"?"+SsoConstants.TOKEN_PARAM_NAME + "=" + token; // response.sendRedirect(redirectUrl /*+ "?" + SsoConstants.TOKEN_PARAM_NAME + "=" + token*/); response.sendRedirect(redirectUrl); return null; } catch (IOException e) { model.addAttribute(LOGIN_TIPS, "網絡異常!"); return returnUrl; } } else { //若是帳號密碼錯誤 model.addAttribute(LOGIN_TIPS, "帳號或密碼錯誤!"); return returnUrl; } } } @ResponseBody @RequestMapping ("/hello") public String token() { return "暫未登陸"; } @RequestMapping (LOGOUT_URL) public String logout(HttpServletRequest request, HttpServletResponse response, Model model) { String tokenParam = null; Cookie[] cookies = request.getCookies(); if (cookies != null) { for (int i = 0; i < cookies.length; i++) { if (cookies[i].getName().equals("gunsToken")) { tokenParam = cookies[i].getValue(); break; } } } String redirectUrl = request.getParameter(SsoConstants.REDIRECT_PARAM_NAME); if (StringUtils.isNotBlank(tokenParam)){ // 刪除redis中保存的token,若是失敗,不容許退出登陸,跳回源地址 if (!authService.removeCachedToken(tokenParam)) { try { redirectUrl = redirectUrl + "?status="+SsoConstants.LOGIN_FAILED_FLAG+"?gunsToken"+tokenParam; response.sendRedirect(redirectUrl); return null; } catch (Exception e) { log.error("重定向失敗", e); return "/404.html"; } } } // 刪除cookie // 開發環境爲了方便前端本地測試配置域名hosts,cookie選擇種到二級域下;線上環境域名一致,cookie種到默認的domain下 if (profile.equals("dev")) { Cookie localhost = new Cookie(SsoConstants.TOKEN_PARAM_NAME, null); localhost.setPath("/"); localhost.setMaxAge(0); response.addCookie(localhost); } else { Cookie newCookie = new Cookie(SsoConstants.TOKEN_PARAM_NAME, null); //假如要刪除名稱爲username的Cookie newCookie.setMaxAge(0); //當即刪除型 newCookie.setPath("/"); //項目全部目錄均有效,這句很關鍵,不然不敢保證刪除 response.addCookie(newCookie); //從新寫入,將覆蓋以前的 } //跳轉到登陸頁面 model.addAttribute(SsoConstants.REDIRECT_PARAM_NAME, redirectUrl); return isMobile(request)? "/login_m.html" : "/login.html"; } }