认证 和授权的区别是什么?
- Authentication(认证) 是验证您的身份的凭据(例如用户名/用户 ID 和密码),用户是否存在。
- Authorization(授权) 发生在 Authentication(认证) 之后,访问系统的权限,用户是否时管理员。
RBAC 模型了解吗?
RBAC (Role-Based Access Control 基于角色的权限访问控制):一种通过角色关联权限,一个用户可以拥有若干角色,每一个角色又可以被分配若干权限,多对多的关系。
为了实现 RBAC 权限模型,数据库表的常见设计如下(一共 5 张表,2 张用户建立表之间的联系)理论这样好,实际为了简便只会用两张表(用户表和角色表):

通过这个权限模型,我们可以创建不同的角色并为不同的角色分配不同的权限范围(菜单)。

Cookie 和 Session
Cookie :存放在客户端,一般用来保存SessionId 或者 Token 或者登陆过的用户信息,并可以通过 Cookie 记录和分析用户行为用户信息。
- 浏览器通过 F12 -> Application -> Cookie可以看到当前域名下的Cookie
- 安全性较低,可以将信息加密然后使用到的时候再去服务器端解密
Session :服务端记录用户的状态。
每次用户登陆系统之后,会返回给客户端具有
SessionID的Cookie,下次请求通过Cookie携带SessionID验证身份。通常需要客户端开启了
Cookie安全性相对Cookie更高
注意
Session的过期时间
多服务器节点下 Session-Cookie 方案如何做?
举个例子:假如我们部署了两份相同的服务 A,B,用户第一次登陆的时候 ,Nginx 通过负载均衡机制将用户请求转发到 A 服务器,此时用户的 Session 信息保存在 A 服务器。结果,用户第二次访问的时候 Nginx 将请求路由到 B 服务器,由于 B 服务器没有保存 用户的 Session 信息,导致用户需要重新进行登陆。
常见解决方案:
- 某个用户的所有请求都通过特性的哈希策略分配给同一个服务器处理。这样的话,每个服务器都保存了一部分用户的 Session 信息。服务器宕机,其保存的所有 Session 信息就完全丢失了。
- 每一个服务器保存的 Session 信息都是互相同步的,这种方案成本太大,节点越多,成本越大。
- 使用Redis缓存进行登陆信息的保存。
如果没有 Cookie 的话 Session 还能用吗?
一般是通过 Cookie 来保存 SessionID ,假如你使用了 Cookie 保存 SessionID 的方案的话, 如果客户端禁用了 Cookie,那么 Session 就无法正常工作。 浏览器禁用cookie的含义是指用户通过浏览器设置或其他方式,阻止网站在其计算机或设备上存储和读取cookie信息。
解决方案
- 1、Url拼接:将
SessionID放在请求的url里面https://javaguide.cn/?Session_id=xxx。Session_id一般需要加密 - 2、使用单独的隐藏表单进行发送,每次点击按钮提交出发表单提交
- 3、使用localStorage进行存储和读取发送
cookie存放在浏览器F12的application的storage的Cookie下面, 如果当前网站请求返回了cookie,在下次登陆就自动携带 token 可以存放在Cookie中或者application的storage的 localStorage 下面,
为什么 Cookie 无法防止 CSRF 攻击,而 Token 可以?
CSRF(Cross Site Request Forgery) 一般被翻译为 跨站请求伪造 。那么什么是 跨站请求伪造 呢?说简单点,就是用你的身份去发送一些对你不友好的请求。举个简单的例子:
小壮登录了某网上银行,他来到了网上银行的帖子区,看到一个帖子下面有一个链接写着“科学理财,年盈利率过万”,小壮好奇的点开了这个链接,结果发现自己的账户少了 10000 元。这是这么回事呢?原来黑客在链接中藏了一个请求,这个请求直接利用小壮的身份给银行发送了一个转账请求,也就是通过你的 Cookie 向银行发出请求。
<a src=http://www.mybank.com/Transfer?bankId=11&money=10000>科学理财,年盈利率过万</>上面也提到过,进行 Session 认证的时候,我们一般使用 Cookie 来存储 SessionId,当我们登陆后后端生成一个 SessionId 放在 Cookie 中返回给客户端,服务端通过 Redis 或者其他存储工具记录保存着这个 SessionId,客户端登录以后每次请求都会带上这个 SessionId,服务端通过这个 SessionId 来标示你这个人。如果别人通过 Cookie 拿到了 SessionId 后就可以代替你的身份访问系统了。
Session 认证中 Cookie 中的 SessionId 是由浏览器发送到服务端的,借助这个特性,攻击者就可以通过让用户误点攻击链接,达到攻击效果。 主要就是因为cookie会自动被浏览器携带发送
但是,我们使用 Token 的话就不会存在这个问题,在我们登录成功获得 Token 之后,一般会选择存放在 localStorage (浏览器本地存储)中。然后我们在前端通过某些方式会给每个发到后端的请求加上这个 Token,这样就不会出现 CSRF 漏洞的问题。因为,即使你点击了非法链接发送了请求到服务端,这个非法请求是不会携带 Token 的,所以这个请求将是非法的。

需要注意的是:不论是 Cookie 还是 Token 都无法避免 跨站脚本攻击(Cross Site Scripting)XSS 。
跨站脚本攻击(Cross Site Scripting)缩写为 CSS 但这会与层叠样式表(Cascading Style Sheets,CSS)的缩写混淆。因此,有人将跨站脚本攻击缩写为 XSS。
XSS 中攻击者会用各种方式将恶意代码注入到其他用户的页面中。就可以通过脚本盗用信息比如 Cookie 。
推荐阅读:如何防止 CSRF 攻击?—美团技术团队
什么是 OAuth 2.0?
OAuth 是一个行业的标准授权协议,主要用来授权第三方应用获取有限的权限。而 OAuth 2.0 是对 OAuth 1.0 的完全重新设计,OAuth 2.0 更快,更容易实现,OAuth 1.0 已经被废弃。详情请见:rfc6749。
实际上它就是一种授权机制,它的最终目的是为第三方应用颁发一个有时效性的令牌 Token,使得第三方应用能够通过该令牌获取相关的资源。
OAuth 2.0 比较常用的场景就是第三方登录,当你的网站接入了第三方登录的时候一般就是使用的 OAuth 2.0 协议。
另外,现在 OAuth 2.0 也常见于支付场景(微信支付、支付宝支付)和开发平台(微信开放平台、阿里开放平台等等)。
下图是 Slack OAuth 2.0 第三方登录的示意图:

跨域请求
后端设置 Access-Control-Allow-Origin : *
防抖
- 前端:通过setTimeout,即一段时间内只会发送一次请求,并且配合clearTimeout,这样用户连续多次点击,只会发送一次请求
- 每次点击会清除延时,重新开始,即上一次的请求并没有发送
点击查看完整代码实现
点击查看完整代码实现
function pay(){
console.log("done");
}
function sent(func, delay){
let timer; // 这里的 timer 是相当于一个全局变量
return function () { // 使用闭包
let context = this;
let args = arguments;
clearTimeout(timer);
timer = setTimeout(function (){
func.apply(context,arguments); // 未知
},delay);
}
}
button.addEventListener("click", sent(pay, 1000)):::
推荐阅读:
