登录注册那些事

我们来聊一聊综合楼的看门大爷

综合楼有一个门卫大爷,综合楼里面有各个房间,207,211等等,每个想进入楼内的人都需要在看门大爷那做一个身份的验证,登记之后才能进到综合楼里,而进到综合楼里的话还分各种权限。如学生能进实验室,老师能进实验室和自己的办公室。

大爷要做的第一件事就是要知道谁是这个楼里的老师或者是学生,那么我们首先需要创建一张USER表,存储能进这栋楼的用户信息,所以在登录之时,也就是你刚进入这栋大楼的时候,大爷会看一下User表,看看上面有没有你的名字,如果有你的名字,再对你的密码啥的进行验证。

那么我们现在说一下,如何对密码进行存储和校验

我们说一下加密算法,也就是Hash哈希算法。哈希算法的细节我们再次不深究,我们只需要知道,Hash算法有一个特点:输入的值对应一个唯一的输出。这样我们就可以实现:注册的时候密码用Hash算法做不可逆的加密,登录的时候也用Hash加密。数据库中不存真实的密码,而是存加密运算过的密码。这时候,一样的密码对应着相同的加密后的密文,我们只需要对比密文是否相等就可以知道密码是否相等了。常见的Hash算法有MD5,SHA256,SHA1等等。

那么我们如何保密地跟门卫大爷交流呢

我们现在知道了我们的信息是如何存储在门卫大爷手上的USER表中,也知道了门卫大爷如何对我们的身份进行验证,那么问题来了,我们告诉门卫大爷我们的信息的时候,万一旁边偷偷站着一个人在偷听我和门卫大爷的对话,偷听了我用POST请求告诉门卫大爷的信息怎么办呢。首先,我们肯定需要使用HTTPS,确保在传输过程中的数据信息安全性。 可是HTTPS的证书也是可以伪造的,HTTPS也可能会失效。所以,在HTTPS的情况下,我们还需要自己在前端对重要信息进行加密,再发往后端。

其实很多小的系统不需要前端加密,国外的一些大公司也不加密,包括github,微软,谷歌都不做前端加密。加密要求很高的系统才需要,小系统就信任https就好了。不过话虽这么说,github此前就是不使用前端加密的,去年翻车了,然后给用户群发邮件改密码,然后乖乖前端加密了。github这次翻车的原因是:你前端不加密,而且https没被攻破,但是https在nginx就解开了啊,nginx解开加密后,在后台,也就是说在公司内部机器上是明文了,明文随便一个运维人员都能看见,在后端打个log日志信息就看到了明文密码了,所以这样很危险啊。于是外国一些公司也开始跟着国内的大厂一起在前端加密了。

我们实施加密的具体方法可以有很多种,下面列出几种常用的(对密码加密的方法,往后还有对账号和手机号,身份证号进行加密的方法,但是不一样,因为身份证号,手机号涉及到短信验证码的发送或者是像公安机关部门申请认证,这样子手机号和身份证等信息一定要有解密的过程,密码可以不需要解密,所以对需要明文的信息和对不需要明文的信息我们采用不同的方法)。

1.前端进行MD5加密,发往后端,后端加salt加密

2.(出于更高安全考虑,使用SHA加密代替MD5)前端进行SHA加密,然后发往后端,后端再进行SHA加salt加密

3.后端先生成一组RSA的公钥和私钥(将HTTPS自己额外做一遍),前端拿着公钥加密,后端拿着私钥解密,然后后端把解密出来的密码再做不可逆的加密如SHA1和MD5等重新进行加salt加密。

4.用AES对称加密的方法,在前端访问登录页的时候,后端生成一个秘钥返回给前端,然后前端使用秘钥加密,后端使用相同的秘钥解密就好了。

5.使用uuid(通用唯一识别码)加密就好了(服务器为了对上验证码和你这次会话会用uuid来标识验证码),既然uuid是现成的,那我们直接拿uuid进行一次对称加密就好了,或者服务器生成需要uuid的时候就生成一个秘钥做成uuid,uuid就作为你秘钥。然后后端解密加密,继续md5加盐。

数据库存储账号密码的格式如

我们在上面都提到了一种东西,叫做salt,盐是一串随机数,因为md5在当今计算机的算力之下暴力破解是可能的,所以md5,实际上没有那么安全了,这时候,我们就要增加密码的位数,然后再进行md5,当密码位数增加的时候,暴力破解的难度也在几何增长,所以增加密码位数的过程我们就叫加盐。当用户注册的时候,我们会随机生成一串字符,加在用户密码字符串的后面或是前面,然后再进行md5加密。(为了更高安全性,在更新的架构中通常使用SHA256甚至SHA512代替MD5)(还可以使用账号创建时间,创建人ip等等信息作为盐,盐的生成方法很多,具体方法看自己的需求)

当门卫大爷验证了我们的身份之后,我们想进入每个屋子怎么办呢(调用各个Api时的鉴权)

现在我们进入了综合楼,可是,有的人能进所有的屋子,有的人能进207,我们如何识别鉴权呢?

此前,我们见过将token存储在数据库中的鉴权(无车承运系统),也见过将token存在服务器缓存中,放置于redis中等方法,这些方法无一例外是有状态的(需要服务器的信息记录)。这样的一种情况对于单体应用来说当然没有问题,但是随着现在所谓的微服务拆分之后,每个微服务服务器都去调用数据库或者共用redis获取相关的信息会使系统又高耦合了起来,甚至如果存在本机的缓存中,微服务将很难方法其他主机的缓存,这样会很消耗服务器资源甚至不易做到跨服务统一鉴权,因为每一次的请求都会额外地多访问一次存储设备,这样是很消耗资源的。

同时,我们也需要明确一个架构概念,即架构越简单越好,组件越多风险越大。所以,session,redis啥的有状态服务我们尽可能避免(将状态维持在不论是服务器还是redis还是数据库中,都会增加服务器的负载压力,且服务器的架构复杂化之后会难以维护)。

这时候我们就要介绍一个协议:JWT(JSON Web Token),可以从名字看出来,这个token是可以从json里传到前端的(在cookie中也有,在web端尽量使用cookie来存储,因为localstorage不安全)。jwt特殊情况下在不支持Cookie的地方也能使用(如微信小程序和app端的登录请求),同时这样也能在跨域的时候对token处理得游刃有余,跨域时就从body取出存入浏览器内存或是自行setCookie即可。jwt可以说是现在应用最广泛的一种鉴权手段了。

token我们叫做令牌,是持于用户手上的,就是综合楼大楼门卫颁发给我们的,上面写着权限信息等信息,服务器不进行存储,存在用户的cookie中,用户每次使用,就从cookie中取出置于head中。

(下面是登录之后返回的body信息,很标准的jwt,在cookie中也有一份同样的token)

{ "msg":"操作成功", "code":200, "token":"eyJhbGciOiJIUzUxMiJ9.eyJsb2dpbl91c2VyX2tleSI6IjM0MDRlNDg3LTk2YTUtNGI1My1hOGFhLTE4NjE3ZTM5M2VkNSJ9.DIGs1_9gR4DIiZZKNkzodFYdy0O_vasQ-9x-Jdk4j95WXjbnnljoDZ7sDHVGtxHJYGO8dadnnF4ARA8Yj0YG3A" }

//发送请求时拦截请求加上head // request拦截器 service.interceptors.request.use( config => { if (getToken()) { config.headers['Authorization'] = 'Bearer ' + getToken() // 让每个请求携带自定义token 请根据实际情况自行修改 } return config }, error => { console.log(error) Promise.reject(error) } ) ------------------------------------------------------------------------------------------- //下面是getToken()方法 export function getToken() { return Cookies.get(TokenKey) }

token的信息有分成明文和加密两部分,一部分存用户信息并进行base64压缩(这一部分相当于明文),一部分存服务器私钥加密过后的密文字符串,每次访问接口,后端会用公钥对私钥加密的部分进行解密,解密之后与明文部分进行比对相等,那就说明token有效。

因为有了token就相当于有了用户权限,这样我们就必须安全地存储token,那么将token存储在cookie中是安全的,所以我们在cookie存token,并在请求时将其置入head即可。

这会有个问题,后端给用户发布了token之后,如果想撤回用户的token怎么办,因为我们说在服务器不存储相关信息,有关登录信息全存储在了用户手上,那么撤回就是无法完成的,只能通过设置超时时间如30分钟,15分钟来达到。(如果实在想实现,就维护一个redis记录一下退出登陆的账号,下次相同账号的请求就拒绝就好了)

结论


生成一对公私钥,服务器放置私钥,前端放置公钥(相当于自己实现一遍简化版单向的HTTPS,但是优点是不会被伪造的证书颁发机构攻破)

刚进入注册或者登录页面,向服务器请求验证码图片,服务器返回uuid(用于标识验证码)和验证码图片的base64码

将用户输入的密码用md5加密,然后对用户名明文和密码密文统一使用我们自己生成的公钥加密。

整个http通讯用https加密

后端用私钥解密,获得用户名明文和前端加密过的密码

后端生成一个随机的盐salt(如果是登录则从数据库查询salt值),前端加密过的密码字符串后加上salt字符串,再进行一次md5加密

将salt和两次md5加密的密码和明文用户名存入数据库(如果是登录则与数据库中的加密后的密码比较)。实现登录注册。

登录成功后,后端将用户权限有关的信息打包成jwt(下面会说jwt),存在cookie中发送给前端(如果是微信小程序,或者手机app不能拿到cookie,可以在body中也传一份,让他们取出来存在自己的localstorage中,毕竟最后验证的不是cookie中的,而是head中的token)

用户每次请求都在head中带上token进行验证。

其他问题

当我们实现了登录注册之后,事情真的这么简单吗,毕竟验证登录是最最重要的安全措施了,在做验证登录的时候我们有很多细节需要解决。比如,为了防止有人疯狂试错密码,可以使用一个redis(为了安全,系统复杂就复杂了)记录记录每天该用户的错误登录次数,如果超过5次禁止登录。还或者同账号只能同时登录一次(顶号)(还是使用redis来实现)。还有,用手机验证码代替密码(就像好食堂一样,直接放弃密码)。还可以,进行异地登录控制认证,如果使用的ip地址所属的区域和常见登录区域不一致时,调用身份验证服务多重验证,比如强制使用手机验证码验证等。还可以使用第三方登录接口,如微信登录,qq登录。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,258评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,335评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,225评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,126评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,140评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,098评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,018评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,857评论 0 273
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,298评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,518评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,678评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,400评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,993评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,638评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,801评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,661评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,558评论 2 352

推荐阅读更多精彩内容