[Day 07] - Spring Boot 实作登入验证(一)(TOKEN or SESSION?)

昨天在controller有做了一个post的登入api,
不过也就只是验证你传入的帐密有没有正确而已,要怎麽实际应用在网页的登入验证上呢?

Session 验证

一般在jsp网站的做法应该是验证客户的帐密是否正确,
正确就在客户的session加一个已登入的attribute
然後还有写一个filter,在需要登入的页面验证这位客户的session有没有登入,差不多就这样!

写起来也很简单,因为Servlet会帮我们把session的ID,一般预设叫是JSESSIONID
存放到client的cookie里面,我们不用再在程序里多写什麽复杂的操作,

以某银行为例,我们在cookie里可以看到JSESSIONID
https://ithelp.ithome.com.tw/upload/images/20210921/20128973GBYcwEQroJ.png

可以看到我们的cookie里存了一个叫JSESSIONID的值,就是Server发配给我的session id
一般是这样,当我们输入帐密登入时,
Server端验证帐密无误,会拿你带着的session id,
找出你的session(存放在Server里面),然後加入一些身分判断的attriubte,

我们每次发送request时都会一并带上session id,
透过fillter的实作
Server端会拿我们带的session id来从Server本身储存的众多session中,找出这个特定session
看看这个客户的session有没有已登入的资讯,有的话就确认身分了,

这样的意思即是,如果有一万个客户在线上,那Server就要储存10,000个不同人的session,
除了对Server造成负担外,如果是有多台主机,还要处理主机间session要怎麽共享的问题

所幸现在普遍用redis就能解决以上两个问题

那还有另一个问题是,如果我盗用这个人的session id,不就等於取得这个人的登入身份了吗

理论上来讲,是的

可以看看几个月前的新闻

骇客解释,首先他们先在网路花 10 美元买被盗用的 Cookie,因 Cookies 保存特定使用者的登录资讯,让骇客可冒充他人身分登入。骇客利用被盗的 Cookie,获得 EA 使用的 Slack 频道许可权,并进入 EA 的 Slack。

虽然新闻中只说Cookie,其实道理差不多,总之就是Cookie里面用来确认身分的东西被人盗用了
不过一般银行会在网站加上Security Header保护Cookie的安全(Set-Cookie: ....; Secure; HttpOnly),
让Cookie不会这麽容易被盗走,且本身交易流程也有验证的机制
所以其实也不用太担心

JWT TOKEN 验证

我查了网路上大部分Spring Boot前後端分离的作法,很流行用jwt这种以token取代session的做法,
jwt是一串由Server端加密後发配给client的token,
client收到token之後,在需要的情况下,发request就带着这个token,让Server解密并验明身分,

这边要注意的是,因为token本身就保存了client的验证资讯,
一般情况下,Server发配token後就不再保存token,
只需要在client丢request过来时解密client的token,看看是否正确就行了

举个简单例子,

有一天我被警察拦检,
session就像是我(client)只报给警察(server)我的身分证字号: 我是谁?家里住哪?你再自己用身分证字号去查
token就是我(client)直接身分证给警察(server): 警察只需要确认身分证是真,我是谁、住哪,也不用去查了(因为都写在证上)

这麽做的优点是减少了Server端的负担,且不必再操心session共享跟server负担大的问题,
不过缺点是Server端无法控制token的失效,因为以token来讲Server只做验证的动作,
如果哪天因为某些原因,你要强制某个client登出,不好意思没办法,就只能等他的token过期或他自己登出,
而使用session的话就可以透过移除server上该客户的session资讯来做到强制登出

虽然token另有搭配refresh token来达到Server控制的作法,不过这样就有点失去JWT Stateless的初衷了...
说到底还是要看业务情境,而且一般应该也很少有要踢退客户的情境,锁ip还比较常见

前面讲到,session因为session id存在cookie里有被盗的风险,那token有吗?
我在查资料的时候有看到文章写说

JWT因为不是储存在浏览器cookie,所以能避免CSRF(跨站请求伪造)的安全问题

想说有这麽神奇吗?那token是储存在哪?怎麽避免的?

查到的作法是存在html5的功能:local storage
不过只要东西存在客户端就一样有被盗用的风险,
甚至,用local storage还更容易被第三方取得...
此外cookie目前已经有很成熟的保护机制(前述的security header),
且token其实也可以存在cookie里,端看实作的方式,所以实际上并没有谁比较不安全的问题

因此安全性不能算是JWT的卖点

那麽,我要用哪种验证方式?
因为我不是要做什麽百万流量的网站、不会遇到session的资源问题,
选session的方式应该是最简单的方法

但是这次参加铁人赛就是要玩点不一样的,明天就以jwt来实作!


<<:  Day 17 储存宝石:【Lab】S3 储存类别 & 生命周期管理 (上)

>>:  Day 8 : HTML – 为什麽Flex没有justify-items和justify-self,而grid却有?

Docker是什麽?用 Docker 建置环境有什麽优点呢?

简单来说 Docker 就是一个虚拟机,确保执行专案时的环境都一样。 毕竟影响程序执行成功或失败的变...

DAY8 Kotlin的第一步

学习这个语言第一个遇到的问题就是...... 要念Kotiln还是念Kotlin,思考许久发现, 一...

xargs - Linux里好用的工具

xargs xargs原来意思是build and execute command lines fr...

建立第一个单元测试(golang)-2(Day21)

接下来就是我要将测试放入现在正在进行的api中了 在这次的测试中,我想测试mRequest.Get(...

Day9 Methods and v-on

今天来介绍这个指令v-on用来绑定HTML DOM,来触发要执行的事件 Method 这时并没有执行...