**
项目描述 **
基于SSM框架整合和Spring Security框架对用户的登录和资源权限查看即用户的认证和授权进行操作,从而进入系统后台通过与MySQL数据库交互来完成商品以及订单的查询与添加操作,并使用SpringAOP切面来完成日志收集。
主要知识点
Spring Security框架
基于spring security安全框架的用户管理主要分为两部分即认证和授权。从认证和授权两方面大概了解一下spring security的工作原理。
工作原理
Spring Security所解决的问题就是安全访问控制,而安全访问控制功能其实就是对所有进入系统的请求进行拦截, 校验每个请求是否能够访问它所期望的资源。
当初始化Spring Security时,会创建一个名为 SpringSecurityFilterChain 的Servlet过滤器,类型为org.springframework.security.web.FilterChainProxy,它实现了javax.servlet.Filter,因此外部的请求会经过此类,下图是Spring Security过滤器链结构图:
文章图片
FilterChainProxy是一个代理,真正起作用的是FilterChainProxy中SecurityFilterChain所包含的各个Filter,同时 这些Filter作为Bean被Spring管理,它们是Spring Security核心,各有各的职责,但他们并不直接处理用户的认 证,也不直接处理用户的授权,而是把它们交给了认证管理器(AuthenticationManager)和决策管理器 (AccessDecisionManager)进行处理。
spring Security功能的实现主要是由一系列过滤器链相互配合完成
文章图片
认证
系统为什么要认证? 认证是为了保护系统的隐私数据与资源,用户的身份合法方可访问该系统的资源。
认证 :用户认证就是判断一个用户的身份是否合法的过程,用户去访问系统资源时系统要求验证用户的身份信 息,身份合法方可继续访问,不合法则拒绝访问。常见的用户身份认证方式有:用户名密码登录,二维码登录,手机短信登录,指纹认证等方式。
会话方式分为基于session方式和token方式。
其中基于session认证方式的流程是,用户认证成功后,在服务端生成用户相关的数据保存在session(当前会话),而发给客户端的 sesssion_id 存放到 cookie 中,这样用客户端请求时带上session_id 就可以验证服务器端是否存在 session 数据,以此完成用户的合法校验。当用户退出系统或session过期销毁时,客户端的session_id也就无效了。基于session的认证机制是由Servlet规范定制,Servlet容器已实现,用户通过HttpSession的操作方法即可实现。
基于token的交互流程是,用户认证成功后,服务端生成一个token发给客户端,客户端可以放到 cookie 或 localStorage 等存储中,每次请求时带上 token,服务端收到token通过验证后即可确认用户身份。
认证流程
- 用户提交密码和用户名。
- 通过UsernamePasswordAuthenticationFilter将请求信息封装到Authentication,实现类为UsernamePasswordAuthenticationToken。
- 然后过滤器将Authentication提交至认证管理器(AuthenticationManager)进行认证
- 认证成功后, AuthenticationManager 身份管理器返回一个被填充满了信息的(包括上面提到的权限信息, 身份信息,细节信息,但密码通常会被移除) Authentication 实例。(AuthenticationManager接口(认证管理器)是认证相关的核心接口,也是发起认证的出发点,它的实现类为ProviderManager。而Spring Security支持多种认证方式,因此ProviderManager维护着一个 List 列表,存放多种认证方式,最终实际的认证工作是由 AuthenticationProvider完成的。其中web表单的对应的AuthenticationProvider实现类为 DaoAuthenticationProvider,它的内部又维护着一个UserDetailsService负责UserDetails的获取。UserDetailsService通过loadUserByUsername()方法获取用户信息,使用UserDetails来封装用户信息。最终 AuthenticationProvider将UserDetails填充至Authentication。)
- SecurityContextHolder 安全上下文容器将第3步填充了信息的 Authentication ,通过 SecurityContextHolder.getContext().setAuthentication(…)方法,设置到其中。
为什么要授权? 认证是为了保证用户身份的合法性,授权则是为了更细粒度的对隐私数据进行划分,授权是在认证通过后发生的, 控制不同的用户能够访问不同的资源。
授权: 授权是用户认证通过根据用户的权限来控制用户访问资源的过程,拥有资源的访问权限则正常访问,没有 权限则拒绝访问。
如何进行授权?一般使用RBAC授权,基于资源的访问控制是按资源(或权限)进行授权的,比如:用户必须具有查询工资权限才可以查询员工工资信息等。其优点是系统可扩展性强。
授权的方式包括 web授权和方法授权。
web授权是通过url拦截进行授权,方法授权是通过方法拦截进行授权。他们都会调用accessDecisionManager进行授权决策,若为web授权则拦截器为FilterSecurityInterceptor;若为方法授权则拦截器为MethodSecurityInterceptor。如果同时通过web授权和方法授权则先执行web授权,再执行方法授权,最后决策通过,则允许访问资源,否则将禁止访问。
授权流程
- 拦截请求,已认证用户访问受保护的web资源将被SecurityFilterChain中的 FilterSecurityInterceptor 的子类拦截。
- 获取资源访问策略,FilterSecurityInterceptor会从 SecurityMetadataSource 的子类 DefaultFilterInvocationSecurityMetadataSource 获取要访问当前资源所需要的权限 Collection 。 SecurityMetadataSource其实就是读取访问策略的抽象,而读取的内容,其实就是我们配置的访问规则。
- 最后,FilterSecurityInterceptor会调用 AccessDecisionManager 进行授权决策,若决策(投票)通过,则允许访问资源,否则将禁止访问
项目流程梳理
首先基于SSM的整合基础上完成商品的查询,添加以及订单的查询,分页以及订单详情查询(主要是多表查询操作),这部分相对来说比较基础,主要说一下SSM三大框架的整合,spring与spring mvc的整合主要是配置spring提供的ContextLoaderListener监听器,启动服务器时加载spring容器,存储ContextServlet对象。spring与mybatis的整合主要是把dao的代理对象放进spring容器,即在spring的配置文件中配置连接池对象,配置SqlSession的工厂和配置扫描dao接口的包。其次的商品和订单的查询添加操作就是由页面发送请求去controller层再去调用service层再去调用dao层从而去从数据库获取相关信息。其中分页操作使用的是mybatis的分页插件PageHelper。订单查询涉及产品表,会员表以及多对多的旅客表。
其次最为主要的便是用户的管理,角色的管理以及资源权限的管理。其中用户表和角色表,角色表和权限表都是多对多的关系。先说一下用户的登录认证操作流程:
文章图片
认证结束之后对用户详情进行查询,其中包含角色,权限等信息。
授权之前要将用户角色权限的关系关联,其中用户与角色多对多只需要在中间表user_role插入数据即可。同样的方法也用于角色与权限之间的关系建立。
权限控制也就是用户授权分为服务端方法控制和页面端标签控制。
Spring Security在方法的权限控制上支持三种类型的注解,JSR-250注解、@Secured注解和支持表达式的注解,这三种注解默认都是没有启用的,需要单独通过global-method-security元素的对应属性进行启用。
JSR-250注解:一般使用@RolesAllowed表示访问对应方法时所应该具有的角色。(示例: @RolesAllowed({“USER”, “ADMIN”}) 该方法只要具有"USER", "ADMIN"任意一种权限就可以访问。这里可以省 略前缀ROLE_,实际的权限可能是ROLE_ADMIN)
支持表达式的注解:@PreAuthorize 在方法调用之前,基于表达式的计算结果来限制对方法的访问
@PostAuthorize 允许方法调用,但是如果表达式计算结果为false,将抛出一个安全性异常等
@Secured注解:@Secured注解标注的方法进行权限控制的支持,其值默认为disabled。
【SSM整合的企业权限管理系统】页面端:在jsp页面中我们可以使用spring security提供的权限标签来进行权限控制
常用标签
在jsp中我们可以使用以下三种标签,其中authentication代表的是当前认证对象,可以获取当前认证对象信息,例如用户名。其它两个标签我们可以用于权限控制
authentication
property: 只允许指定Authentication所拥有的属性,可以进行属性的级联获取,如“principle.username”,不允许直接通过方法进行调用
htmlEscape:表示是否需要将html进行转义。默认为true。
scope:与var属性一起使用,用于指定存放获取的结果的属性名的作用范围,默认我pageContext。Jsp中拥有的作用范围都进行进行指定
var: 用于指定一个属性名,这样当获取到了authentication的相关信息后会将其以var指定的属性名进行存放,默认是存放在pageConext中
authorize
authorize是用来判断普通权限的,通过判断用户是否具有对应的权限而控制其所包含内容的显示
access: 需要使用表达式来判断权限,当表达式的返回结果为true时表示拥有对应的权限
method:method属性是配合url属性一起使用的,表示用户应当具有指定url指定method访问的权限,
method的默认值为GET,可选值为http请求的7种方法
url:url表示如果用户拥有访问指定url的权限即表示可以显示authorize标签包含的内容
var:用于指定将权限鉴定的结果存放在pageContext的哪个属性中
accesscontrollist
accesscontrollist标签是用于鉴定ACL权限的。其一共定义了三个属性:hasPermission、domainObject和var,其中前两个是必须指定的
hasPermission:hasPermission属性用于指定以逗号分隔的权限列表
domainObject:domainObject用于指定对应的域对象
var:var则是用以将鉴定的结果以指定的属性名存入pageContext中,以供同一页面的其它地方使用。
最后就是AOP日志的收集,创建一个切面类处理日志,加入前置通知注解,主要获取访问时间,访问的类,访问的方法。后置通知主要获取日志中时长,ip,url。调用service,调用dao将sysLog插入数据库。
推荐阅读
- java|整合SSM框架全步骤
- 分布式|MQ介绍,RabbitMQ在SpringAMQP中的使用
- java|SpringSecurity安全性框架详解
- Java|某程序员在网吧敲代码,出类拔萃,网友(为何我被打的却是我)
- 字符串|7行代码让B站崩溃3小时,竟因“一个诡计多端的0”
- spring|spring,springboot,springmvc底层原理解析
- springboot|一文详解Spring、SpringBoot、Springcloud的关系与区别
- #|SpringBoot2学习笔记一--Spring与SpringBoot2
- #|Servlet 架构思路(MVC)