我如何修改 Micronaut Http Filter 的顺序,以便它在 Micronaut Security 之后执行
How can i modify the order of Micronaut Http Filter so it get executed after Micronaut Security
我有一个 checkForBankId 注释
@Target(value = { ElementType.METHOD, ElementType.TYPE, ElementType.ANNOTATION_TYPE })
@Retention(value=RetentionPolicy.RUNTIME)
public @interface checkForBankId {
boolean ignore() default false;
}
我有一个 BankIdSecurityService
public class BankIdSecurityService {
/*
* This is declarative client to call the
* InternalAPIs to get all details about the user;
*/
@Inject
UserRepositoryClient client;
static final boolean AUTHORIZED = true;
static final boolean UnAUTHENTICATED = false;
Flowable<Boolean> checkAuthentication(HttpRequest<?> request) {
if (routeMatch instanceof MethodBasedRouteMatch) {
MethodBasedRouteMatch<?, ?> methodBasedRouteMatch =
(MethodBasedRouteMatch<?, ?>) routeMatch;
if (methodBasedRouteMatch.hasAnnotation(checkForBankId.class)) {
String userName = getUserName(request).get();
if(!request.getParameter().contains("bankId")) {
return Flowable.just(UNAUTHORIZED);
}
return this.client.getUser(userName).map(userDetails -> {
String bankId = request.getParameter().get("bankId");
BankAccount[] bankAccounts = userDetails.getPayload().getBankAccounts();
boolean bankIdFound = false;
for(BankAcconut bankAccout: bankAccounts) {
if(bankAccount.getId().equals(bankId)) {
bankIdFound = true;
break;
}
}
return bankIdFound ? AUTHENTICATED : UNAUTHORIZED;
});
}
}
return Flowable.just(AUTHENTICATED);
}
Optional<String> getUserName(HttpRequest<?> request) {
// get jwt from request header
then parse the jwt and extract
the username from it and return;
}
}
然后我有每个请求执行一次的过滤器
@Filter(Filter.MATCH_ALL_PATTERN)
@AllArgsConstructor
@Slf4j
public class BankIdSecurityFilter extends OncePerRequestHttpServerFilter {
private final BankIdSecurityService bankIdSecurityService;
@Override
protected Publisher<MutableHttpResponse<?>> doFilterOnce(
HttpRequest<?> request, ServerFilterChain chain
) {
log.info("request route: {}", request);
return this.bankIdSecurityService
.checkAuthentication(request).switchMap(authResult -> {
log.info("authentication result: {}", authResult);
return authResult ? // if authResult is true then proceed as usual
chain.proceed(request) :
Publishers.just(HttpResponse.status(HttpStatus.BAD_REQUEST)
.body("This bankId doesn't belond to this user.")
); // return bad request
});
}
@Override
public int getOrder() {
return ServerFilterPhase.SECURITY.after();
}
}
在控制器内部,我们在要过滤请求的地方应用@CheckForBankId
@CheckForBankId
@GET("get-bank-account?{bankId}")
Single<BankAccount> getBankAccount(String bankId) {
return someService.getBankAccount(bankId);
}
过滤器工作正常。缺少的是它在 microanut 之前执行
安全性 因此,进入 header 的令牌未经身份验证,在某些情况下它可以
导致一些问题,比如如果过期的令牌传递给 header 并且我的解析器将解析
令牌并将 return 来自它的用户,但它没有任何意义,因为令牌已经无效。它应该在进入过滤器之前就已经被拒绝了..所以,像这个过滤器一样
在 micronaut 安全之后执行。我尝试覆盖 getOrder 方法,但它不起作用:(
您没有指定您使用的是哪个 Micronaut 版本,但答案是该行为是一个错误。它应该在 Micronaut 2.5.4
中按预期工作
我有一个 checkForBankId 注释
@Target(value = { ElementType.METHOD, ElementType.TYPE, ElementType.ANNOTATION_TYPE })
@Retention(value=RetentionPolicy.RUNTIME)
public @interface checkForBankId {
boolean ignore() default false;
}
我有一个 BankIdSecurityService
public class BankIdSecurityService {
/*
* This is declarative client to call the
* InternalAPIs to get all details about the user;
*/
@Inject
UserRepositoryClient client;
static final boolean AUTHORIZED = true;
static final boolean UnAUTHENTICATED = false;
Flowable<Boolean> checkAuthentication(HttpRequest<?> request) {
if (routeMatch instanceof MethodBasedRouteMatch) {
MethodBasedRouteMatch<?, ?> methodBasedRouteMatch =
(MethodBasedRouteMatch<?, ?>) routeMatch;
if (methodBasedRouteMatch.hasAnnotation(checkForBankId.class)) {
String userName = getUserName(request).get();
if(!request.getParameter().contains("bankId")) {
return Flowable.just(UNAUTHORIZED);
}
return this.client.getUser(userName).map(userDetails -> {
String bankId = request.getParameter().get("bankId");
BankAccount[] bankAccounts = userDetails.getPayload().getBankAccounts();
boolean bankIdFound = false;
for(BankAcconut bankAccout: bankAccounts) {
if(bankAccount.getId().equals(bankId)) {
bankIdFound = true;
break;
}
}
return bankIdFound ? AUTHENTICATED : UNAUTHORIZED;
});
}
}
return Flowable.just(AUTHENTICATED);
}
Optional<String> getUserName(HttpRequest<?> request) {
// get jwt from request header
then parse the jwt and extract
the username from it and return;
}
}
然后我有每个请求执行一次的过滤器
@Filter(Filter.MATCH_ALL_PATTERN)
@AllArgsConstructor
@Slf4j
public class BankIdSecurityFilter extends OncePerRequestHttpServerFilter {
private final BankIdSecurityService bankIdSecurityService;
@Override
protected Publisher<MutableHttpResponse<?>> doFilterOnce(
HttpRequest<?> request, ServerFilterChain chain
) {
log.info("request route: {}", request);
return this.bankIdSecurityService
.checkAuthentication(request).switchMap(authResult -> {
log.info("authentication result: {}", authResult);
return authResult ? // if authResult is true then proceed as usual
chain.proceed(request) :
Publishers.just(HttpResponse.status(HttpStatus.BAD_REQUEST)
.body("This bankId doesn't belond to this user.")
); // return bad request
});
}
@Override
public int getOrder() {
return ServerFilterPhase.SECURITY.after();
}
}
在控制器内部,我们在要过滤请求的地方应用@CheckForBankId
@CheckForBankId
@GET("get-bank-account?{bankId}")
Single<BankAccount> getBankAccount(String bankId) {
return someService.getBankAccount(bankId);
}
过滤器工作正常。缺少的是它在 microanut 之前执行 安全性 因此,进入 header 的令牌未经身份验证,在某些情况下它可以 导致一些问题,比如如果过期的令牌传递给 header 并且我的解析器将解析 令牌并将 return 来自它的用户,但它没有任何意义,因为令牌已经无效。它应该在进入过滤器之前就已经被拒绝了..所以,像这个过滤器一样 在 micronaut 安全之后执行。我尝试覆盖 getOrder 方法,但它不起作用:(
您没有指定您使用的是哪个 Micronaut 版本,但答案是该行为是一个错误。它应该在 Micronaut 2.5.4
中按预期工作