美文网首页
springboot-grpc服务拦截器应用

springboot-grpc服务拦截器应用

作者: DuffyHuang | 来源:发表于2019-04-29 17:55 被阅读0次

grpc-server 自定义拦截器实现,适用于server端做鉴权认证场景

在上篇文章 springboot集成grpc服务 基础上,拦截器实现如下

@Slf4j
@GrpcGlobalServerInterceptor
@Component
public class AuthServerInterceptor implements ServerInterceptor {

    private final static String TOKEN = "test_token";
    private final static String APPID = "test_appId";
    @Override
    public <ReqT, RespT> ServerCall.Listener<ReqT> interceptCall(ServerCall<ReqT, RespT> serverCall, Metadata metadata, ServerCallHandler<ReqT, RespT> serverCallHandler) {
        //获取客户端参数
        log.info("header received from client:" + metadata);
        Metadata.Key<String> token = Metadata.Key.of("token", Metadata.ASCII_STRING_MARSHALLER);
        final Metadata.Key<String> appId = Metadata.Key.of("appId", Metadata.ASCII_STRING_MARSHALLER);
        String tokenStr = metadata.get(token);
        final String appIdStr = metadata.get(appId);
        if(!(APPID.equals(appIdStr)&& TOKEN.equals(tokenStr))) {
            //认证失败,关闭连接
            log.info("appId:{},token:{} 认证失败,关闭连接",appIdStr,tokenStr);
            serverCall.close(Status.DATA_LOSS,metadata);
        }
        //服务端写回参数
        ServerCall<ReqT, RespT> call = new ForwardingServerCall.SimpleForwardingServerCall<ReqT, RespT>(serverCall) {
            @Override
            public void sendHeaders(Metadata headers) {
                //由于grpc服务是全双工的,因此我们也可以向客户端推送 Metadata 数据
                headers.put(appId,appIdStr);
                super.sendHeaders(headers);
            }
        };
        return serverCallHandler.startCall(call,metadata);
    }
}

grpc-client 如何在header中设置参数?

1、只设置客户端请求时附带的header,见类 io.grpc.stub.MetadataUtils,其中有个工具方法可直接设置:

    @ExperimentalApi("https://github.com/grpc/grpc-java/issues/1789")
    public static <T extends AbstractStub<T>> T attachHeaders(T stub, Metadata extraHeaders) {
        return stub.withInterceptors(new ClientInterceptor[]{newAttachHeadersInterceptor(extraHeaders)});
    }

Metadata参数对于调用者不太友好,我们希望入参可能是个Map<String,String>,可以简单封装下

private static <T extends AbstractStub<T>> T attachHeaders(T stub, final Map<String, String> headerMap) {
        Metadata extraHeaders = new Metadata();
        if (headerMap != null) {
            for (String key : headerMap.keySet()) {
                Metadata.Key<String> customHeadKey = Metadata.Key.of(key, Metadata.ASCII_STRING_MARSHALLER);
                extraHeaders.put(customHeadKey, headerMap.get(key));
            }
        }
        return MetadataUtils.attachHeaders(stub, extraHeaders);
    }

好了,接下来我们可以使用上述工具来设置client端header参数了

    private ManagedChannel channel;
    private GreeterGrpc.GreeterBlockingStub greeterBlockingStub;
    @Before
    public void init () {
        //通道初始化 建立连接
        log.info(" iat connect start.");
        channel = ManagedChannelBuilder.forAddress("127.0.0.1", 9099)
                .usePlaintext()
                .build();//池化处理 成本高
        greeterBlockingStub = GreeterGrpc.newBlockingStub(channel);
        //设置header参数
        Map<String,String> headerMap = new HashMap<>();
        headerMap.put("appId","427141404052612");
        headerMap.put("token","782bc51504f805ca7eea9209af137100");
       //这里是关键,请注意一定要把greeterBlockingStub存根再次赋值,因为MetadataUtils.attachHeaders底层
      //也是通过注入客户端拦截器重新生成的存根。
      greeterBlockingStub = attachHeaders(greeterBlockingStub,headerMap);
    }

2、支持设置客户端请求的header以及获取服务端返回结果中的header,我们需要定义客户端拦截器来实现

/**
     * 客户端拦截器
     */
    private static class MyClientInterceptor implements ClientInterceptor {
        //客户端header的key
        static final Metadata.Key<String> TOKEN = Metadata.Key.of("token", Metadata.ASCII_STRING_MARSHALLER);
        //客户端header的key
        static final Metadata.Key<String> APPID = Metadata.Key.of("appId", Metadata.ASCII_STRING_MARSHALLER);

        @Override
        public <ReqT, RespT> ClientCall<ReqT, RespT> interceptCall(MethodDescriptor<ReqT, RespT> method, CallOptions callOptions, Channel next) {
            return new ForwardingClientCall.SimpleForwardingClientCall<ReqT, RespT>(next.newCall(method, callOptions)) {
                @Override
                public void start(Listener<RespT> responseListener, Metadata headers) {
                    //放入客户端的header
                    headers.put(TOKEN, "05e0450b40a30bb7e92f3239c2f9e389");
                    headers.put(APPID, "227141404052613");
                    super.start(new ForwardingClientCallListener.SimpleForwardingClientCallListener<RespT>(responseListener) {
                        @Override
                        public void onHeaders(Metadata headers) {
                            //输出服务端传递回来的header
                            System.out.println("header received from server:" + headers);
                            super.onHeaders(headers);
                        }
                    }, headers);
                }
            };
        }
    }

好了,那么我们在客户端建立连接时,注入我们的拦截器。

    private ManagedChannel channel;
    private IatGrpc.IatStub iatStub;
    @Before
    public void init () {
        log.info(" iat connect start.");
        channel = ManagedChannelBuilder.forAddress("127.0.0.1", 50051)
                .usePlaintext()
                .build();
        //客户端通道绑定拦截器
        Channel tmpChannel = ClientInterceptors.intercept(channel, new MyClientInterceptor());
        iatStub = IatGrpc.newStub(tmpChannel);
    }

参考文章:
gRPC请求中对header进行处理

相关文章

  • springboot-grpc服务拦截器应用

    grpc-server 自定义拦截器实现,适用于server端做鉴权认证场景 在上篇文章 springboot集成...

  • Angular 里 HTTP 请求和响应结构的拦截器(inter

    通过拦截,开发人员可以声明拦截器来检查和转换从应用程序到服务器的 HTTP 请求。 相同的拦截器还可以在返回应用程...

  • angular拦截器和Restanglular

    拦截器 用来向应用的业务流程中注入新的逻辑。 拦截器的核心是服务工厂,通过向httpProvider.interc...

  • OkHttp之拦截器(二)

    本篇文章主要介绍OkHttp的默认拦截器 重试拦截器 桥接拦截器 缓存拦截器 连接拦截器 访问服务器拦截器 通过拦...

  • OkHttp源码学习之四 CallServerIntercept

    CallServerInterceptor 请求服务拦截器 整个责任链中最后一个拦截器,负责向服务器发送网络请求...

  • 从零开始写拦截器

    拦截器的应用是非常广泛的,okhttp中有拦截器,spring框架中也有拦截器,这个年代,你要是不知道什么是拦截器...

  • 请求拦截器 与 响应拦截器(React)

    前提: 请求拦截器和响应拦截器主要应用场景:请求网络接口请求拦截器:发送请求的时候,携带一些信息响应拦截器:接收到...

  • 请求拦截器 与 响应拦截器(Vue)

    前提: 请求拦截器和响应拦截器主要应用场景:请求网络接口请求拦截器:发送请求的时候,携带一些信息响应拦截器:接收到...

  • Okhttp拦截器

    Okhttp拦截器分为两大类,一类是应用拦截器,另一类是网络拦截器。 Application Intercepto...

  • ARouter 提供的服务2020-12-05

    ARouter提供了两个默认的IProvider对象:拦截器和自动注入 一、 拦截器服务 1.声明 获取服务器拦截...

网友评论

      本文标题:springboot-grpc服务拦截器应用

      本文链接:https://www.haomeiwen.com/subject/ibkunqtx.html