SSO单点登录实例
单点登录流程图

系统登陆拦截器
//
// 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";
}
}

浙公网安备 33010602011771号