Spring Cloud Gateway YML routing – 有没有办法检查权限?

huangapple 未分类评论45阅读模式
英文:

Spring Cloud Gateway YML routing - is there a way to check permissions?

问题

我有一些微服务,以及一个使用Spring Cloud的网关。我正在尝试在网关中设置路由。理想情况下,我希望在YML文件中设置路由,或者使用一个RouteLocator bean。

但是目前,在我的网关中,对于每个路由,我都有REST端点,只是使用WebClient将请求发送到下游。

(在此之前,我有一个ReactiveAuthenticationManager过滤器,用于验证JWT令牌。它返回一个包含从令牌中获取的一些用户权限的UsernamePasswordAuthenticationToken)。

以下是一个示例,我已经设置了到名为"tracking service"的微服务的路由:

控制器:

@RestController
@RequestMapping("/tracking-service/tracking")
public class TrackingController {

  @Autowired
  private TrackingService trackingService;

  @GetMapping
  public Flux getAllTracking() {
    return trackingService.getAllTracking();
  }

}

服务:

@Service
public class TrackingService {

  private WebClient webClient;

  @PreAuthorize("hasAuthority('MANAGER')")
  public Flux getAllTracking() {
    // 发起到跟踪服务的HTTP请求
  }

}

我之所以这样做是因为使用了@PreAuthorize注解。如果客户端的JWT令牌不包含'MANAGER'令牌,那么这将返回403禁止状态。并非所有的端点都需要'MANAGER'权限,有些端点需要其他权限。

我的问题是 - 在YML中进行路由时是否可以做到这一点?我希望看到类似于这样的内容,但我不确定是否可能?我已经阅读了Spring文档并查看了所有可用的过滤器,但似乎没有看到可以执行此任务的过滤器。

spring:
  cloud:
    gateway:
      routes:
        - id: tracking
          uri: http://tracking-service
          predicates:
            - Path=/tracking-service/**
          filters:
            - StripPrefix=1
            - PreAuthorize=hasAuthority('MANAGER')

谢谢。

英文:

I have some microservices, and a Gateway using Spring Cloud. I'm trying to set up the routing in the Gateway. Ideally, I would like to set up the routing in the YML file, or with a RouteLocator bean.

But currently, in my Gateway, I have REST endpoints for every route, which is just sending the request onwards using a WebClient.

(Prior to this, I have a ReactiveAuthenticationManager filter which validates a JWT token. It returns a UsernamePasswordAuthenticationToken which includes some user authorities it gets from the token).

Here's an example where I have set up a route to a microservice called the tracking service:

Controller:

@RestController
@RequestMapping("/tracking-service/tracking")
public class TrackingController {

  @Autowired
  private TrackingService trackingService;

  @GetMapping
  public Flux getAllTracking() {
    return trackingService.getAllTracking();
  }

}

Service:

@Service
public class TrackingService {

  private WebClient webClient;

  @PreAuthorize("hasAuthority('MANAGER')")
  public Flux getAllTracking() {
    //Make HTTP call to the tracking service
  }

}

The reason I have done it this way is because of the @PreAuthorize annotation. If the client's JWT token does not include the 'MANAGER' token, then this will return a 403 forbidden status. Not all of the endpoints require the MANAGER authority and some of the endpoints require other authorities.

My question - is it possible to do this when routing with the YML? I was hoping to see something that looks like this, but I'm not sure it is possible? I have read the Spring docs and looked at all the available filters, and there was nothing that does this job that I could see.

spring:
  cloud:
    gateway:
      routes:
        - id: tracking
          uri: http://tracking-service
          predicates:
            - Path=/tracking-service/**
          filters:
            - StripPrefix=1
            - PreAuthorize=hasAuthority('MANAGER')

Thanks.

答案1

得分: 0

API网关和授权是两个关注点的分离。理想情况下,授权不应该混合在网关应用程序中。对于权限,您可以直接将其映射到服务,如下所示。

@RestController
public class ResourceREST {

    @RequestMapping(value = "/resource/", method = RequestMethod.GET)
    @PreAuthorize("@customPermissionEvaluator.hasPrivilege(authentication,'somepermission')")
    public Mono<ResponseEntity<?>> user() {
        return Mono.just(ResponseEntity.ok(new Message("Access allowed")));
    }
}

并定义自定义权限评估器

@Service
public class CustomPermissionEvaluator {

    public boolean hasPrivilege(Authentication auth, String permission) {
        String requiredPermissionCheck = permission.toLowerCase();
        for (GrantedAuthority grantedAuth : auth.getAuthorities()) {
            if (grantedAuth.getAuthority().contains(requiredPermissionCheck)) {
                return true;
            }
        }
        return false;
    }
}

因此,网关在路由中不提供任何授权,这是理想的。

英文:

API Gateway and authorization are two separation of concern. Ideally authorization should not be mixed in gateway application. For permission you can directly map it to service like this.

@RestController
public class ResourceREST {

	@RequestMapping(value = &quot;/resource/&quot;, method = RequestMethod.GET)
	 @PreAuthorize(&quot;@customPermissionEvaluator.hasPrivilege(authentication,&#39;somepermission&#39;)&quot;)
	public Mono&lt;ResponseEntity&lt;?&gt;&gt; user() {
		return Mono.just(ResponseEntity.ok(new Message(&quot;Access allowed&quot;)));
	}
}

And define custom permission evaluator

@Service
public class CustomPermissionEvaluator {

	public boolean hasPrivilege(Authentication auth, String permission) {
		String requiredPermissionCheck = permission.toLowerCase();
		for (GrantedAuthority grantedAuth : auth.getAuthorities()) {
			if (grantedAuth.getAuthority().contains(requiredPermissionCheck)) {
				return true;
			}
		}
		return false;
	}
}

As such gateway does not provide any authorization in the routing which is ideal.

huangapple
  • 本文由 发表于 2020年4月6日 19:21:40
  • 转载请务必保留本文链接:https://java.coder-hub.com/61058620.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定