现在貌似大多数网站用户认证都是基于 session 的,(我们公司的网页登陆就是使用的把session),即在服务端生成用户相关的 session 数据,而发给客户端的 sesssion_id 存放到 cookie 中,这样用客户端请求时带上 session_id 就可以验证服务器端是否存在 session 数据,以此完成用户认证。这种认证方式,可以更好的在服务端对会话进行控制,安全性比较高(session_id 随机),但是服务端需要存储 session 数据(如内存或数据库),这样无疑增加维护成本和减弱可扩展性(多台服务器)。 CSRF 攻击一般基于 cookie 。另外,如果是原生 app 使用这种服务接口,又因为没有浏览器 cookie 功能,所以接入会相对麻烦。
——CSRF攻击(比如,用户登陆了网页QQ A,此时用户浏览器端存了一个cookie,网页QQ未下线,然后与此同时登陆了一个钓鱼网站B, B会发出一个Request请求给用户浏览器端,用户浏览器不知道是A发出的请求还是B发出的请求,从而B能达到模拟A的权限。)
——CSRF防御
-
通过referer、token或者验证码来检测用户提交
-
尽量不要在页面的链接中暴露用户隐私信息
-
对于用户增删改查操作都用post请求
-
避免全站通用的cookie,严格设置cookie的域
基于 token 的用户认证是一种服务端无状态的认证方式,服务端不用存放 token 数据。用户验证后,服务端生成一个 token(hash 或 encrypt)发给客户端,客户端可以放到 cookie 或 localStorage 中,每次请求时在 Header 中带上 token ,服务端收到 token 通过验证后即可确认用户身份。这种方式相对 cookie 的认证方式就简单一些,服务端不 用存储认证数据,易维护扩展性强, token 存在 localStorage 可避免 CSRF , web 和 app 应用这用接口都比较简单。不过这种方式在加密或解密的时候会有一些性能开销(好 像也不是很大),有些对称加密存在安全隐患(aes cbc 字节翻转攻击)。
方案 A :我发给你一张身份证,但只是一张写着身份证号码的纸片。你每次来办事,我去后台查一下你的 id 是不是有效。
方案 B :我发给你一张加密的身份证,以后你只要出示这张卡片,我就知道你一定是自己人。
就这么个差别。
//清除cookie’的方法
request.getSession(true).invalidate();//清空session
if (request.getCookies() != null) {
Cookie cookie = request.getCookies()[0];//获取cookie
cookie.setMaxAge(0);//让cookie过期
}