EverydayOneCat
新年🧧!
GateWay网关
Spring cloud gateway是spring官方基于Spring 5.0、Spring Boot2.0和Project Reactor等技术开发的网关,Spring Cloud Gateway旨在为微服务架构提供简单、有效和统一的API路由管理方式,Spring Cloud Gateway作为Spring Cloud生态系统中的网关,目标是替代Netflix Zuul,其不仅提供统一的路由方式,并且还基于Filer链的方式提供了网关基本的功能,例如:安全、监控/埋点、限流等。
在spring cloud入门种我们介绍了GateWay的原理和使用,在此项目中其实就是代替nginx实现路由转发。这样我们配置完成后只需要启动网关和Nacos就能实现nginx效果了。
1.创建模块
在infrastructure模块下创建api_gateway模块
在pom.xml引入依赖:
1 | <dependencies> |
编写application.yml配置文件
1 | server: |
启动类平平无奇,记得加服务注册注解
2.网关相关配置
1、创建配置类CorsConfig
1 |
|
2、全局Filter,统一处理会员登录与外部不允许访问的服务
1 | import com.google.gson.JsonObject; |
3.自定义异常处理
服务网关调用服务时可能会有一些异常或服务不可用,它返回错误信息不友好,需要我们覆盖处理
(1)ErrorHandlerConfig:
1 | import org.springframework.beans.factory.ObjectProvider; |
(2)JsonExceptionHandler:
1 | import org.springframework.boot.autoconfigure.web.ErrorProperties; |
开发权限管理接口
1.需求分析
在一般权限管理中,通常有三个最基础的实体:菜单、角色、用户。
我们需在数据库中定义相关的表并将他们的关系弄清楚。
2.创建权限管理服务
在service模块下创建子模块service-acl,依赖和配置和其他差不多。
2.1获取所有菜单
controller:
1 |
|
Service实现递归查找所有菜单
1 | //========================递归查询所有菜单================================================ |
2.2递归删除菜单
Controller:
1 |
|
Service:
1 | //递归删除菜单 |
2.3给角色分配权限
Controller:
1 |
|
Service:
1 | //给角色分配权限 |
整合SpringSecurity
Spring Security 基于 Spring 框架,提供了一套 Web 应用安全性包括用户认证(Authentication)和用户授权(Authorization)两个部分。
1.认证与授权实现思路
如果系统的模块众多,每个模块都需要就行授权与认证,所以我们选择基于token的形式进行授权与认证,用户根据用户名密码认证成功,然后获取当前用户角色的一系列权限值,并以用户名为key,权限列表为value的形式存入redis缓存中,根据用户名相关信息生成token返回,浏览器将token记录到cookie中,每次调用api接口都默认将token携带到header请求头中,Spring-security解析header头获取token信息,解析token获取当前用户名,根据用户名就可以从redis中获取权限列表,这样Spring-security就能够判断当前请求是否有权限访问。
简单来说,当用户在一个模块登陆时,SpringSecurity一方面会将用户信息权限等数据通过key-value存于redis中,同时另一方面以token形式将用户名相关信息转化发送给客户端让其存于cookie中。接着当我们访问另一个模块时,请求头就会带着token被SpringSecurity拦截并解析获取用户名,接着用用户名查询redis,就会得到权限信息。、
2.创建模块
在common下创建spring_security模块,引入相关依赖
1 | <dependencies> |
代码结构说明:
2.1核心配置类
Spring Security的核心配置就是继承WebSecurityConfigurerAdapter并注解@EnableWebSecurity的配置。
1 | import org.springframework.beans.factory.annotation.Autowired; |
2.2认证授权相关的工具类
(1)DefaultPasswordEncoder:密码处理的方法
1 | package com.atguigu.serurity.security; |
(2)TokenManager:token操作的工具类
1 | import io.jsonwebtoken.CompressionCodecs; |
(3)TokenLogoutHandler:退出实现
1 | import com.atguigu.commonutils.R; |
(4)UnauthorizedEntryPoint:未授权统一处理
1 | import com.atguigu.commonutils.R; |
2.3创建认证授权实体类
User:
1 | import io.swagger.annotations.ApiModel; |
SecutityUser:
1 | import lombok.Data; |
2.4创建认证和授权的filter
(1)TokenLoginFilter:认证的filter
1 | /** |
(2)TokenAuthenticationFilter授权filter:
1 | /** |
3.创建自定义查询用户类
在service_acl模块创建,因为其他模板不会用到
SpringSecurity认证需要实现UserDetailsService这个接口,我们在service_acl模块下创建UserDetailsServiceImpl,用户登录通过MySQL库下的acl_user进行验证
1 |
|
4.SpringSecurity实现过程分析
一图看懂:
1、首先当我们登录时,前端请求的是”/admin/acl/login”这个地址,而我们再SpringSecurity中定义了会拦截此请求用作登录
2、在SpringSecurity中会默认找UserDetailsService的实现类来实现登录验证方法,我们在service_acl中定义了此方法返回securityUser对象,通过查询acl_user表来实现验证
3、登陆成功后调用successfulAuthentication方法实现:
- 获取securityUser返回对象
- 根据对象里面用户名生成token
- 把用户名和权限信息放到redis
- 返回带有用户名信息的token
4、当用户访问其他模块时,SpringSecurity的授权过滤器会调用方法从请求头中读取token信息并解析成用户名再从redis中读取权限信息。
其实这里设计的有点小问题:由于我们需要让用户名成为存到redis中的key,因此我们在数据库设计表时需要让用户名user_name是unique的。但是这种有一个缺陷就是当逻辑删除后,再想取之前逻辑删除的用户名依然是不可取的,这一点可以从token的设计角度解决。
5.前后端整体流程分析
由于课程中并未对前端整合过多讲解,前端和后端交互的整体流程欠缺认知。
这里分享阳光少年勇闯天涯大佬的视频:https://www.bilibili.com/video/BV13K4y1f7DX?p=2&spm_id_from=pageDriver
大佬讲的很全面,基本是全栈高手了😍
结语
Silence,wench,
I do not wish to be horny anymore,
I just want to be happy.