netty系列之:在netty中處理CORS


簡介

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/

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

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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM