【问题标题】:How to get Authorization header from an MethodInterpcetor on micronaut?如何从 micronaut 上的 MethodInterpcetor 获取授权标头?
【发布时间】:2021-06-22 18:52:57
【问题描述】:

在一切之前,我尝试了这两种解决方案,但对我不起作用
Equivalent of javax.ws.rs NameBinding in Micronaut?
https://blogs.ashrithgn.com/custom-annotation-to-handle-authorisation-in-micronaut-aop-tutorial/

在我的应用程序中,我必须在 Authorization 标头中获取一个字符串,然后从 base64 解码它,然后 json 将其转换为 POJO。当然,字符串是 jwt,我需要解码 json 的公共部分以从字段中获取数据。
从技术上讲,客户端会将标头转发给我以获取、解码并提取数据。 (这是非常糟糕的做法,但这是我必须做的)。

为此,我使用的是 micronaut 2.4.1,这是我的代码:

拦截器:

public class HeadInterceptor implements MethodInterceptor<Object, Object> {
    @SneakyThrows
    @Override
    public Object intercept(MethodInvocationContext<Object, Object> context) {

        Request request = (Request) context.getParameterValueMap().get("request");
        // Where do i get Authorization header?
        // i.e String token = (String) context.getParameterValueMap().get("Authorization");
        String token = "eyJhdWQiOiJ0ZXN0IiwiaXNzIjoidGVzdCIsInN1YiI6InRlc3QiLCJleHAiOjExMTExMTEsImlhdCI6MTExMTExMTEsImRhdGEiOiJ0ZXN0In0=";

        ObjectMapper mapper = new ObjectMapper();
        Info info = mapper.readValue(new String(Base64.getDecoder().decode(token)), Info.class);
        request.setData(info.getSub().toUpperCase());

        return context.proceed();
    }
}

控制器:

@Controller("/main")
public class MainController {

    @Post
    @Head
    public Single<Response> index(@Body @Valid Request request) {
        return Single.just(
                Response.builder()
                        .message(String.format("%s-%s", request.getData(), request.getInfo()))
                        .build()
        );
    }
}

这是一个示例应用程序https://github.com/j1cs/micronaut-jacksonxml-error
(忽略名称用于其他问题)

【问题讨论】:

    标签: java micronaut


    【解决方案1】:

    在您的实现中,无法在拦截器中显示标头,因为您的 index 方法没有将其作为参数接收。

    因此,如果您将其添加为如下参数:

    ...
    @Post
    @Head
    public Single<Response> index(@Body @Valid Request request, @Header("Authorization") String authorizationHeader) {
        return Single.just(
                Response.builder()
                        .message(String.format("%s-%s", request.getData(), request.getInfo()))
                        .build()
        );
    }
    ...
    

    然后,您可以通过getParameterValues()intercept 方法中检索它。基本上,它将是第二个参数。

    ...
    @SneakyThrows
    @Override
    public Object intercept(MethodInvocationContext<Object, Object> context) {
        ...
        String token = (String) context.getParameterValues()[1];
        ...
    }
    ...
    

    更新

    由于您希望 Request 包含正文和标题,因此我稍微编辑了解决方案。基本上,标头作为成员变量添加到Request,如下所示:

    public class Request {
        @NotNull
        @NotBlank
        private String info;
        private String data;
    
        @Header("Authorization")
        String authorizationHeader;
    } 
    

    然后,在 Request 参数上使用 @RequestBean 而不是 @Body 注释:

    ...
    @Post
    @Head
    public Single<Response> index(@RequestBean @Valid Request request) {
        return Single.just(
                Response.builder()
                        .message(String.format("%s-%s", request.getData(), request.getInfo()))
                        .build()
        );
    }
    ...
    

    最后,您可以在intercept() 方法中轻松访问标题,如下所示:

    @SneakyThrows
    @Override
    public Object intercept(MethodInvocationContext<Object, Object> context) {
        ...   
        Request request = (Request) context.getParameterValueMap().get("request");
        String token = request.authorizationHeader;
        ...
    }
    

    我为此更改创建了一个拉取请求 here,因此您可以检查它是如何工作的

    【讨论】:

      【解决方案2】:

      为了解决问题,你可以先把问题分成几部分。

      第 1 部分:如何获取任意标题(或列出所有标题)?

      尝试使用request.getHeaders()doc

      第 2 部分:如何获取名为 Authorization 的标头?

      使用第 1 部分中的方式。另外,请注意 case。比如Authorizationauthorization一样吗?


      方法二:

      在控制器中 (https://github.com/j1cs/micronaut-jacksonxml-error/blob/master/src/main/java/me/jics/MainController.java):

      public Single<Response> index(@Body Request request, @Header('Authorization') String authorization) {
      ...
      }
      

      附言“标题”注释的文档在这里:https://docs.micronaut.io/2.0.1/api/io/micronaut/http/annotation/Header.html

      在拦截器中:

      ...
      String token = context.getParameterValueMap().get("authorization");
      ...
      

      为什么代码是这样的

      1. 首先通过参数注入获取你想要的auth header。
      2. 其次,回忆一下 AOP / AspectJ(拦截器类使用的)的基本概念。在您的拦截器中,您拦截了一个方法(在您的例子中,是控制器中的 index 方法。因此,您可以愉快地获取该方法的参数。在上面的代码中,只是 authorization 参数。

      如果您卡在某个地方,请告诉我(并粘贴代码和输出)。

      【讨论】:

        猜你喜欢
        • 2014-09-19
        • 2018-04-17
        • 1970-01-01
        • 1970-01-01
        • 2019-12-12
        • 2014-07-31
        • 2016-09-14
        • 2017-07-07
        • 1970-01-01
        相关资源
        最近更新 更多