gRPC Android SSL/TLS Demo(Android上帶有SSL/TLS加密的gRPC使用詳解)

最近項(xiàng)目有用到gRPC來發(fā)起請求,并且需要用到加密。做的過程中也是各種坑,官網(wǎng)文檔也不詳細(xì),網(wǎng)上資料也不多。我把過程都記錄一下,希望能幫助到有需要的朋友。

最近有朋友說構(gòu)建時(shí)不成功,findbugs的包報(bào)錯(cuò)(當(dāng)然這個(gè)只是靜態(tài)分析用的,去掉也可以),這里在gradle文件中加上這句話即可(下面的gradle示例代碼中已經(jīng)加上):
configurations.all { resolutionStrategy.force 'com.google.code.findbugs:jsr305:3.0.1'}

1、gRPC介紹

定義介紹就不說了網(wǎng)上一大堆,簡單理解就是google新推出的一種通信協(xié)議,定義好proto文件,客戶端和服務(wù)端都可以自動(dòng)生成相關(guān)的方法和對(duì)象,調(diào)用接口時(shí)直接使用這些生成好的文件,幫助開發(fā)者更多的關(guān)注業(yè)務(wù)。

需要注意的是:官方案例中要各種編譯對(duì)應(yīng)語言的文件,編譯過程中下載相關(guān)的文件速度特別慢,各種坑。其實(shí)Android使用時(shí)只需要導(dǎo)入插件和lib庫,就可以自動(dòng)編譯好相關(guān)的java文件供調(diào)用。

2、proto文件

拿一段官網(wǎng)的proto案例介紹

proto文件.png

這個(gè)類名service Greeter編譯后會(huì)自動(dòng)生成GreeterGrpc,通過GreeterGrpc調(diào)用里面的方法比如SayHello。另外假如類名service User,就會(huì)生成UserGrpc
HelloRequest也會(huì)自動(dòng)生成相應(yīng)的類,到時(shí)直接使用。這就省去了建實(shí)體類以及請求數(shù)據(jù)的方法的步驟,省事了很多

這里推薦proto文件(有個(gè)P的小圖標(biāo)后文會(huì)提到)放在和java同一級(jí)目錄下:

同級(jí)目錄.png

3、環(huán)境配置

需要配置protobuf插件和庫用來自動(dòng)生成gRPC文件。
在最外層的build.gradle下加上

apply plugin: 'com.android.application'
apply plugin: 'com.google.protobuf'


android {
    compileSdkVersion 24
    buildToolsVersion "24.0.0"
    defaultConfig {
        applicationId "com.xxx.xxx.xxxxx"
        minSdkVersion 15
        targetSdkVersion 24
        versionCode 1
        versionName "1.0"
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
    lintOptions {
        disable 'InvalidPackage'
    }

    configurations.all {    
         resolutionStrategy.force 'com.google.code.findbugs:jsr305:3.0.1'
    }
}

protobuf {
    protoc {
        artifact = 'com.google.protobuf:protoc:3.0.0'
    }
    plugins {
        javalite {
            artifact = "com.google.protobuf:protoc-gen-javalite:3.0.0"
        }
        grpc {
            artifact = 'io.grpc:protoc-gen-grpc-java:1.0.0'
        }
    }
    generateProtoTasks {
        all().each { task ->
            task.plugins {
                javalite {}
                grpc {
                    // Options added to --grpc_out
                    option 'lite'
                }
            }
        }
    }
}

dependencies {
    compile fileTree(include: ['*.jar'], dir: 'libs')

    //grpc need
    compile 'io.grpc:grpc-okhttp:1.0.0'
    compile 'io.grpc:grpc-protobuf-lite:1.0.0'
    compile 'io.grpc:grpc-stub:1.0.0'
    
    compile 'com.google.code.findbugs:jsr305:3.0.0'
    compile 'com.google.guava:guava:18.0'
    compile 'javax.annotation:javax.annotation-api:1.2'
}

注意點(diǎn)
1、grpc { artifact = 'io.grpc:protoc-gen-grpc-java:1.0.0'}
這句話一定要有,不然自動(dòng)生成的java文件沒有GreeterGrpc,就無法調(diào)用方法了

2、配置好gradle,gradle構(gòu)建時(shí)會(huì)提示安裝插件(頂部的 apply plugin: 'com.google.protobuf'),就是這個(gè)插件

插件.png

安裝后,項(xiàng)目中proto文件前面就會(huì)出現(xiàn)個(gè)P字的小圖標(biāo)

插件效果.png

3、官網(wǎng)案例中的版本都是1.1.0-SNAPSHOT,但是我在實(shí)踐的過程中發(fā)現(xiàn)根本下不了,不存在這個(gè)版本,這里建議使用1.0.0
compile 'io.grpc:grpc-okhttp:1.0.0'
compile 'io.grpc:grpc-protobuf-lite:1.0.0'
compile 'io.grpc:grpc-stub:1.0.0'

4、另外,gradle版本可能也會(huì)影響到構(gòu)建,最好使用最新的版本

5、findbugs的包報(bào)錯(cuò),這里在gradle文件中加上這句話即可:
configurations.all { resolutionStrategy.force 'com.google.code.findbugs:jsr305:3.0.1'}
其實(shí)這個(gè)findbugs不要也沒關(guān)系

6、工程根目錄的gradle文件中要有這句:
classpath "com.google.protobuf:protobuf-gradle-plugin:0.8.0"

Paste_Image.png

特別注意~~~~
gradle構(gòu)建時(shí)下載速度很慢,一定要耐心等待,通過查看gradle日志來跟蹤構(gòu)建過程,我當(dāng)時(shí)一直在running了10來分鐘,以為斷了就關(guān)掉重來,花費(fèi)了很長時(shí)間才搞明白其實(shí)它是在下載相關(guān)的文件,日志顯示正在下載,只是速度非常慢,即使翻墻速度也很慢。

日志.png

構(gòu)建好后,rebuild一下項(xiàng)目就會(huì)自動(dòng)根據(jù)項(xiàng)目目錄中的proto文件生成對(duì)應(yīng)的java文件,我項(xiàng)目的文件如下:

生成文件.png

這時(shí)就可以進(jìn)行開發(fā)了。


4、gRPC Android使用方法(主要是SSL/TLS加密驗(yàn)證)

官網(wǎng)也有使用案例:

官網(wǎng)案例.png

不過它這個(gè)沒有使用加密

這里說下gRPC的加密,官方文檔中也有介紹,分為:
1、服務(wù)端認(rèn)證加密使用的 SSL/TLS
2、通過 Google 進(jìn)行認(rèn)證
3、開發(fā)者自定義的加密憑證

可以參考官網(wǎng)文檔 , 中文版文檔


我們項(xiàng)目用的是SSL/TLS協(xié)議來加密,這里就有坑了:
官網(wǎng)給了一段java案例:

// With server authentication SSL/TLS
ManagedChannel channel = ManagedChannelBuilder.forAddress("myservice.example.com", 443)
    .build();
GreeterGrpc.GreeterStub stub = GreeterGrpc.newStub(channel);

// With server authentication SSL/TLS; custom CA root certificates; not on Android
ManagedChannel channel = NettyChannelBuilder.forAddress("myservice.example.com", 443)
    .sslContext(GrpcSslContexts.forClient().trustManager(new File("roots.pem")).build())
    .build();
GreeterGrpc.GreeterStub stub = GreeterGrpc.newStub(channel);

這句not on Android就坑爹了,Android端生成的文件中根本沒有NettyChannelBuilder這個(gè)東西。不過幸好還有一段小字:

If the issuing certificate authority is not known to the client then a properly configured SslContext or SSLSocketFactory should be provided to the NettyChannelBuilder or **OkHttpChannelBuilder******, respectively.

還有OkHttpChannelBuilder官方給的案例也沒有提到這玩意,其實(shí)實(shí)例化這里需要這樣:

ManagedChannel channel = OkHttpChannelBuilder.forAddress("xxx",yyy)
                        .overrideAuthority("zzz")
                        .sslSocketFactory(sslFactory)
                        .build();


1、千萬不要像官網(wǎng)案例那樣設(shè)置setPlaintext(true),這個(gè)是設(shè)置明文,我們用的是密文

2、xxx是服務(wù)器的ip,yyy是端口號(hào),zzz是domain(這些參數(shù)服務(wù)端都會(huì)提供給你)
特別注意這個(gè)overrideAuthority一定要調(diào)用,覆蓋hostname來匹配服務(wù)器的證書

3、sslSocketFactory這個(gè)方法就是設(shè)置密鑰的方法。一般服務(wù)端會(huì)提供個(gè).pem的密鑰文件,放在raw中。我們把這個(gè)密鑰設(shè)置到OkHttpChannelBuilder中即可以訪問服務(wù)器了,關(guān)于sslSocketFactory 網(wǎng)上可以搜索到很多有關(guān)的內(nèi)容。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容