netty系列之:在netty中處理CORS

flydean發表於2021-09-17

簡介

CORS的全稱是跨域資源共享,他是一個基於HTTP-header檢測的機制,通過對HTTP-header進行控制,可以實現對跨域資源的許可權管理功能。在之前的CORS詳解文章中,我們已經對CORS有了基本的解釋。

本文將會從netty的實現角度,講解如何在netty中實現CORS。

服務端的CORS配置

熟悉CORS的朋友應該知道,CORS所有的操作都是在HTTP協議之上通過控制HTTP頭來實現的。所以說如果要在伺服器端實現CORS的支援,事實上也是對HTTP協議的頭進行各種設定完成的。

為了方便大家的使用,netty提供了一個CorsConfig類,來統一CORS的頭設定。

先看下CorsConfig類中定義的屬性:

    private final Set<String> origins;
    private final boolean anyOrigin;
    private final boolean enabled;
    private final Set<String> exposeHeaders;
    private final boolean allowCredentials;
    private final long maxAge;
    private final Set<HttpMethod> allowedRequestMethods;
    private final Set<String> allowedRequestHeaders;
    private final boolean allowNullOrigin;
    private final Map<CharSequence, Callable<?>> preflightHeaders;
    private final boolean shortCircuit;

這些屬性和CORS的HTTP頭設定是一一對應的。比如說origins表示的是允許的源,anyOrigin表示允許所有的源。

是和下面的設定對應的:

Origin: <origin>

exposeHeaders是和Access-Control-Expose-Headers一一對應的,表示伺服器端允許客戶端獲取CORS資源的同時能夠訪問到的header資訊。其格式如下:

Access-Control-Expose-Headers: <header-name>[, <header-name>]*

allowCredentials表示是否開啟CORS的許可權認證。表示伺服器端是否接受客戶端帶有credentials欄位的請求。如果用在preflight請求中,則表示後續的真實請求是否支援credentials,其格式如下:

Access-Control-Allow-Credentials: true

allowedRequestMethods表示訪問資源允許的方法,主要用在preflight request中。其格式如下:

Access-Control-Allow-Methods: <method>[, <method>]*

allowedRequestHeaders用在preflight request中,表示真正能夠被用來做請求的header欄位,其格式如下:

Access-Control-Allow-Headers: <header-name>[, <header-name>]*

當客戶端傳送OPTIONS方法給伺服器的時候,為了安全起見,因為伺服器並不一定能夠接受這些OPTIONS的方法,所以客戶端需要首先傳送一個
preflighted requests,等待伺服器響應,等伺服器確認之後,再傳送真實的請求。我們舉一個例子。preflightHeaders表示的就是伺服器允許額preflight的請求頭。

shortCircuit表示請求是否是一個有效的CORS請求,如果請求被拒絕之後,就會返回一個true。

CorsConfigBuilder

CorsConfig使用來表示Cors的配置類,那麼怎麼去構造這個配置類呢?我們看下CorsConfig的建構函式:

    CorsConfig(final CorsConfigBuilder builder) {
        origins = new LinkedHashSet<String>(builder.origins);
        anyOrigin = builder.anyOrigin;
        enabled = builder.enabled;
        exposeHeaders = builder.exposeHeaders;
        allowCredentials = builder.allowCredentials;
        maxAge = builder.maxAge;
        allowedRequestMethods = builder.requestMethods;
        allowedRequestHeaders = builder.requestHeaders;
        allowNullOrigin = builder.allowNullOrigin;
        preflightHeaders = builder.preflightHeaders;
        shortCircuit = builder.shortCircuit;
    }

可以看到CorsConfig是通過CorsConfigBuilder來構造的。通過設定CorsConfigBuilder中的各種屬性即可。CorsConfigBuilder中提供了多種設定屬性的方法。

可以使用這樣的方法來構造CorsConfig如下:

CorsConfig corsConfig = CorsConfigBuilder.forAnyOrigin().allowNullOrigin().allowCredentials().build();

CorsHandler

有了corsConfig,我們還需要將這個config配置在netty的handler中,netty提供了一個CorsHandler類來專門處理corsConfig,這個類就叫CorsHandler。

首先看下CorsHandler的建構函式:

    public CorsHandler(final CorsConfig config) {
        this(Collections.singletonList(checkNotNull(config, "config")), config.isShortCircuit());
    }

    public CorsHandler(final List<CorsConfig> configList, boolean isShortCircuit) {
        checkNonEmpty(configList, "configList");
        this.configList = configList;
        this.isShortCircuit = isShortCircuit;
    }

CorsHandler有兩個建構函式,一個是傳入CorsConfig,一個是傳入一個CorsConfig的列表。

CorsHandler的主要工作原理就是在channelRead的時候,對responseHeader進行處理,設定CORS頭。

netty對cors的支援

上面我們已經講過了netty中cors的核心類和方法,最後一步就是把cors的支援類加入到netty的pipeline中,其核心程式碼如下:

    public void initChannel(SocketChannel ch) {

        ChannelPipeline pipeline = ch.pipeline();
        pipeline.addLast(new HttpResponseEncoder());
        pipeline.addLast(new HttpRequestDecoder());
        pipeline.addLast(new HttpObjectAggregator(65536));
        pipeline.addLast(new ChunkedWriteHandler());

        CorsConfig corsConfig = CorsConfigBuilder.forAnyOrigin().allowNullOrigin().allowCredentials().build();
        pipeline.addLast(new CorsHandler(corsConfig));

        pipeline.addLast(new CustResponseHandler());
    }

總結

cors比較簡單,netty也為其提供了住夠的方法支援。大家可以直接使用。

本文的例子可以參考:learn-netty4

本文已收錄於 http://www.flydean.com/22-netty-cors/

最通俗的解讀,最深刻的乾貨,最簡潔的教程,眾多你不知道的小技巧等你來發現!

歡迎關注我的公眾號:「程式那些事」,懂技術,更懂你!

相關文章