Android利用AndServer库搭建https服务器
背景
最近项目中需要用到web端与安卓终端设备通讯,并且web端是https,所有需要安卓端建立一个https服务器用来与web端通讯。
依赖库
由于安卓原生没有这类服务器的依赖包,我决定使用第三方依赖库来实现这类功能,选择AndServer的原因很简单,它提供类似SpringMVC的注解,如果熟悉SpringMVC,可以很快掌握,按照官方文档很快就能搭建一个安卓http服务器,但是官方没有个https服务器的Demo,文档也没有相关说明,因此记录我用AndServer实现Https服务器过程。
官网地址
https://github.com/yanzhenjie/AndServer
添加依赖
根项目build.gradle引入插件
buildscript {
dependencies {
classpath 'com.yanzhenjie.andserver:plugin:2.1.12'
}
}
模块项目build.gradle引入依赖
implementation 'com.yanzhenjie.andserver:api:2.1.12'
annotationProcessor 'com.yanzhenjie.andserver:processor:2.1.12'
模块项目build.gradle增加插件
plugins {
id 'com.android.application'
id 'com.yanzhenjie.andserver' // 新增
}
建立http服务器
Server server = AndServer.webServer(context)
.port(8080)
.timeout(10, TimeUnit.SECONDS)
.build();
// startup the server.
server.startup();
...
// shutdown the server.
server.shutdown();
建立接口控制器
@RestController
@RequestMapping(path = "/user")
public class UserController {
@PostMapping("/login")
public String login(@RequestParam("account") String account,
@RequestParam("password") String password) {
...
return "Successful.";
}
@GetMapping(path = "/{userId}")
public User info(@PathVariable("userId") String userId,
@QueryParam("fields") String fields) {
User user = findUserById(userId, fields);
...
return user;
}
@PutMapping(path = "/{userId}")
public void modify(@PathVariable("userId") String userId
@RequestParam("age") int age) {
...
}
}
建立https服务器
创建jks证书,并将jks证书转换成BKS
使用Keytool生成jks证书,jks证书怎么创建请自行百度,这里主要是将jks转成安卓使用的bks,portecle是最新版密钥证书管理转换工具 Android SSL双向验证码PEM转BKS创建、加载、保存和转换密钥库
工具下载地址:https://nchc.dl.sourceforge.net/project/portecle/v1.11/portecle-1.11.zip
1、下载protecle.zip压缩包,解压。使用java -jar portecle.jar运行此工具
2、点击File–>Open Keystore File(ctrl+o),选中demo.jks并打开
3、输入jks对应密码
4、点击Tools–>Change Keystore Type --> BKS
5、在弹出的密码框输入密码,点OK
6、点击确定后,按快捷键Ctrl+S保存,在弹出的保存对话框里填上httpskey.bks并保存到当前目录,后导入到Android项目的Raw文件夹
启动https服务
// 证书对应密码
String password = "123456";
KeyStore keyStore = KeyStore.getInstance("BKS");
keyStore.load(this.getResources().openRawResource(R.raw.httpskey), password.toCharArray());
KeyManagerFactory keyManagers = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
keyManagers.init(keyStore, password.toCharArray());
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
KeyStore ts = KeyStore.getInstance(KeyStore.getDefaultType());
ts.load(this.getResources().openRawResource(R.raw.httpskey), password.toCharArray());
tmf.init(ts);
SSLContext ctx = SSLContext.getInstance("TLS");
ctx.init(keyManagers.getKeyManagers(), tmf.getTrustManagers(), null);
Server server = AndServer.webServer(this)
.port(8011)
.sslContext(ctx)
.serverSocketFactory(ctx.getServerSocketFactory())
.sslSocketInitializer(new SSLSocketInitializer() {
@Override
public void onCreated(@NonNull SSLServerSocket socket) throws SSLException {
}
})
.listener(new Server.ServerListener() {
@Override
public void onStarted() {
Log.d("Server", "onStarted ");
Toast.makeText(MainActivity.this, "服务启动成功", Toast.LENGTH_SHORT).show();
}
@Override
public void onStopped() {
}
@Override
public void onException(Exception e) {
Log.d("Server", "onException: " + e.toString());
}
})
.timeout(10, TimeUnit.SECONDS)
.build();
server.startup();