一、实现原理
本单点登录原理是基于SpringBoot的HandlerInterceptor拦截器实现的,大致思路如下:
SP提供单点登录接口,并通过HandlerInterceptor对该地址进行拦截。统一平台访问该SP时携带认证Token信息,HandlerInterceptor向IDP验证Token的合法性,验证通过后进入SP单点登录接口处理,验证失败跳转到统一登录地址。
拦截器在单点登录集成的Jar包中实现,SP只需在项目中引入Jar包并实现单点登录接口处理即可。
二、单点登录集成Jar实现
1、sso配置文件
/**
* sso配置文件
*
* @author sunyp
*/
@Component
@ConfigurationProperties(prefix = "sso") // 配置文件中的前缀
@Getter
@Setter
public class SSOConfig {
//SP单点登录地址
private String loginPath;
//IDP认证地址
private String server;
}
2、拦截器配置
/**
* 单点登录拦截器配置
*/
@Configuration
@Getter
@Setter
public class SSOInterceptorConfig implements WebMvcConfigurer {
@Autowired
private SSOConfig config;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(ssoAuthenticationInterceptor())
.addPathPatterns(config.getLoginPath());
}
@Bean
public SSOAuthenticationInterceptor ssoAuthenticationInterceptor() {
return new SSOAuthenticationInterceptor();
}
}
3、拦截器实现
/**
* 单点登录拦截器
*/
@Getter
@Setter
public class SSOAuthenticationInterceptor implements HandlerInterceptor {
@Autowired
private SSOConfig config;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object object) throws Exception {
//从参数中取出统一系统登录成功的token
String token = request.getParameter("token");
if (StringUtil.isEmpty(token)) {
//没有token直接转到统一登录地址,默认会跳转到登录页
response.sendRedirect(config.getServer());
return false;
}
//去IDP验证token的合法性,合法会返回用户信息
String result = HttpClientUtils.get(config.getServer() + "/sso/auth?token=" + token);
if (result.equals("")) {
response.sendRedirect(config.getServer());
return false;
}
try {
JSONObject jsonObject = JSONObject.parseObject(result);
if (jsonObject.getInteger("code") != 200) {
response.sendRedirect(config.getServer());
return false;
}
JSONObject data = jsonObject.getJSONObject("data");
if (!data.getBoolean("status")) {
response.sendRedirect(config.getServer());
return false;
}
request.setAttribute("loginName", data.getString("loginName"));
request.setAttribute("userName", data.getString("userName"));
return true;
} catch (Exception e) {
response.sendRedirect(config.getServer());
return false;
}
}
@Override
public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
}
@Override
public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
}
}
三、SP端代码
1、单点登录处理
/**
* 单点登录处理
*/
@Controller
@RequestMapping(value = "service/sso")
public class SSOLogin {
@RequestMapping()
@PassToken
public void login(HttpServletRequest request, HttpServletResponse response) throws IOException {
//单点登录成功后会进入此方法内部,可以从request中获取loginName和userName;
String loginName = request.getAttribute("loginName").toString();
String userName = request.getAttribute("userName").toString();
//TODO 进行本地化权限处理
//跳转到系统首页
response.sendRedirect("/");
}
}
2、配置文件
sso:
loginPath: /service/sso #单点登录接口
server: http://192.168.34.110:8080/ #IDP地址