什么是单点登录?回顾单系统登录
一、什么是单点登录?
单点登录的英文名叫做:Single Sign On(简称SSO)。
(资料图)
在初学/以前的时候,一般我们就单系统,所有的功能都在同一个系统上。
所有的功能都在同一个系统上
后来,我们为了合理利用资源和降低耦合性,于是把单系统拆分成多个子系统。
拆分成多个子系统
比如阿里系的淘宝和天猫,很明显地我们可以知道这是两个系统,但是你在使用的时候,登录了天猫,淘宝也会自动登录。
登录了天猫,淘宝也登录了
简单来说,单点登录就是在多个系统中,用户只需一次登录,各个系统即可感知该用户已经登录。
二、回顾单系统登录
在我初学JavaWeb的时候,登录和注册是我做得最多的一个功能了(初学Servlet的时候做过、学SpringMVC的时候做过、跟着做项目的时候做过…),反正我也数不清我做了多少次登录和注册的功能了…这里简单讲述一下我们初学时是怎么做登录功能的。
众所周知,HTTP是无状态的协议,这意味着服务器无法确认用户的信息。于是乎,W3C就提出了:给每一个用户都发一个通行证,无论谁访问的时候都需要携带通行证,这样服务器就可以从通行证上确认用户的信息。通行证就是Cookie。
如果说Cookie是检查用户身上的”通行证“来确认用户的身份,那么Session就是通过检查服务器上的”客户明细表“来确认用户的身份的。Session相当于在服务器中建立了一份“客户明细表”。
HTTP协议是无状态的,Session不能依据HTTP连接来判断是否为同一个用户。于是乎:服务器向用户浏览器发送了一个名为JESSIONID的Cookie,它的值是Session的id值。其实Session是依据Cookie来识别是否是同一个用户。
所以,一般我们单系统实现登录会这样做:
登录
将用户信息保存在Session对象中
如果在Session对象中能查到,说明已经登录
如果在Session对象中查不到,说明没登录(或者已经退出了登录)
注销(退出登录)
从Session中删除用户的信息
记住我
(关闭掉浏览器后,重新打开浏览器还能保持登录状态)配合Cookie来用
我之前Demo的代码,可以参考一下:
/** * 用户登陆 */@PostMapping(value = "/user/session", produces = {"application/json;charset=UTF-8"})public Result login(String mobileNo, String password, String inputCaptcha, HttpSession session, HttpServletResponse response) { //判断验证码是否正确 if (WebUtils.validateCaptcha(inputCaptcha, "captcha", session)) { //判断有没有该用户 User user = userService.userLogin(mobileNo, password); if (user != null) { /*设置自动登陆,一个星期. 将token保存在数据库中*/ String loginToken = WebUtils.md5(new Date().toString() + session.getId()); user.setLoginToken(loginToken); User user1 = userService.userUpload(user); session.setAttribute("user", user1); CookieUtil.addCookie(response,"loginToken",loginToken,604800); return ResultUtil.success(user1); } else { return ResultUtil.error(ResultEnum.LOGIN_ERROR); } } else { return ResultUtil.error(ResultEnum.CAPTCHA_ERROR); }}/** * 用户退出 */@DeleteMapping(value = "/session", produces = {"application/json;charset=UTF-8"})public Result logout(HttpSession session,HttpServletRequest request,HttpServletResponse response ) { //删除session和cookie session.removeAttribute("user"); CookieUtil.clearCookie(request, response, "loginToken"); return ResultUtil.success();}/*** @author ozc* @version 1.0* * 拦截器;实现自动登陆功能*/public class UserInterceptor implements HandlerInterceptor {@Autowiredprivate UserService userService;public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object o) throws Exception { User sessionUser = (User) request.getSession().getAttribute("user"); // 已经登陆了,放行 if (sessionUser != null) { return true; } else { //得到带过来cookie是否存在 String loginToken = CookieUtil.findCookieByName(request, "loginToken"); if (StringUtils.isNotBlank(loginToken)) { //到数据库查询有没有该Cookie User user = userService.findUserByLoginToken(loginToken); if (user != null) { request.getSession().setAttribute("user", user); return true; } else { //没有该Cookie与之对应的用户(Cookie不匹配) CookieUtil.clearCookie(request, response, "loginToken"); return false; } } else { //没有cookie、也没有登陆。是index请求获取用户信息,可以放行 if (request.getRequestURI().contains("session")) { return true; } //没有cookie凭证 response.sendRedirect("/login.html"); return false; } }}}
总结一下上面代码的思路:
用户登录时,验证用户的账户和密码
生成一个Token保存在数据库中,将Token写到Cookie中
将用户数据保存在Session中
请求时都会带上Cookie,检查有没有登录,如果已经登录则放行
三、多系统登录的问题与解决
3.1 Session不共享问题
单系统登录功能主要是用Session保存用户信息来实现的,但我们清楚的是:多系统即可能有多个Tomcat,而Session是依赖当前系统的Tomcat,所以系统A的Session和系统B的Session是不共享的。
系统A的Session和系统B的Session是不共享的
解决系统之间Session不共享问题有一下几种方案:
Tomcat集群Session全局复制(集群内每个tomcat的session完全同步)【会影响集群的性能呢,不建议】
根据请求的IP进行Hash映射到对应的机器上(这就相当于请求的IP一直会访问同一个服务器)【如果服务器宕机了,会丢失了一大部分Session的数据,不建议】
把Session数据放在Redis中(使用Redis模拟Session)【建议】
我们可以将登录功能单独抽取出来,做成一个子系统。
抽取出来成为子系统
SSO(登录系统)的逻辑如下:
// 登录功能(SSO单独的服务)@Overridepublic TaotaoResult login(String username, String password) throws Exception { //根据用户名查询用户信息 TbUserExample example = new TbUserExample(); Criteria criteria = example.createCriteria(); criteria.andUsernameEqualTo(username); List list = userMapper.selectByExample(example); if (null == list || list.isEmpty()) { return TaotaoResult.build(400, "用户不存在"); } //核对密码 TbUser user = list.get(0); if (!DigestUtils.md5DigestAsHex(password.getBytes()).equals(user.getPassword())) { return TaotaoResult.build(400, "密码错误"); } //登录成功,把用户信息写入redis //生成一个用户token String token = UUID.randomUUID().toString(); jedisCluster.set(USER_TOKEN_KEY + ":" + token, JsonUtils.objectToJson(user)); //设置session过期时间 jedisCluster.expire(USER_TOKEN_KEY + ":" + token, SESSION_EXPIRE_TIME); return TaotaoResult.ok(token);}
其他子系统登录时,请求SSO(登录系统)进行登录,将返回的token写到Cookie中,下次访问时则把Cookie带上:
public TaotaoResult login(String username, String password, HttpServletRequest request, HttpServletResponse response) { //请求参数 Map param = new HashMap<>(); param.put("username", username); param.put("password", password); //登录处理 String stringResult = HttpClientUtil.doPost(REGISTER_USER_URL + USER_LOGIN_URL, param); TaotaoResult result = TaotaoResult.format(stringResult); //登录出错 if (result.getStatus() != 200) { return result; } //登录成功后把取token信息,并写入cookie String token = (String) result.getData(); //写入cookie CookieUtils.setCookie(request, response, "TT_TOKEN", token); //返回成功 return result;}
总结:
SSO系统生成一个token,并将用户信息存到Redis中,并设置过期时间
其他系统请求SSO系统进行登录,得到SSO返回的token,写到Cookie中
每次请求时,Cookie都会带上,拦截器得到token,判断是否已经登录
到这里,其实我们会发现其实就两个变化:
将登陆功能抽取为一个系统(SSO),其他系统请求SSO进行登录
本来将用户信息存到Session,现在将用户信息存到Redis
3.2 Cookie跨域的问题
上面我们解决了Session不能共享的问题,但其实还有另一个问题。Cookie是不能跨域的
比如说,我们请求时,浏览器会自动把google.com的Cookie带过去给google的服务器,而不会把的Cookie带过去给google的服务器。
这就意味着,由于域名不同,用户向系统A登录后,系统A返回给浏览器的Cookie,用户再请求系统B的时候不会将系统A的Cookie带过去。
针对Cookie存在跨域问题,有几种解决方案:
服务端将Cookie写到客户端后,客户端对Cookie进行解析,将Token解析出来,此后请求都把这个Token带上就行了
多个域名共享Cookie,在写到客户端的时候设置Cookie的domain。
将Token保存在SessionStroage中(不依赖Cookie就没有跨域的问题了)
到这里,我们已经可以实现单点登录了。
3.3 CAS原理
说到单点登录,就肯定会见到这个名词:CAS (Central Authentication Service),下面说说CAS是怎么搞的。
如果已经将登录单独抽取成系统出来,我们还能这样玩。现在我们有两个系统,分别是www.java3y.com和www.java4y.com,一个SSOwww.sso.com
现在我们有三个系统
首先,用户想要访问系统Awww.java3y.com受限的资源(比如说购物车功能,购物车功能需要登录后才能访问),系统Awww.java3y.com发现用户并没有登录,于是重定向到sso认证中心,并将自己的地址作为参数。
sso认证中心发现用户未登录,将用户引导至登录页面,用户进行输入用户名和密码进行登录,用户与认证中心建立全局会话(生成一份Token,写到Cookie中,保存在浏览器上)
4步过程
随后,认证中心重定向回系统A,并把Token携带过去给系统A,
接着,系统A去sso认证中心验证这个Token是否正确,如果正确,则系统A和用户建立局部会话(创建Session)。到此,系统A和用户已经是登录状态了。
第五步和第六步
此时,用户想要访问系统受限的资源(比如说订单功能,订单功能需要登录后才能访问),系统发现用户并没有登录,于是重定向到sso认证中心,并将自己的地址作为参数。
注意,因为之前用户与认证中心已经建立了全局会话(当时已经把Cookie保存到浏览器上了),所以这次系统B重定向到认证中心是可以带上Cookie的。
认证中心根据带过来的Cookie发现已经与用户建立了全局会话了,认证中心重定向回系统B,并把Token携带过去给系统B
接着,系统B去sso认证中心验证这个Token是否正确,如果正确,则系统B和用户建立局部会话(创建Session)。到此,系统B和用户已经是登录状态了。
系统B的流程图
看到这里,其实SSO认证中心就类似一个中转站。
标签:
相关推荐:
最新新闻:
- 简单了解一下FIS yarnglobaladdfis3使用方法|环球今亮点
- 爬虫代码中使用代理ip的方法 代理ip使用原理
- 数据挖掘的过程是什么?有哪些阶段?
- linuxtone日常命令:快速杀掉mysql进程
- windwos7无线打不开怎么办?acer4820tg无线打不开的解决办法|全球播资讯
- community音响怎么样?community音响优势介绍-时讯
- 开源文本编辑器Vim推出新编程语言Zimbu:全球通讯
- 快播怎么用BT种子?快播播放种子的3种方法 全球热文
- 魔兽世界6.2版本宠物对战新内容:塔纳安丛林遍布战斗宠物_每日观点
- 照片和视频拼在一起?快影教你一招|当前热点
- 智能可穿戴设备 智能可穿戴设备未来会怎样?
- 世界今头条!QQ如何登录?腾讯QQ首次登录QQ保障信息安全
- rmvb怎样转mp4?9.30MBVB转MP4转换器_全球动态
- 全球即时:戴尔笔记本电脑怎么样?戴尔笔记本电脑推荐及价格介绍
- 天天滚动:重装系统常见道ghost 如何恢复分区?
- 微信群怎么设置管理员?设置微信管理员的方法:焦点讯息
- 想让你的二次元老婆动起来吗?试试这个神器吧-世界聚焦
- 【进程隐藏之内核】EPROCESSSS结构体
- 为什么应用需要加固?操作步骤是什么?
- 联想G450摄像头不清楚怎么办?解决办法
- 世界动态:如何一次性删除全部页眉页脚?Word中删除全部页眉页脚的方法
- 【世界新视野】博客积分如何计算?CSDN积分规则
- 天天通讯!【Linux操作系统】系统调用和库函数编程基础知识
- 博世壁挂炉怎么样?博世壁挂炉欧洲之星评测
- 什么是单点登录?回顾单系统登录
- 投影仪出租的优势 投影仪出租有哪些注意事项?
- ChatGPT创始人的个性和经历将如何影响它的未来?
- 与哲学僵尸作战
- 即时焦点:天佑武汉 天佑种花家!爬之分析之各省数据入口
- Java程序员面试宝典:100道面试题+答案汇总:全球通讯
- 世界快看:《喋血复仇》内容停更 开发商专注于打造新游戏
- 传真机耗材怎么选购?传真机耗材选购窍门
- 【天天热闻】施耐德空气开关怎么样?施耐德空气开关的型号与价格
- 电脑键盘快捷键有哪些?电脑键盘快捷键和组合键功能使用大全
- My97DatePickerBeta日期控件乱码问题解决办法-天天头条
- 死亡计算机官网在线 死亡计算器软件安装教程-世界速看
- 全球微动态丨360隐私保护器是怎么一回事?全面认识下360隐私保护器
- 小米4怎么样?小米4屏幕尺寸以及评测报价
- 《星际争霸Ⅱ》游戏秘籍:游戏中按回车输入以下秘籍|每日播报
- 世界上最大的会计事务所——Pricewaterhouse
- 天天实时:新买的手机怎么充电?充电时接电话会引起爆炸?
- 今日精选:如何登录Windows弹性云服务器?网吧服务器系统介绍
- 家用净水器过滤方式是什么?家用净水器哪种过滤方式好?:环球热议
- 分享100个有趣的python项目 值得收藏
- Java的类型是什么?byte字节型占一个字节(8bit)的数据范围
- 每日观点:NET是什么?netFramework是一个品牌商标推出的?
- 四年一遇:ngix+rtmp+ffmpeg的直播效果
- 新版《绯闻女孩》被HBO取消 第二季即完结-天天时讯
- 全球看热讯:如何查看8080端口被占用的信息?Linux查看端口占用以及端口详情
- 微资讯!部门组织结构及分工设想——技术总监、技术运维组
- DirectStorage测试显示PCIe3硬盘的速度基本与PCIe 5相同
- 《火星孤征》现已登陆各平台 上市预告片分享:全球观焦点
- 环球热门:《宝可梦朱紫》BUG多帧率不稳 任天堂道歉
- 印度富豪Adani紧急自救!考虑提前偿债、释放股权质押提振信心,高盛称其债券已触底
- 新年新气象 新一代装机配置怎么选?|天天资讯
- 【当前热闻】每日低价硬货:联想12代酷睿主机套装开工季仅需3093元
- EA砍掉《泰坦陨落》后续游戏 员工自谋出路
- 哈曼中国蝉联“中国杰出雇主2023”称号
- 每日信息:【在线观点】集成灶市场品类优势尽显,2023年必将再创发展高增速
- 天天热头条丨北证50指数表现吸睛 主题基金业绩分化
- 每日头条!玩家抱怨《霍格沃茨之遗》魔法数量太少:老头环有上百种
- 科乐美大幅下调财务预计 预期利润近乎减半-当前快报
- 传闻:任天堂新一期直面会将于下周举行
- Epic喜加一:《罪恶之城》《耻辱:界外魔之死》免费领:全球独家
- “我需要的不是一个丈夫,而是妻子”|世界报道
- 今日报丨昔日16冠豪门今降级?免签5欧冠妖人,但求逆天改命,353场110球
- 《雷霆沙赞2》主创集结庆祝定档 3月17日影院见:信息
- 展肖华_展肖华_世界快讯
- Steam 1月硬件调查报告 RTX显卡越来越普及_速讯
- 精彩看点:《死亡空间》之父感谢Motive忠实地重制了游戏
- 环球热推荐:壳牌2022年净利润增长一倍以上,创115年历史新高|财报见闻
- 日本电影的“巨匠”神话是如何诞生的?
- 网飞打击账号共享:仅限家庭使用 严控异地登录-环球观察
- 未来电价存在上涨可能:为什么?怎么涨?谁买单?
- 华软科技大股东一致行动人申得兴投资完成减持22.03万股 全球今头条