sdudoc-动态路由

动态路由实际上就是动态配置API网关的路由参数。这样就可以实现在不重启服务的情况下,API路由规则的动态配置。
在这里选用Spring Cloud Gateway进行处理。

Spring Cloud Gateway是Spring Cloud家族中的一款API网关。因为之前 Zuul 2.x 的不断跳票,Spring Cloud 才釜底抽薪推出了自己的服务网关:Spring Cloud Gateway。Gateway 建立在 Spring Webflux上,目标是提供一个简洁、高效的API网关,同时也可以快速的拼装上Spring Cloud全家桶的API网关

Spring Cloud Gateway包含特性:

  • 能够自由设置任何请求属性的路由
  • 路由可以自由设置断言(Predicates)和过滤器(Filter)
  • 可集成熔断器
  • Spring Cloud DiscoveryClient原生支持
  • 流量限速
  • 路径重写
    那么相比较于直接修改application的
    动态路由,就是在API服务网关启动之后,路由关系可取决于外部环境的变化而变化,比如通过注册中心的不同的微服务、数据库中的映射路由关系等,动态的改变路由关系。Spring Cloud Gateway也提供了两种动态路由的方式,一种是Spring Cloud DiscoveryClient原生支持、一种是基于Actuator API。

Spring Cloud DiscoveryClient

Spring Cloud原生支持服务自动发现并且注册到路由之中,通过在application.properties中设置spring.cloud.gateway.discovery.locator.enabled=true ,同时确保 DiscoveryClient 的实体 (Netflix Eureka, Consul, 或 Zookeeper) 已经生效,即可完成服务的自动发现及注册。

创建路由关系:

{
  "id": "first_route",
  "predicates": [{
    "name": "Path",
    "args": {"_genkey_0":"/first"}
  }],
  "filters": [],
  "uri": "https://www.uri-destination.org",
  "order": 0
}]

删除:
需要使用 DELETE 请求到 /gateway/routes/{id_route_to_delete}

但上述方法自由度仍然受限。

基于服务注册发现的Spring Cloud DiscoveryClient,需要全部服务在Spring Cloud家族体系下,一旦有外部路由关系,会将思维负载化。Actuator API是一种外部API调用,虽然能够解决90%以上的问题,但是对于高度定制化的需求,频繁定制增删改查路由的API,难免会有bug,甚至修改时会造成服务的瞬时不可用。所以我们对其进行修改。采取的修改思路是动态修改,即请求进来时,以GlobalFilter的方式动态修改路由地址。

主要处理思路如下:

/**
 * 设置请求头中包含网关信息的全局过滤器
 * 用于标识网关转发的请求,防止微服务被直接请求
 * 加密方式:将JWT进行Bcrypt加密,并将加密后的字符串放入请求头中,各微服务拦截请求头并进行校验,防止被恶意访问
 */

所以,定义了鉴权管理器,用于判断是否有资源的访问权限。

/**
 * 鉴权管理器,用于判断是否有资源的访问权限
 */
@Component
class AuthorizationManager : ReactiveAuthorizationManager<AuthorizationContext> {
//    @Resource
//    private val redisTemplate: RedisTemplate<String, Any>? = null

对应跨域的预检请求直接放行

    if (request.method == HttpMethod.OPTIONS) {
            return Mono.just(AuthorizationDecision(true))
        }

从Redis中获取当前路径可访问角色列表

        val uri = authorizationContext.exchange.request.uri
//        val obj = redisTemplate!!.opsForHash<String, String>()[RedisConstant.RESOURCE_ROLES_MAP, uri.path]

//        var authorities = Convert.toList(String::class.java, obj)
        var authorities = listOf<String>("TEST", "ADMIN")
        authorities =
            authorities.stream().map { i: String -> AuthConstant.AUTHORITY_PREFIX + i }.collect(Collectors.toList())

        

认证通过且角色匹配的用户可访问当前路径

return authentication
            .filter(Predicate { obj: Authentication -> obj.isAuthenticated })
            .flatMapIterable(Function<Authentication, Iterable<GrantedAuthority>> { obj: Authentication -> obj.authorities })
            .map<String> { obj: GrantedAuthority -> obj.authority } // 判断当前用户是否有权限访问当前路径
            .any(Predicate { o: String? -> authorities.contains(o) })
            .map<AuthorizationDecision>(Function { granted: Boolean? -> AuthorizationDecision(granted!!) })
            .defaultIfEmpty(AuthorizationDecision(false))

其他:

自定义两种返回结果:没有登录或token过期、没有权限

/**
 * 网关白名单,可使得部分请求越过网关
 * 通过在配置文件中配置, 如下:
 * secure:
 *   ignore:
 *      urls:
 *        - "/api/user/login"
 */

@param publisher 用于更新路由信息
@param nacosConfigManager nacos配置管理器

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Chi Z犬里

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值