原创: 刘欣 码农翻身 2017-03-20
1
美好的旧时光
我经常怀念三十年前那美好的旧时光, 工作很轻松, 生活很悠闲。
上班的时候偶尔有些HTTP的请求发到我这里, 我简单的看一下, 取出相对应的html文档,图片,发回去就可以了, 然后就可以继续喝茶聊天。
我的创造者们对我很好, 他们制定的一个简单HTTP协议, 就是请求加响应, 尤其是我不用记住是谁刚刚发了HTTP请求, 每个请求对我来说都是全新的!
邮件服务器很羡慕我, 他说:老弟,你的生活太惬意了, 哪像我, 每次有人从客户端访问邮箱, 我都得专门给他建立一个会话, 来处理他发的消息, 你倒好, 完全不用管理会话。
这是由应用的特性决定的, 如果邮件服务器不管理会话, 那多个人之间的邮件消息就会完全混到一起了, 乱作一团了。
而30年前的Web 基本上就是文档的浏览而已, 既然是浏览,我作为一个服务器, 为什么要记住谁在一段时间里都浏览了什么文档呢?
2
Session
但是好日子没持续多久, 很快大家就不满足于静态的Html 文档了, 交互式的Web应用开始兴起, 尤其是论坛, 在线购物等网站。
我马上就遇到了和邮件服务器一样的问题, 那就是必须管理会话,必须记住哪些人登录系统, 哪些人往自己的购物车中放了商品, 也就是说我必须把每个人区分开。
这对我来说是个不小的挑战, 由于HTTP协议的无状态特性, 我必须加点小手段,才能完成会话管理。
我想出的办法就是给大家发一个会话标识(session id), 说白了就是一个随机的字符串,每个人收到的都不一样, 每次大家向我发起HTTP请求的时候,把这个字符串给一并捎过来, 这样我就能区分开谁是谁了。
3
沉重的负担
大家都很高兴, 可是我就不爽了。
每个人只需要保存自己的session id,而我需要保存所有人的session id ! 如果访问我的人多了, 就得由成千上万,甚至几十万个。
这对我来说是一个巨大的开销 , 严重的限制了我的扩展能力, 比如说我用两个机器组成了一个集群, 小F通过机器A登录了系统, 那session id会保存在机器A上, 假设小F的下一次请求被转发到机器B怎么办? 机器B可没有小F的 session id啊。
有时候我会采用一点小伎俩: session sticky , 就是让小F的请求一直粘连在机器A上, 但是这也不管用, 要是机器A挂掉了, 还得转到机器B去。
那我只好做session 的复制了, 把session id 在两个机器之间搬来搬去, 快累死了。
后来有个叫Memcached的给我支了招: 把session id 集中存储到一个地方, 所有的机器都来访问这个地方的数据, 这样一来,就不用复制了, 但是增加了单点失败的可能性, 要是那个负责session 的机器挂了, 所有人都得重新登录一遍, 估计得被人骂死。
我也尝试把这个单点的机器也搞出集群,增加可靠性, 但不管如何, 这小小的session 对我来说是一个沉重的负担。
4
时间换空间
这几天的晚上我一直在思考, 我为什么要保存这可恶的session呢, 只让每个客户端去保存该多好?
可是如果我不保存这些session id , 我怎么验证客户端发给我的session id 的确是我生成的呢? 如果我不去验证,我都不知道他们是不是合法登录的用户, 那些不怀好意的家伙们就可以伪造session id , 为所欲为了。
嗯,对了,关键点就是验证 !
比如说, 小F已经登录了系统, 我给他发一个令牌(token), 里边包含了小F的 user id, 下一次小F 再次通过Http 请求访问我的时候, 把这个token 通过Http header 带过来不就可以了。
不过这和session id没有本质区别啊, 任何人都可以可以伪造, 所以我得想点儿办法, 让别人伪造不了。
那就对数据做一个签名吧, 比如说我用HMAC-SHA256 算法,加上一个只有我才知道的密钥, 对数据做一个签名, 把这个签名和数据一起作为token , 由于密钥别人不知道, 就无法伪造token了。
这个token 我不保存, 当小F把这个token 给我发过来的时候,我再用同样的HMAC-SHA256 算法和同样的密钥,对数据再计算一次签名, 和token 中的签名做个比较, 如果相同, 我就知道小F已经登录过了,并且可以直接取到小F的user id , 如果不相同, 数据部分肯定被人篡改过, 我就告诉发送者: 对不起,没有认证。
Token 中的数据是明文保存的(虽然我会用做下编码, 但那不是加密), 还是可以被别人看到的, 所以我不能在其中保存像密码这样的敏感信息。
当然, 如果一个人的token 被别人偷走了, 那我也没办法, 我也会认为小偷就是合法用户, 这其实和一个人的session id 被别人偷走是一样的。
这样一来, 我就不保存session id 了, 我只是生成token , 然后验证token , 我用我的CPU计算时间获取了我的session 存储空间 !
解除了session id这个负担, 可以说是无事一身轻, 我的机器集群现在可以轻松地做水平扩展, 用户访问量增大, 直接加机器就行。 这种无状态的感觉实在是太好了!
1
美好的旧时光
我经常怀念三十年前那美好的旧时光, 工作很轻松, 生活很悠闲。
上班的时候偶尔有些HTTP的请求发到我这里, 我简单的看一下, 取出相对应的html文档,图片,发回去就可以了, 然后就可以继续喝茶聊天。
我的创造者们对我很好, 他们制定的一个简单HTTP协议, 就是请求加响应, 尤其是我不用记住是谁刚刚发了HTTP请求, 每个请求对我来说都是全新的!
邮件服务器很羡慕我, 他说:老弟,你的生活太惬意了, 哪像我, 每次有人从客户端访问邮箱, 我都得专门给他建立一个会话, 来处理他发的消息, 你倒好, 完全不用管理会话。
这是由应用的特性决定的, 如果邮件服务器不管理会话, 那多个人之间的邮件消息就会完全混到一起了, 乱作一团了。
而30年前的Web 基本上就是文档的浏览而已, 既然是浏览,我作为一个服务器, 为什么要记住谁在一段时间里都浏览了什么文档呢?
2
Session
但是好日子没持续多久, 很快大家就不满足于静态的Html 文档了, 交互式的Web应用开始兴起, 尤其是论坛, 在线购物等网站。
我马上就遇到了和邮件服务器一样的问题, 那就是必须管理会话,必须记住哪些人登录系统, 哪些人往自己的购物车中放了商品, 也就是说我必须把每个人区分开。
这对我来说是个不小的挑战, 由于HTTP协议的无状态特性, 我必须加点小手段,才能完成会话管理。
我想出的办法就是给大家发一个会话标识(session id), 说白了就是一个随机的字符串,每个人收到的都不一样, 每次大家向我发起HTTP请求的时候,把这个字符串给一并捎过来, 这样我就能区分开谁是谁了。
3
沉重的负担
大家都很高兴, 可是我就不爽了。
每个人只需要保存自己的session id,而我需要保存所有人的session id ! 如果访问我的人多了, 就得由成千上万,甚至几十万个。
这对我来说是一个巨大的开销 , 严重的限制了我的扩展能力, 比如说我用两个机器组成了一个集群, 小F通过机器A登录了系统, 那session id会保存在机器A上, 假设小F的下一次请求被转发到机器B怎么办? 机器B可没有小F的 session id啊。
有时候我会采用一点小伎俩: session sticky , 就是让小F的请求一直粘连在机器A上, 但是这也不管用, 要是机器A挂掉了, 还得转到机器B去。
那我只好做session 的复制了, 把session id 在两个机器之间搬来搬去, 快累死了。
后来有个叫Memcached的给我支了招: 把session id 集中存储到一个地方, 所有的机器都来访问这个地方的数据, 这样一来,就不用复制了, 但是增加了单点失败的可能性, 要是那个负责session 的机器挂了, 所有人都得重新登录一遍, 估计得被人骂死。
我也尝试把这个单点的机器也搞出集群,增加可靠性, 但不管如何, 这小小的session 对我来说是一个沉重的负担。
4
时间换空间
这几天的晚上我一直在思考, 我为什么要保存这可恶的session呢, 只让每个客户端去保存该多好?
可是如果我不保存这些session id , 我怎么验证客户端发给我的session id 的确是我生成的呢? 如果我不去验证,我都不知道他们是不是合法登录的用户, 那些不怀好意的家伙们就可以伪造session id , 为所欲为了。
嗯,对了,关键点就是验证 !
比如说, 小F已经登录了系统, 我给他发一个令牌(token), 里边包含了小F的 user id, 下一次小F 再次通过Http 请求访问我的时候, 把这个token 通过Http header 带过来不就可以了。
不过这和session id没有本质区别啊, 任何人都可以可以伪造, 所以我得想点儿办法, 让别人伪造不了。
那就对数据做一个签名吧, 比如说我用HMAC-SHA256 算法,加上一个只有我才知道的密钥, 对数据做一个签名, 把这个签名和数据一起作为token , 由于密钥别人不知道, 就无法伪造token了。
这个token 我不保存, 当小F把这个token 给我发过来的时候,我再用同样的HMAC-SHA256 算法和同样的密钥,对数据再计算一次签名, 和token 中的签名做个比较, 如果相同, 我就知道小F已经登录过了,并且可以直接取到小F的user id , 如果不相同, 数据部分肯定被人篡改过, 我就告诉发送者: 对不起,没有认证。
Token 中的数据是明文保存的(虽然我会用Base64做下编码, 但那不是加密), 还是可以被别人看到的, 所以我不能在其中保存像密码这样的敏感信息。
当然, 如果一个人的token 被别人偷走了, 那我也没办法, 我也会认为小偷就是合法用户, 这其实和一个人的session id 被别人偷走是一样的。
这样一来, 我就不保存session id 了, 我只是生成token , 然后验证token , 我用我的CPU计算时间获取了我的session 存储空间 !
解除了session id这个负担, 可以说是无事一身轻, 我的机器集群现在可以轻松地做水平扩展, 用户访问量增大, 直接加机器就行。 这种无状态的感觉实在是太好了!
原创 2017-07-03 老刘 码农翻身
1. 我把密码献给你
小梁开发了一个“信用卡管家”的程序 , 可以自动从邮箱中读取信用卡相关邮件,分析、汇总,形成一个报表。
小梁找到信用卡达人张大胖试用 : “你的信用卡那么多,看看我这个程序吧, 保准你会爱死它。”
张大胖尝试了几下说: “咦,你这个程序要读取我的网易邮箱啊,那需要用户名/密码吧”
“是啊 , 你把密码告诉输入程序不就行了, 我的程序替你加密保存,保证不会泄露。”
“得了吧你, 我可不会告诉你我的密码, 为了方便记忆, 我的密码都是通用的, 万一泄露了就完蛋了”
小梁说:“这样吧,我不保存,我就访问邮箱的时候使用一次, 用完就扔!”
“你以为你是阿里巴巴啊, 有信用背书, 你只是个小网站, 我把密码献给你,总是觉得不安全。就是我信任你,别人能信任你吗?”
小梁想想也是, 这是一个巨大的心理障碍, 每个人都要誓死捍卫自己的密码啊。
2. Token
过了一周, 小梁兴致勃勃地把张大胖拉来看“信用卡管家”的升级版。
“升级为2.0了啊, 这次不用问你要网易邮箱的用户名和密码了”
“那你怎么访问我的邮箱?”
“很简单,我提供了一个新的入口,使用网易账号登录, 你点了以后,其实就会重定向到网易的认证系统去登录, 网易的认证系统会让你输入用户名和密码,并且询问你是否允许信用卡管家访问网易邮箱, 你确认了以后,就再次重定向到我的‘信用卡管家’网站, 同时捎带一个‘token’ 过来, 我用这个token 就可以通过API来访问网易邮箱了。 在这个过程中, 我根本不会接触到你的用户名和密码,怎么样, 这下满意了吧?”
“你说得轻松, 你这个信用卡管家是个小网站,还没有什么名气, 网易怎么会相信你这个网站呢?”
“我当然要先在网易注册一下啊, 他们会给我发个app_id 和app_secret, 我重定向到网易的时候需要把这个东西发过去, 这样网易就知道是‘信用卡管家’这个应用在申请授权了。”
(点击看大图)
张大胖说: “ 你这重定向来重定向去的, 实际上不就是为了拿到一个token 吗?”
“对啊,因为你不信任我的信用卡管家, 不让它保存你的密码,只好用token的方法了 , 它是网易认证中心颁发的,实际上就代表了你对信用卡管家访问邮箱的授权,所以有了这个token 就可以访问你的邮箱了”
"对了" 张大胖问题, “你为什么用Javascript的方式来读取token啊”
“这样我的后端服务器就不用参与了,工作都在前端搞定, 你注意到那个URL中的#号了吗? www.a.com/callback#token=<网易返回的token>”
张大胖说: “我知道啊,这个东西叫做hash fragment, 只会停留在浏览器端, 只有Javascript 能访问它,并且它不会再次通过http request 发到别的服务器器, 我想这是为了提高安全性吧。”
小梁说: “没错, 那个token非常非常重要,得妥善保存,不能泄露!”
“可是在第6步通过重定向,这个token 以明文的方式发送给了我的浏览器, 虽然是https ,不会被别人窃取,可是浏览器的历史记录或者访问日志中就能找到, 岂不暴露了?”
小梁说: “这个.... , 我说你这个家伙,安全意识很强烈嘛, 让我想想,有没有更安全的方式。"
3. Authorization Code + Token
又过了一周,小梁成功地把信用卡管家升级为3.0.
他对张大胖说: “这次我成功地把那个非常重要的、表示授权的token 给隐藏起来了, 你要不要看看?”
“你先说说你是怎么隐藏的?”
“其实整体思路和之前的类似,只是我引入了一个叫做Authorization Code 的中间层。 当你用网易账号登录的时候, 网易认证中心这一次不给我直接发token,而是发一个授权码(authorization code) , 我的信用卡管家服务器端取到这个code以后,在后台再次访问网易认证中心, 这一次他才发给我真正的token 。 还是直接上图吧:”
(点击看大图)
张大胖说: “还比较容易理解, 本质上就是你拿着这个返回的授权码在服务器后台‘偷偷地’完成申请token 的过程, 所以token 浏览器端根本就接触不到,对吧?”
“什么叫偷偷地申请token ? 这是我信用卡管家服务器和网易之间的正常交流, 只是你看不到而已。”
“开个玩笑了, 你虽然隐藏了token,但是这个授权码确是暴露了啊,你看第7步,我在浏览器中都能明文看到, 要是被谁取到, 不也是照样能取到token吗?”
小梁说: “我们肯定有防御措施, 比如这个授权码和我的信用卡管家申请的app_id,app_secret关联, 只有信用卡管家发出的token请求, 网易认证中心才认为合法; 还可以让授权码有时间限制,比如5分钟失效,还有可以让授权码只能换一次token, 第二次就不行了。 ”
“听起来似乎不错, 好吧, 这次我可以放心地使用了!”
4. 后记
本文讲的其实就是就是OAuth 中的三种认证方式,依次是:
1. Resource Owner Password Credentials Grant(资源所有者密码凭据许可)
2. Implicit Grant(隐式许可)
3. Authorization Code Grant(授权码许可)
还有一种叫做Client credentials ,用的较少,文章没有涉及。
这些名称有些古怪, 但是本质没那么复杂。 在OAuth中,还有几个术语大家可以理解下:
资源所有者 : 就是我们上文的张大胖
资源服务器 : 即网易邮箱
客户端: 就是上文的信用卡管家
授权服务器 : 即上文的网易认证中心
预警: 这是一篇长文,耐心阅读,必有收获。
这家集团公司财大气粗,竟然自己建了一个数据中心, 放了数百台机器, 部署了几十个企业内部系统。
在无尘、恒温、恒湿的环境里,这些信息系统的日子过得非常惬意。
他们只需要在白天应对人类的HTTP 请求,及时做出响应, 只要人类一下班, 系统的负载就陡然下降,CPU内存全部都空闲下来。 大家闲来无事, 热热闹闹的机房夜话就开始了。
1第一夜
休假系统是用世界上最好的语言PHP做的,他向来消息灵通,今天带来了一个特别新闻:“ 号外号外, 听说了吗, 人类要搞SSO了。”
Python 写的报销系统, C#写的车辆管理系统早就看不惯PHP这种中英混杂的风格了: “ 别拽了,说中文!”
PHP休假系统很不屑: “就是单点登录嘛,难道你们没听说过?”
C# 说: “不就是登录嘛! 人类不是天天登录系统? 你看他们想调度车俩的时候,就得登录我的系统, 输入用户名和密码, 我做验证, 验证通过就建立session, 然后把session id 通过cookie发送给人类的浏览器, 下次人类再访问我的URL的时候, cookie就会发过来, 我就知道他已经登录过了。 “
C#很得意,向大家炫耀着登录的原理。
“对了,告诉你们一个小秘密, 人类这些密码太简单了,不是123456, 就是abcd。 ”
Python附和道: “ 是啊,人类太懒了, 密码超级简单,听说上一次有个家伙用领导账号成功地登录了系统, 于是全集团人员的工资都暴露了! ”
“那对于同一个人, 你这里的用户名/密码和小C#那里会一样吗?” PHP说
“这个。。。 很有可能不一样。”
PHP说: “对啊,这就是问题了, 这么多不同的用户名,有的是邮箱地址,有的是手机号,有的是用户名, 我们这里几十个系统,搁谁都记不全啊! 这就是他们为什么要搞单点登录: 在一个地方登录一次, 就可以访问我们这里所有的系统了”
C# 叫道: " 只需要登录一次? 听起来很美好啊 ! 让我想想怎么实现, 对了, 登录就是cookie,那我们把cookie共享起来不就可以了? 人类在报销系统那里登录后,再访问我这个车辆管理系统, 把cookie发过来不就行了?"
众人纷纷表示赞同。
PHP 心里再次鄙视了一下C# , 说: “NO , NO , cookie是不能跨域的, a.com 产生的cookie , 浏览器是不会发到b.com去的。 ”
有人在悄悄地google , PHP果然说得不错。
大家赶紧检查了下自己的域名,有的叫 xxx.vaction.com, 有的叫xxx.hr.com , 看来共享cookie方案不管用。
PHP补充到: “也许人类能把我们统一到一级或二级域名下, 比如 xxx.company.com, 这样cookie可以共享了! 但是我们后端没有session 也不行啊, 你cookie发过来,我内存中没数据,根本不知道你是否登录过, 怎么验证?”
C#说: “session 也可以共享哦 , 你看我这个系统有两个服务器,共享的是redis中的session, 将来我们这几十个系统都共享同一个redis,想想都让人激动啊!”
Python 说: “ 这么多系统, 架构不同,语言也不同, 共享session太麻烦了吧? ”
C# 发愁地说: “那怎么办? ”
这时候旁边传来了一声大吼: “你们在那里吵吵什么,老子在生成报表,都没法专心干活了!”
这是脾气暴躁的COBOL在抱怨了, 千万不要惹这个老家伙,于是大家纷纷噤声, 老老实实地睡觉去了。
2第二夜
第二天晚上,COBOL程序终于歇着了, 大家继续讨论。
Python提了一个新点子:“要我说,我们别共享session了, 我们就用cookie, 用户在我这个报销系统这里登录了, 我就在cookie中写个token , 用户访问别的系统,就可以把token 带过去, 那个系统验证一下token ,如果没问题,就认为它已经登录了。”
“那token 得加密吧, 要不然谁都可以伪造” C#安全意识挺强
“那是自然, 听说过json web token 没有? 我们每个系统在生成token 的时候,都要对数据做个签名,防止别人篡改, 下面就是我生产的token , 其中有header 信息和userID, 你看我用Hash算法和密钥生产了一个签名。 这个签名啊也是token数据的一部分, 到时候也会发到你的系统去” Python 说
(计算签名的过程)
(放置到cookie中的token)
C#说: “明白了, 我收到了token ,就用同样的算法再计算签名,然后和你计算的相比, 如果相等,证明他登录过,我可以直接取出userID使用了, 如果不相等, 说明有人篡改, 我就关门放狗, 把他暴揍一顿。”
Ruby 插嘴说: “这个办法不错,轻量级,我喜欢! 只是这个算法和密钥大家都得一致才行。 密钥的分发也是个问题。”
PHP听了半天, 发现了一个漏洞:“你这个token中放了一个userID, 可是我们每个系统的userID都不一样啊, 你的userID 我拿过来没有任何用处, 怎么办?”
这的确是个致命的问题!每个系统中都有一套自己独特的user id ,互不共享,这样以来之前讨论的什么共享session, 共享cookie ,都很难实现了 !
一阵沉默, 看来没救了。
夜已深,大家讨论得有点累了,纷纷睡去。
3第三夜
第三天,机房夜话继续, 但还是没有解决方案。气氛有点小尴尬。
老成持重的Java咳嗽了几声,示意要发言了。
“你们知道吗, 我们是一个企业内部系统,人类搞SSO就是想消除这多个账号的问题,将来每个系统都不需要维护自己的用户系统, 他们会建立一个统一的认证中心,所有的用户注册和认证都在那里做。”
“这么做行得通吗,认证中心怎么通知我们说用户已经认证了?” C#问道
“这个过程稍微有点复杂” , Java 对C# 说, “举个例子来解释下, 比如用户通过浏览器先访问你这个系统www.a.com/pageA , 这个pageA是个需要登录才能访问的页面,你发现用户没有登录, 这时候你需要做一件额外的操作,就是重定向到认证中心,www.sso.com/login?redirect=www.a.com/pageA”
C#说: “为什么后面要跟一个redirect的url呢? 奥,明白了, 将来认证通过后,还要重定向到我这里来。”
“没错, 浏览器会用这个www.sso.com/login?redirect=www.a.com/pageA 去访问认证中心, 认证中心一看, 没登录过, 认证中心就让用户去登录, 登录成功以后, 认证中心要做几件重要的事情 :
1. 建立一个session。
2. 创建一个ticket (可以认为是个随机字符串)
3. 然后再重定向到你那里, url 中带着ticket : www.a.com/pageA?ticket=T123 与此同时cookie也会发给浏览器,比如:Set cookie : ssoid=1234, sso.com ”
“可是这个cookie对我一点用处都没有啊,跨域不能访问啊。”
“人家网站sso.com的cookie对你肯定没用了, 浏览器会保存下来。 但是注意那个ticket ” Java 提醒道, “这个东西是个重要的标识,你拿到以后需要再次向认证中心做验证。”
“明白,是为了防止不坏好意的人伪造”
“你拿着token ,去问下认证中心, 这是您发的token 吗, 认证中心说没错,是我发的,那你就可以认为用户在认证中心登录过了”
“那我该干什么事情呢? ”
“浏览器向你发出的请求不是www.a.com/pageA?ticket=T123 吗, 这时候你既然认为用户已经登录过了,那就给他建立session, 返回pageA这个资源啊”
“嗯, 我还需要给浏览器发一个cookie, 对吧, 这是属于我的cookie : Set cookie : sessionid=xxxx, a.com ” C# 说道
"孺子可教, 注意,这时候浏览器实际上有两个cookie,一个是你发的,另外一个是认证中心发的。"
“如果用户再次访问我另外一个受保护的页面,www.a.com/pageA1, 该怎么办? 难道还要去认证中心登录 ” C#继续问
“那当然不用了,你给浏览器发过你自己的cookie , 到时候浏览器自然会带过来,你就知道它登录过了。 ”
“原来如此, 好麻烦啊” C#感慨道。
Python 插了一句: “如果用户访问C#的系统(www.a.com/pageA)时已经通过认证中心登录了, 然后再访问我www.b.com/pageB, 会发生什么状况呢?”
Java 说:“很简单, 和访问www.a.com/pageA非常类似,唯一的不同就是不需要用户登录了,因为浏览器已经有了认证中心的cookie, 直接发给www.sso.com就可以了”
说着, Java 又画了两张图。
同样,认证中心会返回token , www.b.com 需要做验证
PHP 一直在努力的听,他说: “其实本质上就一个认证中心的cookie ,加上多个子系统的cookie 而已!”
Java 撇了一眼PHP : “总结的很精辟!”
C#发现了一点新东西: “在认证中心,为什么要去做一个系统注册的操作呢?, 我看到注册了系统A,还有系统B”
"SSO 是单点登录,是不是还要有单点退出啊, 用户在一个系统退出了,认证中心需要把自己的会话和cookie干掉,然后还要去通知各个系统, 让他们把自己的会话统统干掉,这样才能在所有的系统都实现真正地退出啊。" Java回答。
大家琢磨了一会儿,很快就喧嚣起来:
“太麻烦了”
“我们的代码还得改动不少呢”
“重定向太多了, 把我都搞晕了”
“我觉得人类不会这么搞!”
......
Java 说“别小看它, 这个点子是耶鲁大学提出的,叫做CAS(Central Authentication Server ) , 是一个很著名的SSO解决方案, 弄不好人类就会采用。 你们呐,还是好好学学吧。
1、具有1-5工作经验的,面对目前流行的技术不知从何下手,需要突破技术瓶颈的可以加群。
2、在公司待久了,过得很安逸,但跳槽时面试碰壁。需要在短时间内进修、跳槽拿高薪的可以加群。
3、如果没有工作经验,但基础非常扎实,对java工作机制,常用设计思想,常用java开发框架掌握熟练的,可以加群。
4、觉得自己很牛B,一般需求都能搞定。但是所学的知识点没有系统化,很难在技术领域继续突破的可以加群。
5. 群号,高级架构群: 283943715 备注好信息!
6.阿里Java高级大牛直播讲解知识点,分享知识,下面几大专题都是各位老师多年工作经验的梳理和总结,带着大家全面、科学地建立自己的技术体系和技术认知!