1.概念介绍
单点登录SSO(Single Sign On),就是在多系统环境下,用户在其中一个系统登录后,就不用在其它系统再登录了。
早期我们的web系统都是单体应用,所有功能都写到一个war包中,用户登录认证功能处理起来相对比较简单。用户登陆成功后,服务器将用户信息写入到会话中(Session)。会生成 session id来标记这块内存区间是属于你的,并且,这个 session id( jsessionid ) 会写入到你的浏览器 cookie 中,只要你浏览器没关闭,每次向服务器发送请求,服务器就会从你发送过来的 cookie 中去取这个 session id,然后根据这个 session id 到相应的内存中取出你之前存放的数据,但是,如果退出登录。服务器会清除属于你的内存区域,再登录时,重新生成新的 session
但是随着应用的访问量不断扩大,单体应用无法满足应用要求,由此分布式应用应运而生。在分布式应用环境下,当某个子系统访问量增加时,我们会把这个系统同时布署多份。当同一个用户登录成功后,由于Nignx反向代理策略不能保存让这个用户访问到同一个子系统,也就是用户登录成功的session是不能在多个子系统中共享的,从而会导致其登录失败。所以在分布式应用中要解决session的同步问题,这就是单点登录的由来。
说到SSO,我们不得不提JWT。 JWT是一个Token的规范,它本质是一个字符串,常应用于认证授权,单点登录。JWT由三部分构成:header(头部:指定类型和算法)、payload(载荷:存放Claims声明信息)和signature(签名:把前两者对应的Json结构·进行base64url编码之后的字符串拼接起来和密钥放一起加密后的签名组成方式为 header.payload.signature)。JWT一般存放到请求参数的header或cookie中。JWT在信息传递方面更加安全方便,其特点是简洁,紧凑,自包含。Kisso(cookie sso)是基于JWT规范的单点登录中间件,能够快速开发javaweb单点登录登录系统。随着设备的多元化,会出现一个账号在不同的设备上登录,最典型的是微信及QQ,可以在手机上登录也可能在电脑上也登录,我们希望用户在不同设备上登录账号会将之前的账户状态注销,同一时间只有一个用户在线,也称为单设备登录。sa-Token是一个轻量级Java权限认证框架,解决单点登录,多端登录踢人下线等权限相关问题。
2.解决方案
2.1基于kisso的身份认证方案:
用户在登录业务系统的时候,检查本地是否有Cookie,如果没有Cookie,访问SSO项目,SSO也没有Cookie的话。则进行登录。登录成功将加密的Token写入Cookie并回传给业务系统。通过几次的加密认证,双方认证OK后,在业务系统域名下写入Cookie,完成登录。
如何使用:
1.配置信息
# kisso配置SSOConfig
kisso:
config:
signkey: xxxx #对称签名密钥(非必须)
cookieName: token #COOKIE名称
cookieDomain: www.95coder.com # COOKIE域名
2.常用API
public void test(HttpServletRequest request, HttpServletResponse response) throws IOException {
//用户登录代码
SSOToken ssoToken = SSOToken.create();
ssoToken.setIp(request).setId("userId").setIssuer("loginName");//保存登录用户id、账号、IP
int cookieMaxage = SSOConfig.getInstance().getCookieMaxage();
ssoToken.setTime(new Date().getTime()+cookieMaxage*1000);//设置过期时间
SSOHelper.setCookie(request, response, ssoToken, true);//cookie模式登录,写入加密token值
//获取生成的token值,一般用于返回给前端,前端在请求时可存放在header中
String token = ssoToken.getToken();
//用户退出登录代码(清除cookie对应的token信息)
SSOHelper.logout(request, response);
//获取登录用户id, 登录账号
ssoToken = SSOHelper.getSSOToken(request);
String userId = ssoToken.getId();
String loginName = ssoToken.getIssuer();
//判断是否已过期:true是,false否
boolean expireFlag = new Date().getTime() > ssoToken.getTime();
if(expireFlag){
throw new RuntimeException("登录已过期,请重新登录!");
}
//多端登录,调用踢人下线,需要实现SSOCache接口
SSOHelper.kickLogin(userId);
}
2.2 sa-token身份认证方案:
单设备登录只能在一个设备上登录,若同时在其他设备登录,先前登录的用户会被提醒:该账户在其他设备登录。可以通过独立的认证子系统来实现或者使用缓存服务器(redis)来保存所有登录的用户信息来实现。独立的认证子系统要求所有应用系统共享同一个身份认证系统,身份认证系统能对用户登录的认证,并返回识别用户身份的ticket,当用户再次携带ticket登录时,可以识别和提取ticket信息,并判断用户是否在其它设备上已登录。使用缓存服务器时,会把用户的登录认证后的信息缓存到一个公共的缓存服务器上。用户再次登录时都会从缓存中取出ticket来进行识别是否登录或在别的设备已登录。通过sa-token,你可以以一种极简的方式实现系统的权限认证部分
如何使用:
//登录
StpUtil.setLoginId(10001);
//根据账号id踢人
StpUtil.logoutByLoginId(10001);
//根据Token令牌踢人
StpUtil.logoutByTokenValue("xxxx-xxxx-xxxx-xxxx-xxxx");
3.优缺点对比
3.1 基于session的身份认证的缺点:
1). sessions : 每次用户认证通过以后,服务器需要创建一条记录保存用户信息,通常是在内存中,随着认证通过的用户越来越多,服务器的在这里的开销就会越来越大。
2).scalability : 由于Session是在内存中的,这就带来一些扩展性的问题。
3).CORS : 当我们想要扩展我们的应用,让我们的数据被多个移动设备使用时,我们必须考虑跨资源共享问题。当使用AJAX调用从另一个域名下获取资源时,我们可能会遇到禁止请求的问题。
4).CSRF : 用户很容易受到CSRF攻击。
3.2 基于kisso的身份认证的缺点:
优点:提高用户效率,提高开发效,简化管理
缺点:单点登录指在多个应用系统中,用户只需要登陆一次就可以访问相互信任的应用系统,所以这些应用系统要互相兼容,耗时,存在信息泄露的问题
3.3 基于sa-token的身份认证的缺点:
优点:简单,强大,易用,高扩展