搭建个人OpenAPI (2)

新建AccessFilter ,继承ZuulFilter,来实现权限验证

@Component public class AccessFilter extends ZuulFilter { private final AccessInfoService accessInfoService; public AccessFilter(AccessInfoService accessInfoService) { this.accessInfoService = accessInfoService; } @Override public String filterType() { return PRE_TYPE; } @Override public int filterOrder() { return 0; } @Override public boolean shouldFilter() { return true; } @Override public Object run() { RequestContext currentContext = RequestContext.getCurrentContext(); HttpServletRequest request = currentContext.getRequest(); if (!isAuthorized(request)) { HttpStatus httpStatus = HttpStatus.UNAUTHORIZED; currentContext.setSendZuulResponse(false); currentContext.setResponseStatusCode(httpStatus.value()); } return null; } /** * 判断请求是否有权限 * * @param request * @return */ private boolean isAuthorized(HttpServletRequest request) { // 检查请求参数是否包含 access_key String access_key = request.getParameter("access_key"); if (!StringUtils.isEmpty(access_key)) { // 检查 access_key 是否匹配 List<AccessInfo> accessInfos = accessInfoService.findAll(); Optional<AccessInfo> accessInfo = accessInfos.stream() .filter(s -> access_key.equals(s.getAccessKey())).findAny(); if (accessInfo.isPresent()) { return true; } return false; } return false; } }

启动网关服务,访问 :8080/open-api/v1/info

如果请求参数不带access_key,网关服务会直接返回 401 未授权的错误;

如果请求参数带access_key,但是与我们数据库的安全验证不匹配,网关服务也会直接返回 401 错误;

image-20200113164209186

请求access_key,也通过后台数据库验证,则调用成功

image-20200113164052292

权限缓存

以上已经实现了基本权限的验证,但是每次api的请求,都会进行数据库的校验。

2020-01-13 16:44:43.591 INFO 25028 --- [trap-executor-0] c.n.d.s.r.aws.ConfigClusterResolver : Resolving eureka endpoints via configuration Hibernate: select accessinfo0_.access_key as access_k1_0_, accessinfo0_.access_desc as access_d2_0_, accessinfo0_.access_status as access_s3_0_, accessinfo0_.create_time as create_t4_0_, accessinfo0_.update_time as update_t5_0_, accessinfo0_.visit_module as visit_mo6_0_ from access_info accessinfo0_ Hibernate: select accessinfo0_.access_key as access_k1_0_, accessinfo0_.access_desc as access_d2_0_, accessinfo0_.access_status as access_s3_0_, accessinfo0_.create_time as create_t4_0_, accessinfo0_.update_time as update_t5_0_, accessinfo0_.visit_module as visit_mo6_0_ from access_info accessinfo0_ Hibernate: select accessinfo0_.access_key as access_k1_0_, accessinfo0_.access_desc as access_d2_0_, accessinfo0_.access_status as access_s3_0_, accessinfo0_.create_time as create_t4_0_, accessinfo0_.update_time as update_t5_0_, accessinfo0_.visit_module as visit_mo6_0_ from access_info accessinfo0_

实际生产中肯定不能这么操作,对数据库的压力太大,所以,我们要对权限验证的数据进行缓存。

首先,在启动类上增加@EnableCaching注解

@EnableDiscoveryClient @EnableZuulProxy @SpringBootApplication @EnableCaching public class ApiGatewayApplication { public static void main(String[] args) { SpringApplication.run(ApiGatewayApplication.class, args); } }

AccessInfo需要实现Serializable接口,方便序列化后保存在redis中。

@Data @Entity public class AccessInfo implements Serializable { //... }

获取所有访问权限信息的方法上增加缓存处理

@Cacheable(value = "api-gateway:accessInfo") public List<AccessInfo> findAll() { return accessInfoRepository.findAll(); }

重新启动服务后,多调用几次api接口,发现第一次加载时会调用一次数据库,后面都是取缓存中的权限信息,不再查询数据库。

限流控制

RateLimiter是guava提供的基于令牌桶算法的实现类,可以非常简单的完成限流特技,并且根据系统的实际情况来调整生成token的速率。

新建RateLimitFilter继承ZuulFilter,定义一个RateLimiter,这里为了测试方便,每秒设置最多2个请求

/** * 限流 */ @Component public class RateLimitFilter extends ZuulFilter { //每秒产生N个令牌 private static final RateLimiter rateLimiter = RateLimiter.create(2); @Override public String filterType() { return PRE_TYPE; } @Override public int filterOrder() { return SERVLET_DETECTION_FILTER_ORDER - 1; } @Override public boolean shouldFilter() { return true; } @Override public Object run() { if (!rateLimiter.tryAcquire()) { RequestContext currentContext = RequestContext.getCurrentContext(); HttpStatus httpStatus = HttpStatus.TOO_MANY_REQUESTS; currentContext.setSendZuulResponse(false); currentContext.setResponseStatusCode(httpStatus.value()); } return null; } }

重启服务后,1s内如果多次访问接口,会提示 429 Too Many Requests错误,这样限流的功能就完成了

image-20200113184107059

部署环境 微服务注册

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpyfsg.html