GitHub轻松阅读微服务实战项目流程详解【第二天:API网关的设计与实现】
Two Day
- 1.配置文件精解
- (1)bootstrap.yml文件
- (2)nacos中关于gateway的配置信息
- (3)applicaton.properties白名单配置
- 2.代码详解
- (1)IP限流
- (2)白名单
- (3)Jwt工具类验证token的有效性
- (4)网关层面快速失败返回接口
- (5)微服务安全认证流程
- (6)身份认证过滤器实现
github地址:https://github.com/Zealon159/light-reading-cloud
该网关层面使用Spring GateWay进行实现。
1.配置文件精解
(1)bootstrap.yml文件
spring:application:# 服务逻辑名称name: light-reading-cloud-gatewaycloud:nacos:# 配置中心config:server-addr: xxxxxxfile-extension: ymlrefresh: trueshared-dataids: light-reading-cloud-gateway.yml #Data IDnamespace: 4d109a4d-f34d-4e86-9e39-c2d36db24b00 #命名空间# 注册中心discovery:server-addr: xxxxxnamespace: 4d109a4d-f34d-4e86-9e39-c2d36db24b00
(2)nacos中关于gateway的配置信息
server:port: 8010spring:application:# 服务逻辑名称name: light-reading-cloud-gatewaycloud:gateway:discovery:locator:enabled: true #开启gateway的注册和发现lowerCaseServiceId: true #将请求路径中的服务名小写,因为服务注册时,Nacos将其转换成大写了routes: #路由匹配- id: book-center-rpc uri: lb://light-reading-cloud-book #服务地址predicates: #断言,匹配路径和请求方式- Path=/book/**- Method=GETfilters:# 降级配置- name: Hystrixargs:name: fallbackcmdfallbackUri: forward:/fallback #失败了直接跳转到该路据,这个接口是用户失败后快速返回的# 限流配置- name: RequestRateLimiterargs:redis-rate-limiter.replenishRate: 3 # 每秒允许处理的请求数量redis-rate-limiter.burstCapacity: 5 # 每秒最大处理的请求数量key-resolver: "#{@ipKeyResolver}" # 限流策略,对应策略的Bean,在gateway配置了该IP的限流策略- id: homepage-rpcuri: lb://light-reading-cloud-homepagepredicates:- Path=/index/**filters:# 降级配置- name: Hystrixargs:name: fallbackcmdfallbackUri: forward:/fallback# 限流配置- name: RequestRateLimiterargs:redis-rate-limiter.replenishRate: 3redis-rate-limiter.burstCapacity: 5key-resolver: "#{@ipKeyResolver}"- id: account-center-rpcuri: lb://light-reading-cloud-accountpredicates:- Path=/account/**filters:# 降级配置- name: Hystrixargs:name: fallbackcmdfallbackUri: forward:/fallback# 限流配置- name: RequestRateLimiterargs:redis-rate-limiter.replenishRate: 3redis-rate-limiter.burstCapacity: 5key-resolver: "#{@ipKeyResolver}"hystrix:threadpool:default:coreSize: 20 #并发执行的最大线程数,默认10maxQueueSize: 1000 #BlockingQueue的最大队列数,默认值-1queueSizeRejectionThreshold: 400
ribbon:eager-load:enabled: true #开启Ribbon的饥饿模式, 用于点对点直连问题clients: light-reading-cloud-account,light-reading-cloud-book,light-reading-cloud-homepage
(3)applicaton.properties白名单配置
system.properties=/account/user/register,/account/user/login
这个本地application.properties是配置的白名单信息,后面会在配置类中进行加载。
2.代码详解
(1)IP限流
@Configuration
public class RedisRateLimiterConfig {/*** 按客户端IP限流* Lambda表达式或者匿名函数都可以快速实现* @return*/@Beanpublic KeyResolver ipKeyResolver() { return exchange -> Mono.just(exchange.getRequest().getRemoteAddress().getHostName());}
}
这个ipKeyResolver方法是在gateway配置文件中引用的
(2)白名单
@Data
@Component
public class SystemPropertiesConfig {/** 请求白名单,引用application.preperties中的属性 */@Value("${system.properties}")private String whitelist;
}
(3)Jwt工具类验证token的有效性
Token比较适用于微服务的安全认证,JWT是一种安全认证规范,token中存储了用户信息,只有在服务端才能根据密钥进行解密。
public class JwtUtil {/*** 身份认证* @param jwt 令牌* @return 成功状态返回200,其它均为失败*/public static Result<User> validationToken(String jwt) {try {//解析JWT字符串中的数据,并进行最基础的验证Claims claims = Jwts.parser().setSigningKey(SECRET_KEY).parseClaimsJws(jwt).getBody();//如果解析成功,将其封装到User返回User user = new User();user.setUuid(claims.get("uuid").toString());user.setLoginName(claims.get("loginName").toString());user.setNickName(claims.get("nickName").toString());if (claims.get("phoneNumber") != null) {user.setPhoneNumber(claims.get("phoneNumber").toString());}user.setId(Integer.parseInt(claims.get("id").toString()));user.setHeadImgUrl(claims.get("headImgUrl").toString());return ResultUtil.success(user);} catch (ExpiredJwtException e) {// 已过期令牌return ResultUtil.authExpired();} catch (SignatureException e) {// 伪造令牌return ResultUtil.unAuthorized();} catch (Exception e) {// 系统错误return ResultUtil.unAuthorized();}}}
(4)网关层面快速失败返回接口
public class FallbackController {@GetMapping("/fallback")public Result fallback() {return ResultUtil.fail();}
}
(5)微服务安全认证流程
常用的认证方式主要有三种:Session、HTTP Basic Authentication 和 Token。
- session 是认证中最常用的一种方式,也是最简单的。用户登录后将信息存储在后端,客户端则通过 Cookie 中的 SessionId 来标识对应的用户。
- HTTP Basic Authentication 也就是 HTTP 基本认证,它是 HTTP 1.0 提出的一种认证机制。HTTP 基本认证的原理是客户端在请求时会在请求头中增加 Authorization,Authorization 是用户名和密码用 Base64 加密后的内容。服务端获取 Authorization Header 中的用户名与密码进行验证。
- Token 中会存储用户的信息,然后通过加密算法进行加密,只有服务端才能解密,服务端拿到 Token 后进行解密获取用户信息。
Token更适用于微服务的安全认证,本项目采用了token这种认证方式,并基于JWT的安全认证规范。
jwt是一种认证规范,它允许我们通过jwt在用户和服务器之间传递可靠的信息。在通信过程中进行身份认证
Ⅰ.用户进行登录时,将用户名和密码提交给认证服务器,服务器会验证用户提交信息的合法性,如果验证成功,则会返回一个token,客户端将token保存起来
Ⅱ.用户再次请求服务器时,一般会将token放到请求头中。当请求达到网关后,会在网关中对token进行校验;如果校验成功,网关会将其转发到后端服务中,转发时会将用户信息一并传递过去,这样后端服务就不用再进行校验了。
(1)网关是唯一的入口,所以微服务之间的请求就不需要再进行认证。
(2)有些请求是不需要进行认证的,所以我们加入了白名单进行处理。
(3)jwt的认证过程主要是加密,而加密会耗费CPU的运算资源。如果请求量过大,可以将token缓存起来,这样可以提高网关服务器CPU的性能。
(6)身份认证过滤器实现
对于认证过滤器实现类GlobalFilter和Ordered接口
1.GlobalFilter是gateway中的一个全局过滤器
2.我们知道gateway中的核心由一个过滤器链组成,这个过滤器链中的一个个过滤器是由Ordered进行排序的,数值越小越靠前执行。
3.ServerWebExchange是gateway中的一个网络交换器,它的内部封装了HTTP请求信息和响应信息,我们可以在Filter中根据这个ServerWebExchange对请求信息或者响应信息进行拦截,然后进行响应的操作。
4.consumer是Java8提供了一个消费性函数式接口,对此我们可以通过lambda快速向请求头中加入解析后的用户信息
5.一般情况下,请求和响应中的信息是不能修改的,但gateway为我们提供类一个mutate方法,专门用来修改请求和响应信息。由于我们通过ServerWebExchange进行数据交换的,所以我们可以先将信息追加到ServerHttpRequest中,然后再将ServerHttpRequest封装到ServerWebExchange中。
/*** 身份认证过滤器* @author: Ronin* @since: 2021/10/5* @email:* 统一认证的实现方式是自定义实现全局过滤器,在过滤器里面可以处理白名单放行、认证校验、动态处理请求参数等*/
@Component
public class AuthFilter implements GlobalFilter, Ordered {@Autowired //白名单配置类private SystemPropertiesConfig systemPropertiesConfig;@Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {// 白名单Path,获取白名单,获取配置文件中的白名单Set<String> whiteList = this.getWhiteList();//获取请求信息中的请求路径String path = exchange.getRequest().getPath().toString();// 主页接口、图书接口正则匹配,如果匹配这两个表示不用登录就可以访问boolean indexMatch = Pattern.matches("/index[^\\s]*", path);boolean bookMatch = Pattern.matches("/book/[^\\s]*", path);// 白名单接口、开放接口放行if (whiteList.contains(path) || bookMatch || indexMatch) {return chain.filter(exchange);}String[] segments = path.split("/");if (!whiteList.contains(segments[1])) {// 认证--从请求头中获取token,通过jwt进行校验String token = exchange.getRequest().getHeaders().getFirst("token");Result<User> result = JwtUtil.validationToken(token);if (result.getCode() == HttpCodeEnum.OK.getCode()) {// 认证通过User user = result.getData();// 追加请求头用户信息Consumer<HttpHeaders> httpHeaders = httpHeader -> {httpHeader.set("userId",user.getId().toString());httpHeader.set("nickName",user.getNickName());};ServerHttpRequest serverHttpRequest = exchange.getRequest().mutate().headers(httpHeaders).build();exchange.mutate().request(serverHttpRequest).build();return chain.filter(exchange);}// 认证过期、失败,均返回401ServerHttpResponse response = exchange.getResponse();//将对象转换为byte - json字符串byte[] bits = JSONObject.toJSONString(result).getBytes(StandardCharsets.UTF_8);DataBuffer buffer = response.bufferFactory().wrap(bits);response.setStatusCode(HttpStatus.UNAUTHORIZED);// 指定编码,否则在浏览器中会中文乱码response.getHeaders().add("Content-Type", "text/plain;charset=UTF-8");return response.writeWith(Mono.just(buffer));}return chain.filter(exchange);}@Overridepublic int getOrder() {return 0; //数值越小,该过滤器越向前执行}/*** 请求白名单* @return*/private Set<String> getWhiteList(){String whitelists = this.systemPropertiesConfig.getWhitelist();if (StringUtils.isEmpty(whitelists)) {return new HashSet<>();}Set<String> whiteList = new HashSet<>();String[] whiteArray = whitelists.split(",");for (int i = 0; i < whiteArray.length; i++) {whiteList.add(whiteArray[i]);}return whiteList;}
}
GitHub轻松阅读微服务实战项目流程详解【第二天:API网关的设计与实现】相关推荐
- GitHub轻松阅读微服务实战项目流程详解【第一天:数据库表设计及其环境搭建、项目运行】
One Day 1.数据库表详解 2.项目环境准备 github地址:https://github.com/Zealon159/light-reading-cloud 项目服务端主要使用SpringB ...
- GitHub轻松阅读微服务实战项目流程详解【第四天:账户服务的设计与实现】
Four Day 1.配置文件精解 (1)boootstrap.yml (2)配置中心的yml文件 2.Config (1)书架线程池配置 (2)Mybatis及其Swagger配置 (3)Redis ...
- GitHub轻松阅读微服务实战项目流程详解【第三天:公共模块的设计与实现】
Three Day 1.缓存 (1)账户中心缓存Key (2)图书资源缓存Key (3)精品页缓存key (5)缓存操作类 2.常量 (1)精品页常量类 (2)jwt常量类 3.图书相关枚举 (1)图 ...
- go设置后端启动_名企实习项目|后端开发岗go微服务实战项目启动,大牛导师带你拿offer!...
「DAC实习项目早知道」 今天是第2期实习项目推送 --go微服务实战项目-- 岗位职责 Position Description 1.负责协助高质量的设计和编码: 2.主要语言为Golang: 3. ...
- go设置后端启动_名企实习项目 | 后端开发岗go微服务实战项目启动,大牛导师带你拿offer!...
「DAC实习项目早知道」 今天是第2期实习项目推送 --go微服务实战项目-- 微服务是近年来非常流行的架构,是后端开发工程师必备技能. 什么是微服务? 微服务(Microservices Archi ...
- 【最新最全】Java微服务实战项目【尚医疗】_智慧医疗管理项目_基于若依框架快速开发
尚医疗是专门为各大医院.门诊提供的一款医疗管理平台.系统包含:系统管理.药品进销存管理.看病就诊.收费管理.检查管理.数据统计等核心模块.通过尚医疗系统可以快速.方便的管理病人从挂号到门诊结束所涉及到 ...
- Java微服务实战项目推荐
以下是我推荐的几个Java微服务实战项目: Spring Cloud微服务电商项目:这是一个完整的电商应用程序,使用Spring Cloud实现微服务架构.它包括注册中心.配置中心.网关.商品服务.订 ...
- APP开发项目流程详解,长知识了!
APP的开发流程并不复杂,APP开发人员一般都包含着UI设计师 .前端开发.后端开发.测试专员.产品经理等等. 而根据开发人员的分工不同,可以把APP的开发项目流程分为三个阶段:需求阶段–开发阶段–发 ...
- 微服务实战项目-学成在线-课程发布模块
学成在线-课程发布模块 1 模块需求分析 1.1 模块介绍 课程信息编辑完毕即可发布课程,发布课程相当于一个确认操作,课程发布后学习者在网站可以搜索到课程,然后查看课程的详细信息,进一步选课.支付.在 ...
最新文章
- 华为手机媒体音量自动静音_华为手机的音量键还可以这么用,涨见识!
- 干货丨一文介绍机器学习中基本的数学符号
- 马云“赢在中国”对于80后创业者的忠告
- LeetCode Additive Number(递归)
- 印象笔记电脑版使用技巧_印象笔记使用攻略
- php mysql 非空_MySQL非空约束(NOT NULL)
- Android 中的接口回调
- Go在谷歌:以软件工程为目的的语言设计
- Apache Zookeeper入门1
- 执行NET 命令无法使用超过20个字符的组名或用户名
- Microsoft Visual Studio Installer Project模板下载太慢解决办法
- c++ opencv [ INFO:0] global c:\build\master_winpack-build-win64-vc15\***
- java mysql图书馆管理系统源码+论文
- 基于ATtiny85制作MIDI数字音乐盒
- 深度学习数据增强方法-内含(亮度增强,对比度增强,旋转图图像,翻转图像,仿射变化扩充图像,错切变化扩充图像,HSV数据增强)七种方式进行增强-每种扩充一张实现7倍扩)+ 图像缩放代码-批量
- worldwind 三维模型加载优化总结
- 绝地求生一直崩溃的异常解决
- urllib库(二)parse模块:urlparse()/urlsplit(),parse_qs()/parse_qsl(),urlunparse()/urlunsplit(),urlencode()
- 就这样,我走完了程序员的前五年...
- 大数据、云计算、物联网、数据仓库、OLAP、OLTP、等大数据你必须知道并且了解的概念及相关关系,我的一些总结
热门文章
- 影响一生的职业建议 [转] - 看懂了不一定在高位,在高位的必须看懂了、信息量很大,多学学!...
- 壊小子的学习【日常阅读篇】(四)与阅读有关的那些事儿
- 需求规格说明书格式及要求
- web服务器网站网速慢的原因,apache配置优化 - 解决apache环境下网站访问速度慢的问题...
- 拉马车 的游戏 c语言编程,蓝桥杯 拉马车(模拟)
- stm32g474教程_STM32-开发入门教程
- android 相机纹理,Android平台Camera实时滤镜实现方法探讨(五)--GLSurfaceView实现Camera预览...
- url充定向 html转义,html、javascript、url特殊字符的转义诠释及使用方法详解
- mac笔记本怎么外接显示屏_苹果MAC笔记本怎么外接显示器?
- 计算机一级b考试理论知识,全国计算机等级考试一级b知识点