英文:
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 = "/resource/", method = RequestMethod.GET)
@PreAuthorize("@customPermissionEvaluator.hasPrivilege(authentication,'somepermission')")
public Mono<ResponseEntity<?>> user() {
return Mono.just(ResponseEntity.ok(new Message("Access allowed")));
}
}
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.
专注分享java语言的经验与见解,让所有开发者获益!
评论