在互联网中我们一致都有提到或接触到关于认证和授权概念或名字,那到底什么是认证?什么是授权?他们两又有什么联系和区别呢?本系列将记录自己近一段时间学习和实践的过程,以便加深理解过程。
我们先来一起认识两个单词authentication
和 authorization
,有没有发现什么特点,我第一次接触到的时候,我一直都分不清楚这两个单词的意思(其实就是英语差)。直到后续学习的过程中经常会碰到它们,我才理解了这两个词的意思,在接下来的文章中,你也可能会经常看见它们。
1.1 什么是认证
在互联网中,我们每天都会使用到各种各样的APP和网站,在使用过程中通常还会遇到需要注册登录的情况,输入你的用户名和密码才能正常使用,也就是说成为这个应用的合法身份才可以访问应用的资源,这个过程就是认证。当然认证的方式有很多,常见的账号密码登录,手机验证码登录,指纹登录,刷脸登录等等。
1.2 什么是会话
当一个用于认证通过以后,为了避免用户的每次操作都进行认证,这个时候就需要保持一个用户认证状态的会话,常见的认证会话机制有很多,例如session
认证,token
认证等。
基于session的认证方式
用户认证成功后,在服务端生成用户相关的数据保存在当前会话session
中,发给客户端的 SesssionId
会存放到 cookie
中,这样用户客户端请求时带上 SesssionId
就可以验证服务器端是否存在 session
数 据,以此完成用户的合法校验,当用户退出系统或session
过期销毁时,客户端的SesssionId
也就无效了。
基于token的认证方式
用户认证成功后,服务端生成一个token发给客户端,客户端可以放到 cookie 或 localStorage等存储中,每次请求时带上 token,服务端收到token通过验证后即可确认用户身份。
基于session
的认证方式由Servlet
规范定制,服务端要存储session
信息需要占用内存资源,客户端需要支持cookie
;
基于token
的方式则一般不需要服务端存储token
,并且不限制客户端的存储方式。如今移动互联网时代 更多类型的客户端需要接入系统,系统多是采用前后端分离的架构进行实现,所以基于token
的方式更适合。
1.3 什么是授权
授权是用户认证通过根据用户的权限来控制用户访问资源的过程,拥有资源的访问权限则正常访问,没有 权限则拒绝访问。例如视频网站的VIP用户,可以查看到普通用户看不到的资源信息。
1.4 授权的数据模型
授权过程中,我们需要知道如何对用户访问的资源进行控制,需要了解一些简单的授权数据模型。
授权可以非常简单的理解成谁(Who)对什么(What)进行怎么样(How)的操作。
- Who 即主体(Subject),一般指用户,也可以是应用程序
- What 即资源(Resource),例如商品信息,订单信息,页面按钮或程序中的接口等信息。
- How 即权限(Permission),规定了用户或程序对资源操作的许可。例如普通用户只能查看订单,管理员可修改或删除订单,这是因为普通用户和管理员用户对订单资源的操作权限不一样。
通常主体、资源、权限相关的数据模型通常会包含以下几个部分
- 主体Subject(用户ID,账号,密码...)
- 资源Resource(资源ID,资源名称,访问地址...)
- 权限Permission(权限ID、权限标识、权限名称,对应的资源ID...)
- 角色Role(角色ID,角色名称...)
你会发现权限中包含了一个资源ID,多个权限可指向一个资源,我们是否可以直接在权限信息中把资源信息包含进来呢?当然,这也是很多企业开发中的做法,将权限和资源合并为 权限(权限ID、权限标识、权限名称、资源名称、资源访问地址、...)
1.4 RBAC设计模型
1.4.1 基于角色的访问控制
RBAC基于角色的访问控制(Role-Based Access Control)是按角色进行授权。
例如当用户角色为总经理时,他就可以查询公司的某员工的工资情况,用伪代码的方式我们可以这样表示
if(Subject.hasRole("总经理角色ID")){
// 查询员工工资
}
现在突然来了个需求,要求公司的部门经理也可以查看员工的工资情况,怎么做呢?再加一个判断就好了嘛
if(Subject.hasRole("总经理角色ID") || Subject.hasRole("部门经理角色ID")){
// 查询员工工资
}
这时候我们发现了一个问题,当哪天修改角色的权限时,就需要修改授权相关的代码,系统可扩展性较差。
1.4.2 基于资源的访问控制
RBAC基于资源的访问控制(Resource-Based Access Control)是按资源(或权限)进行授权。
同样是上面的需求,这时候我们的代码变成了
if(Subject.hasPermission("查询员工工资的权限标识")){
// 查询员工工资
}
当哪天行政主管角色的用户需要查询员工的工资时,我们只需要为行政主管的角色添加一个查询员工工资的权限即可,不需要去修改授权相关的代码,系统的可扩展性增强了。
(完)