SSO简介
SSO英文全称Single Sign On,单点登录。SSO是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统。它包括可以将这次主要的登录映射到其他应用中用于同一个用户的登录的机制。
话不多说,先看看今天实现一个简单的SSO的原理流程图:
整个项目工程:
简单说明下:SSO为a,b两个系统的统一认证中心,其中SSO,a和b系统均不在同一个域名内,前端跨域需要jsonp处理,后端需要进行跨域处理。
/**
* @Title: CORSConfiguration
* @Description: 解决跨域问题的配置
* @author: youqing
* @version: 1.0
* @date: 2018/12/4 16:39
*/
@Configuration
public class CORSConfiguration extends WebMvcConfigurerAdapter {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
.allowedMethods("GET", "HEAD", "POST", "PUT", "DELETE", "OPTIONS")
.allowCredentials(false)
.maxAge(3600);
}
}
SSO认证实现
主要实现三点:
- 进行账号登入,登录后,对旗下管理的子系统进行对应的token赋予操作。
- 检查相关子系统的token检验工作。
- 账号从一端进行退出操作以后,清除子系统所保留的相应的token。
@RequestMapping("sso")
public class LoginController {
/**
*
* 功能描述: 登入系统
*
* @param:
* @return:
* @auther: youqing
* @date: 2018/12/29 14:46
*/
@PostMapping("login")
public ResultData login(String loginName, String password){
Map<String,Object> data = new HashMap<>();
if(StringUtils.isEmpty(loginName)){
return ResultData.fail("001","登录名为空!");
}
if(StringUtils.isEmpty(password)){
return ResultData.fail("001","登录密码为空!");
}
if(loginName.equals("admin") && password.equals("123456")){
data.put("loginName",loginName);
data.put("token","123");
List<String> urls = new ArrayList<>();
urls.add("http://a.com:9091/addCookie");
urls.add("http://b.com:9092/addCookie");
data.put("urls",urls);
return ResultData.success("1","登入成功!").with(data);
}
return ResultData.fail("001","登录名或登录密码错误!");
}
/**
*
* 功能描述: 通过token检验是否登入
*
* @param:
* @return:
* @auther: youqing
* @date: 2018/12/29 14:46
*/
@GetMapping("checkToken")
public ResultData checkToken(HttpServletRequest request){
String token = request.getHeader("token");
Map<String,Object> data = new HashMap<>();
if(StringUtils.isEmpty(token)){
return ResultData.fail("003","token为空!");
}
if(token.equals("123")){
data.put("loginName","admin");
return ResultData.success("1","登入成功!").with(data);
}
return ResultData.fail("003","token失效!");
}
/**
*
* 功能描述: 退出系统
*
* @param:
* @return:
* @auther: youqing
* @date: 2018/12/29 14:45
*/
@GetMapping("logout")
public ResultData logout(){
Map<String,Object> data = new HashMap<>();
List<String> urls = new ArrayList<>();
//清除子系统的cookie
urls.add("http://a.com:9091/clearCookie");
urls.add("http://b.com:9092/clearCookie");
data.put("urls",urls);
return ResultData.success("1","退出成功!").with(data);
}
}
子系统认证实现
子系统的操作都是一致的
- 进行登录操作事,请求SSO的认证登录操作
- 将token添加到本系统的cookie中
- 将token从本系统的cookie中清除
/**
*
* 功能描述: 进行登入
*
* @param:
* @return:
* @auther: youqing
* @date: 2018/12/29 14:55
*/
@PostMapping("toLogin")
@ResponseBody
public ResultData toLogin(@RequestBody User user){
ResultData resultData = new ResultData();
Map<String, String> param = new HashMap<>();
String result = null;
param.put("loginName",user.getLoginName());
param.put("password",user.getPassword());
result = HttpUtil.doPost("http://sso-server.com:9090/sso/login",param);
resultData = JSON.parseObject(result,ResultData.class);
return resultData;
}
/**
*
* 功能描述: 添加cookie
*
* @param:
* @return:
* @auther: youqing
* @date: 2018/12/29 14:55
*/
@GetMapping("/addCookie")
public void addCookie (String token, HttpServletResponse response) {
log.info("添加cookie");
Cookie cookie = new Cookie("token",token);
cookie.setPath("/");
cookie.setMaxAge(3600);
response.addCookie(cookie);
}
/**
*
* 功能描述: 清除cookie
*
* @param:
* @return:
* @auther: youqing
* @date: 2018/12/29 14:55
*/
@GetMapping("/clearCookie")
public void clearCookie (HttpServletRequest request, HttpServletResponse response) {
log.info("清除cookie");
Cookie[] cookies = request.getCookies();
for (Cookie cookie : cookies) {
cookie.setMaxAge(0);
cookie.setPath("/");
response.addCookie(cookie);
}
}