OData网站如果采用http明文传输,安全性很差,最好采用https加密传输。服务端要使用SSL证书。
在开发阶段,可以使用自签名SSL证书用于软件调试和测试。如果只有PC和移动客户端,可以在发布后继续使用自签名证书。如果有网页客户端,用户会在浏览器看到网站的证书信息,为了给用户一个安全的体验,必须购买正式的SSL证书。
1. 创建自签名SSL证书
如果网站部署在Windows Server,可以在IIS中直接创建自签名证书,非常简单。
Linux服务器创建自签名证书不像IIS这么方便。如果直接在Linux系统里创建自签名证书,需要下载,安装一堆东西,甚至可能还要重新编译,比较繁琐。其实,完全可以在Windows系统里创建自签名证书,然后拿到Linux系统去使用。
在以下网站下载openssl的Windows安装包。
https://slproweb.com/products/Win32OpenSSL.html
如果下载慢可以用迅雷。
下载后直接安装,全部默认好了。
然后以管理器权限打开控制台,输入以下命令创建自签名证书。如果提示密码,输入xxx,这个以后会用到。这个证书采用sha256算法,有效期365天。
C:\OpenSSL-Win64\bin\openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -keyout myweb.key -out myweb.crt -subj /CN=*.myweb.com
C:\OpenSSL-Win64\bin\openssl pkcs12 -export -out myweb.pfx -inkey myweb.key -in myweb.crt
然后可以得到3个文件。后面要用到。
myweb.crt
myweb.key
myweb.pfx
2. 修改网站代码支持https
为了简单起见,直接修改Program.cs,整个网站都使用https传输。
public static IWebHost BuildWebHost(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseKestrel(ConfigHttps)
//必须指定端口,否则在Win10命令行运行端口是5000,在CentOS docker运行端口是80
//.UseUrls("http://*:5000")
.UseStartup<Startup>()
.Build();
private static void ConfigHttps(KestrelServerOptions options)
{
options.Listen(IPAddress.Any, 5000, listenOptions =>
{
//填入pfx文件路径和指定的密码
string pfxFile = Path.Combine(Directory.GetCurrentDirectory(), "myweb.pfx");
listenOptions.UseHttps(pfxFile, "xxx");
});
}
给项目添加myweb.pfx,设置属性为【如果较新则复制】,生成操作为【内容】。重新发布网站。运行网站,访问https://localhost:5000/odata/Books,浏览器会提示网站不安全。
点击继续转到网页,浏览器地址栏提示证书错误,点击该信息会提示网站问题。
如果购买了正式的证书,浏览器地址栏会提示一把锁,例如访问百度网站:
3. docker网站采用SSL证书
修改nginx配置文件。需要用到2个证书文件。
server {
listen 9000 ssl;
ssl_certificate myweb.crt;
ssl_certificate_key myweb.key;
location / {
proxy_pass https://odataweb-service:5000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection keep-alive;
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
修改docker-compose.yml文件。挂载当前目录下的2个证书文件给nginx容器使用。
version: '3'
services:
mysql-service:
container_name: mysqlservice
image: mysql
environment:
- MYSQL_ROOT_PASSWORD=xxx
volumes:
- ./data:/var/lib/mysql
restart: always
odataweb-service:
container_name: odatawebservice
image: odatawebimage
build:
context: ./odataweb
dockerfile: Dockerfile
environment:
- ASPNETCORE_ENVIRONMENT=Development
restart: always
depends_on:
- mysql-service
links:
- mysql-service
nginx-proxy:
container_name: nginxproxy
image: nginx
ports:
- "9000:9000"
volumes:
- ./nginx.conf:/etc/nginx/conf.d/default.conf
- ./myweb.crt:/etc/nginx/myweb.crt
- ./myweb.key:/etc/nginx/myweb.key
restart: always
links:
- odataweb-service
然后把myweb.crt、myweb.key放在docker-compose.yml相同的目录下,在Linux系统里重新创建、运行容器。
访问https://192.168.80.134:9000/odata/Books,检查结果。
4. 客户端访问https网站
新建Winform项目WinODataClient。
OData Client Code Generator还没有发布支持VS2017的版本,改用Simple.OData.Client封装客户端对OData服务器的访问。
NuGet安装Simple.OData.V4.Client 4.29.0。
做一个简单的CURD测试。
private Uri DataUri = new Uri("https://192.168.80.134:9000/odata");
private ODataClientSettings settings;
private void frmMain_Load(object sender, EventArgs e)
{
//允许访问https网站,对http访问无干扰
ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
//初始化OData客户端
settings = new ODataClientSettings(DataUri);
settings.PayloadFormat = ODataPayloadFormat.Json;
settings.RequestTimeout = TimeSpan.FromSeconds(30);
btnRefresh.Click += async (ss, ee) =>
{
var client = new ODataClient(settings);
var result = await client.For<Book>().FindEntriesAsync();
var books = result.ToList();
this.dataGridViewBook.DataSource = books;
};
btnQuery.Click += async (ss, ee) =>
{
var client = new ODataClient(settings);
var query = client.For<Book>("Books");
//query.Skip(2).Top(2);//分页
query.OrderBy(x => x.Price);//排序
query.Filter(x => x.Author == "金庸");//条件
var result = await query.FindEntriesAsync();
var books = result.ToList();
this.dataGridViewBook.DataSource = books;
};
btnAdd.Click += async (ss, EnumerableExecutor) =>
{
var client = new ODataClient(settings);
Book book = new Book() { Name = "绝绝代双骄", PublishDate = new DateTime(1957, 10, 1), Author = "古龙", Price = 10.5f };
var result = await client.For<Book>().Set(book).InsertEntryAsync(true);
};
btnEdit.Click += async (ss, ee) =>
{
var client = new ODataClient(settings);
var result = await client.For<Book>().Key(1).Set(new { Price = DateTime.Now.Second }).UpdateEntryAsync(true);
};
btnDel.Click += async (ss, ee) =>
{
var client = new ODataClient(settings);
await client.For<Book>().Key(1).DeleteEntryAsync();
};
}
运行软件报错:
Unable to load OData adapter from assembly Simple.OData.Client.V4.Adapter
FileLoadException: 未能加载文件或程序集“Microsoft.OData.Edm, Version=6.17.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35”或它的某一个依赖项。找到的程序集清单定义与程序集引用不匹配。 (异常来自 HRESULT:0x80131040)
Simple.OData.Client 4.29.0版本要求的Microsoft.OData.Edm至少要6.17.0,但是NuGet安装的时候只安装了6.0.0,在NuGet管理器中把Microsoft.OData.Core升级到6.17.0,它会自动升级2个关联库Microsoft.OData.Edm和Microsoft.Spatial到6.17.0,然后再次运行没问题了。