單點登錄流程圖

系統登陸攔截器
//
// 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服務器登錄驗證代碼
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";
}
}
