Login Security
最近有机会深入了解一下神秘的登录了:)之前开发的规则引擎ui需要权限验证功能了,我就不得不写了一套权限验证的东西,从前端到后端。其实公司里是有集成的统一登录项目,但是这个项目做的不好,没有考虑好前后端分离场景下的权限验证,导致我走了很多弯路。 先看看一般的登录场景 用户访问某一资源 后台系统发现用户没有登录 重定向到登录页面 用户输入用户名和密码,并提交请求道后台 后台验证用户名密码成功,跳转到登录成功后的页面 很多旧系统,特别是前后端没有分离的系统,基于用户名密码的验证方式,当用户验证成功之后,会将当前session标记为authenticated,这样当用户再访问后续资源时,只要带着cookie中的sessionId就可以了,而不需要后续验证。即,在session生效的时间段内,用户可以访问任何资源而不需要进行权限验证。这里称之为基于状态的验证(cookie)。 另外一种,这里统称为基于token的验证,例如oauth2、basic authentication。每次访问的时候需要在header中加入token进行验证。 以basic authentication为例。很长时间以来,我都认为basic auth是一种十分不可靠的权限验证方式,因为不像oauth2,token是从服务器临时获取而来的,basic auth的token是由用户名和密码经过base64加密而来的,众所周知base64是不安全的。但在我看过这个视频之后,我感觉我了解了真相。。。 简单来说,这个视频是spring security的老大讲解rest api的安全问题。从这个分享,我认为Rob Winch是一个安全专家(至少在我的认知范围内是这样的)。深受启发呀。先抛出一个很有可能被忽视的事实: the browser always sends cookies, and the server always has a session (unless you switch it off). 回头再来看rest api的安全问题。从协议角度来说,rest api是无状态的,也就是说使用rest api访问资源不应该依赖session状态,而是依赖token。http是无状态的,但是在生产环境下使用http访问资源是十分危险的,最简单的例子是,当提交用户名密码时,在http下使用post请求,也是明文传输密码的。所以安全的传输必定是建立在https上的。而TLS/SSL是有状态的 The web server and the client (browser) cache the session including the cryptographic keys to improve performance and do not perform key exchange for every request. 所以https下的rest api其实是stateful!所以正确的保护rest api的方式,是使用token+session的方式。使用token保护rest api所访问的资源看起来十分自然,而使用session的原因在于csrf的保护,只要有浏览器访问rest api,就应该有防范csrf,因为浏览器每次发请求都会带上cookie,而且server总会维护session(除非主动关闭),所以使用基于session的方式放置csrf是很本能的做法。这里不需要再写其他的代码,只需要关注你的业务逻辑即可。...