完成权限管理需要三个对象
在权限管理的概念中,有两个非常重要的名词:
认证:通过用户名和密码成功登陆系统后,让系统得到当前用户的角色身份。
授权:系统根据当前用户的角色,给其授予对应可以操作的权限资源。
- 用户:主要包含用户名,密码和当前用户的角色信息,可实现认证操作。
- 角色:主要包含角色名称,角色描述和当前角色拥有的权限信息,可实现授权操作。
- 权限:权限也可以称为菜单,主要包含当前权限名称,url地址等信息,可实现动态展示菜单。
注:这三个对象中,用户与角色是多对多的关系,角色与权限是多对多的关系,用户与权限没有直接关系,二者是通过角色来建立关联关系的。
系统安全和系统保护设计
在实际开发过程中,为了保证我们的系统能够安全稳定的运行下去,一般都要从下面两点来考虑:
- 系统安全性:防止非法入侵、非法请求、非法拦截等。我们需要阻止和屏蔽不信任的请求源访问,保证数据的安全可靠,不被人窃取。
- 系统健壮性:也就是系统可用性,最常见的解决方案就是做服务 “冗余”。当然量级够大的话,要做的事情会很多很多,比如限流、熔断、降级等等。
这里只简单的谈一谈系统的安全性,在项目的开发中需要从全方位、多角度做工作,以确保整个业务链路、整个体系范围都能保证安全。下面就大致介绍下在实际开发过程中,开发者经常用到的一些方法:
- 数据校验,包括前端 js 校验和后端校验,其实前端校验主要是为了体验,也就是尽可能降低出错率,提高一次性提交的成功率。也可以说前端校验规则是后端校验的子集。
- 防止命令注入,比如最常见的 SQL 注入,它不是利用操作系统的 BUG 来实现攻击,而是针对程序员编程时的疏忽,通过 SQL 语句,实现无帐号登录,甚至篡改数据库。
- 认证安全,对于使用应用的实体,无论是人还是系统程序,都应当做到对每个请求都能找到对应的责任实体。因此,在处理请求前,要先对认证信息进行检测。
- 登录鉴权,即要控制这个用户登录后能在系统中做什么,比如一般要把用户分为外部用户、员工等。
- 数据加密,对于敏感数据,不得明文传输和明文存储。如数据存储中,密码等信息我们可以加密后再存储;数据传输中,对密文使用 DES3/RSA 加密。
- 请求签名,在外部请求时也是常见的处理方式,只有通过接口签名验证的请求,才信任为合法的请求。
在系统的安全方面,我们的 Spring Security 框架,解决的最主要的问题就是 认证安全 和 登录鉴权。
Spring Security 核心功能介绍
Spring Security 其核心就是一组过滤器链,项目启动后将会自动配置。最核心的就是 Basic Authentication Filter 用来认证用户的身份,一个在 Spring Security 中一种过滤器处理一种认证方式。比如,对于 username password 认证过滤器来说:
- 会检查是否是一个登录请求;
- 是否包含 username 和 password (也就是该过滤器需要的一些认证信息);
- 如果不满足则放行给下一个。
然后下一个认证过滤器,再次按照自身职责判定是否是自身需要的信息。中间可能还有更多的认证过滤器,只要有一个认证过滤器通过了,就是用户登录成功。
在整个过滤器中的最后一环是 FilterSecurityInterceptor
,这里会判定该请求是否能进行访问 REST 服务,如果被拒绝了就会抛出不同的异常(根据具体的原因)。Exception Translation Filter
会捕获抛出的错误,然后根据不同的认证方式进行信息的返回提示。
认证授权分析
用户在进行资源访问时,要求系统要对用户进行权限控制,其具体流程如图-1所示:
简单来说,认证就是登录,授权其实就是权限的鉴别,看用户是否具备相应请求的权限。
SpringSecurity 架构设计
鸟瞰SpringSecurity 基本技术架构,例如:
绿色部分是认证过滤器,需要我们自己配置,可以配置多个认证过滤器。认证过滤器可以使用 Spring Security 提供的认证过滤器,也可以自定义过滤器(例如:短信验证)。认证过滤器要在 configure(HttpSecurity http)方法中配置,没有配置不生效。下面会重点介绍以下三个过滤器:
UsernamePasswordAuthenticationFilter 过滤器:该过滤器会拦截前端提交的 POST 方式的登录表单请求,并进行身份认证。
BasicAuthenticationFilter:检测和处理 http basic 认证。
ExceptionTranslationFilter 过滤器:该过滤器不需要我们配置,对于前端提交的请求会直接放行,捕获后续抛出的异常并进行处理(例如:权限访问限制)。
FilterSecurityInterceptor 过滤器:该过滤器是过滤器链的最后一个过滤器,根据资源权限配置来判断当前请求是否有权限访问对应的资源。如果访问受限会抛出相关异常,并由 ExceptionTranslationFilter 过滤器进行捕获和处理。
SpringSecurity实现后端模块式登录
在Spring Security,默认使用Session机制存储成功登录的用户信息(因为HTTP协议是无状态协议,并不保存客户端的任何信息,所以,同一个客户端的多次访问,对于服务器而言,等效于多个不同的客户端各访问一次,为了保存用户信息,使得服务器端能够识别客户端的身份,必须采取某种机制),当下,更推荐使用Token或相关技术(例如JWT)来解决识别用户身份的问题。
要在Spring Security中使用JWT,至少需要:
不能让Spring Security按照原有模式来处理登录(原有模式中,登录成功后,自动装用户信息存储到Session中,且跳转页面),需要
- 需要自动装配AuthenticationManager对象
- 使得SecurityConfiguration配置类继承自WebSecurityConfigurerAdapter类,重写其中的xx方法,在此方法中直接调用父级方法即可,并在此方法上添加@Bean注解
创建AdminLoginDTO类,此类中应该包含用户登录时需要提交的用户名、密码
-
创建IAdminService接口
-
在IAdminService接口中添加登录的抽象方法
String login(AdminLoginDTO adminLoginDTO);
- 创建AdminServiceImpl类,实现以上接口
- 在实现过程中,调用AuthenticationManager实现认证,当认证成功后,生成JWT并返回
-
创建AdminController类,在类中处理登录请求
-
在SecurityConfiguration中配置Spring Security,对特定的请求进行放行(默认所有请求都必须先登录)
SpringSecurity实现前后端分离式模块登录
参考文件
- SpringSecurity入门使用
- 用户认证流程
- SpringSecurity图片验证码
- SpringSecurity添加记住我功能
- SpringSecurity短信验证码接口发送
- SrpingSecurity的Session管理与退出登录
- 使用Spring Security控制授权
- JWT实现SSO单点登录
- SpringSecurity用户身份认证与授权
本文由 liyunfei 创作,采用 知识共享署名4.0
国际许可协议进行许可
本站文章除注明转载/出处外,均为本站原创或翻译,转载前请务必署名
最后编辑时间为: Aug 10,2022