使用NanoHttpd在app内搭建https server(二)

56 篇文章 1 订阅
一、场景

由于需求和安全的考虑,需要将上一篇文档,使用NanoHttpd搭建的http server改成https的协议,但由于我们测试没办法正式的CA机构颁发的数字证书,所以就使用自签名的方式来验证https server。

由于查看源码得知,NanoHttpd是支持Https的,Support for HTTPS (SSL)

 二、Https协议相关的基础知识

 HTTPS的基本工作原理想必对于许多开发者来说是非常熟悉的了,我们一起先回忆一下HTTP常见的八股文中的描述:

1.客户端(浏览器)访问 HTTPS 的URL;
2.服务器返回 HTTPS 使用的 CA 证书;
3.客户端(浏览器)验证 CA 证书是否为合法证书;
4.验证通过,证书合法,生成一串随机数并使用公钥(证书中提供的)进行加密;
5.发送公钥加密后的随机数给服务器;
6.服务器拿到密文,通过私钥进行解密,获取到随机数(公钥加密,私钥解密,反之也可以);
7.服务器把要发送给浏览器的内容,使用随机数进行加密后传输给客户端(浏览器);
8.此时客户端(浏览器)可以使用随机数进行解密,获取到服务器的真实传输内容。
 

        那么我们回到我们的主题里,首先需要知道CA证书是什么,CA是证书颁发机构(Certificate Authority)的缩写,那么CA证书就是证书机构颁发的一种数字证书,为什么需要这个机构来颁发证书呢?可以理解为就是一个第三方担保机构,这个担保机构保证了在客户端和服务器的通讯阶段的安全,这样客户端只要是看到证书是这个担保机构担保过的,那就会认可这个服务器并和它进行后续交互,反之其他证书都是不合法的,不会进行更进一步的交互了。

        其次,这个证书不光是用来证明其合法性,其中还包含了一个公钥,公钥是什么呢?这边就涉及到一些密码学相关知识点了,我们需要先知道非对称加密的一点概念,可以猜出来,有非对称加密那肯定有对称加密,对称加密就是使用同一把密钥进行加密和解密,而非对称加密会用到2个密钥,一把公钥和一把私钥进行加密和解密,公钥会公开出去给客户端,而私钥会保存在本地防止泄漏,所以会更安全,使用这个公钥加密后的数据可以被私钥解开,反过来也是一样的,在上面的HTTPS的连接过程中,1-6步骤所涉及到的就是非对称加解密过程,而后续则会采用对称加密的方式,即使用一个随机数充当了对称加密的密钥进行了通讯,这样一方面是为了提高通讯的效率更重要的是为了保证安全,因为如果还使用原有的公钥和私钥的方式在服务端使用私钥加密,那么只要有公钥的客户端都可以截获服务端发来的信息进行解密,显然这样是不行的。

        知道了概念后,那自签证书的概念就是我们自己充当这个CA机构给自己颁发一个证书,然后想办法让客户端信任这个证书(一般的默认做法是系统会有一个受信任的证书列表,其中就会有存放一些CA机构的根证书),并且证书里面包含了我们的公钥,客户端使用这个公钥进行数据加密,再传输数据,服务端接收并用私钥解开,从而完成整个加解密的通讯过程。那接下来我们就来模拟这样一个通讯过程
 

三、自签名证书过程

使用KeyStore Explorer创建一个BKS-V1密钥库,并将其作为“keystore.bks”保存到android的raw文件夹。或者,您也可以使用以下代码来创建密钥库文件,然后只需使用密钥库资源管理器将其打开,并将其类型更改为 BKS-V1。

密钥库资源管理器 - 下载 (keystore-explorer.org)

windows打开cmd终端,粘贴下面这一段命令,其中的-storepass后面的值可以自己修改成自己的storepass。

keytool -genkey -keyalg RSA -alias selfsigned -keystore keystore.bks -storepass myKeyStorePass -validity 360 -keysize 2048 -ext SAN=DNS:localhost,IP:127.0.0.1  -validity 9999


上面的命令应该不难理解,就是你给密钥文件设置的生成位置,key alias、key password和key store、validity ,回车后,需要继续按照提示输入相关信息,依次填写好信息后,输入 Y 确认信息即可。上面一行的storepass为myKeyStorePass,别名为selfsigned,有效期为360天,keystore.bks保存在了C盘的当前用户目录(C:\Users\sunbinkang)。


然后用上面安装好的密钥库资源管理器KeyStore Explorer去找到这个keystore.bks文件打开,打开的时候输入上面的storepass密码就行(ps:我被这里坑了好久,记住要输入storepass的这个密码,不是keypass的密码),打开后,找到Tools--->change KeyStore Type--->BKS-V1保存就行。
 

四、Android项目中使用自签名证书

        将上一步中生成的keystore.bks做了type转换后,将文件放入到项目的main->res->raw目录下,如果没这个文件夹,新建一个就行;

在HttpServer.kt的文件中的次构造中加入如下代码:

    //服务器信任的客户端证书
    constructor(context: Context, hostname: String?, port: Int) : this(hostname, port) {
        //从文件中拿到流对象
        val keystoreStream: InputStream =
            context.resources.openRawResource(R.raw.keystore)
        //拿到keystore对象
        val keyStore = KeyStore.getInstance(KeyStore.getDefaultType())
        //keystore加载流对象,并把storepass参数传入
        keyStore.load(keystoreStream, "myKeyStorePass".toCharArray())
        val keyManagerFactory =
            KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm())
        //这里的第二个参数就是密钥密码,keypass
        keyManagerFactory.init(keyStore, "*******".toCharArray())
        //调用 NanoHttpd的makeSecure()方法
        makeSecure(makeSSLSocketFactory(keyStore, keyManagerFactory), null)
    }
五、postman或者浏览器发起https请求验证

第一张图是因为自签名的原因,需要用户自己手动信任证书。图二为发起的https的get 请求,请求成功。

至此,我们在Nanohttpd的httpserver的基础上做了支持https协议。

最后附上mainactivity的代码。

class MainActivity : AppCompatActivity() {
    var mHttpServer: HttpServer? = null
 
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        mHttpServer = HttpServer(MainActivity@ this, HTTP_IP, HTTP_PORT)
        //三种启动方式都行
//        mHttpServer.start()
//        mHttpServer.start(NanoHTTPD.SOCKET_READ_TIMEOUT)
        mHttpServer?.start(NanoHTTPD.SOCKET_READ_TIMEOUT, false)
    }
 
    override fun onDestroy() {
        super.onDestroy()
        mHttpServer?.stop()//停止
    }
}

项目代码地址:GitHub - sunbinkang/NanoHttpdDemo: android app 使用nanohttpd搭建http server,并且支持https协议

需要注意的是,项目中的raw文件需要你自己生成证书,因为证书是有密码的,我自己证书的密码在代码中用******标记了,所以拿到我的keystore.bks也没用。所以要想跑起来就得自己生成了。具体生成看步骤

————————————————
版权声明:本文为CSDN博主「sunbinkang」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/sunbinkang/article/details/124306367

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
FastAPI是一个由Python编写的现代高性能Web框架,特别适合构建RESTful API和Web应用。它基于星lette和Uvicorn,提供了简单易用的API定义、自动文档生成以及类型安全等特性。以下是一些基本步骤来使用FastAPI搭建Web服务器: 1. 安装FastAPI: 首先确保你已经安装了Python和pip,然后在命令行中运行 `pip install fastapi uvicorn` 来安装FastAPI和其依赖的Uvicorn。 2. 创建项目文件结构: 创建一个新的目录,例如`my_api`,并在其中创建`main.py`和`app.py`(如果需要分模块管理)。 3. 编写`main.py` (或app.py): 这里通常导入并启动FastAPI应用程序。例如,一个简单的示例是: ```python from fastapi import FastAPI # 在这里导入你的API路由和配置 from app import app as api if __name__ == "__main__": import uvicorn uvicorn.run(api, host="0.0.0.0", port=8000) ``` 4. 定义路由和处理函数: 在`app.py`中,你需要定义`API Router`,即定义HTTP方法(GET、POST、PUT等)和URL路径,以及对应的处理函数。例如: ```python from fastapi import APIRouter, Depends, HTTPException, status router = APIRouter() @router.get("/items/") async def read_items(): # 这里是返回数据的逻辑,比如查询数据库 return [{"item_id": 1, "item_name": "Example item"}] ``` 5. 文档生成: FastAPI内置了`docs`功能,可以通过`app.include_router(router, tags=["Items"])`来添加文档,并访问`http://localhost:8000/docs`查看API文档。 6. 启动服务: 运行`main.py`(或指定的`app.py`),在指定的主机和端口上(如8000)启动Web服务器。 相关问题-- 1. FastAPI与星lette和Uvicorn的关系是什么? 2. 如何在FastAPI中处理POST请求并解析请求体数据? 3. 如何在FastAPI中设置全局响应头信息? 4. FastAPI中的Depends函数是用来做什么的?

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值