minio可以很方便的搭建自有存储服务,docker运行也比较省心,接触minio是因为冷总的PIGX,以下部分代码片段来源于pigx,这是商业软件,请大家尊重版权,本代码只起到抛砖引玉的作用,接入minio可以查看官方文档,如果需要完整minio 的Spring Starter代码,请去围观冷总的pigx,开源版地址:
minio官方文档java client api 地址:
https://docs.min.io/docs/java-client-api-reference.html
介于SNS富文本code在移动端显示严重变形,所以我就全部截图了,
改造的目的:
1、因为pigx原版的minio前端获取的是blob文件流,部署的时候会直接从主服务器获取,添加了外链策略之后,就能直接从minio服务器获取文件,减少主服务器压力
2、既然多租户,每个租户的文件不分隔会很难管理,租户数据迁移麻烦,所以添加租户自动创建存储桶
3、minio默认创建的存储桶策略是无下载和上传权限的,所以无法外链访问,这也是为什么pigx默认文件流返回给前端,所以创建存储同之后我们要设置 download 权限
那下面就开始:
1、如果有pigx源码,那就直接在MInioTemplate 添加几个方法,这个只是个封装,直接接入minio就可以直接 MinioClient 调用了
2、因为策略设置 setBuckePolicy 的 Policy 参数是一个json字符串,可以使用 getBuckePolicy 传入BucketName 获取到,如果默认创建存储桶,没有设置策略,会返回空值,设置了读策略也就是download,返回的Json格式如下:
其中Action 就是我们要设置的策略,这个因为java client 和 minio的 go源码并不统一,因为没有深入研究,所以简单说明下,上图是读权限的 策略返回的json,下图是minio client 官方客户端设置策略返回的策略列表,可以看到设置download,返回的是 readonly,所以不纠结内部实现,只完成我们自己的需求:
3、每次传参都构造个json太费事了,所以我们写一个方法,直接传入bucketName 和要设置测存储桶策略类型,自动构造个json policy,先定义一个枚举,
构造json policy
这样我们需要的json格式的policy就创建好了,根据传入的策略类型,自动生成json,
4、基础服务好了之后就是前端文件上传的方法了 ,关键代码就几行:
这样就可以根据租户编号自动创建存储桶,并设置只读访问权限,前端就可以通过获取到的filePath 访问minio中的资源了。
别问bucket 的策略我怎么找到的,我是一次一次log.info分析的,不懂go源码,也就没去找,纯人肉的。
感谢小莫兄弟发现的匿名用户可以读取bucket列表问题,修复代码如下:
因为权限策略当时测试download,按照返回的json生成的,所以忽略了,添加了
s3:ListBucket
导致可以读取列表,修复下
public static String getPolicyType(String bucketName, PolicyType policyType) {
StringBuilder builder = new StringBuilder();
builder.append("{\n");
builder.append(" \"Statement\": [\n");
builder.append(" {\n");
builder.append(" \"Action\": [\n");
switch (policyType) {
case WRITE:
builder.append(" \"s3:GetBucketLocation\",\n");
builder.append(" \"s3:ListBucketMultipartUploads\"\n");
break;
case READ_WRITE:
builder.append(" \"s3:GetBucketLocation\",\n");
builder.append(" \"s3:ListBucket\",\n");
builder.append(" \"s3:ListBucketMultipartUploads\"\n");
break;
default:
builder.append(" \"s3:GetBucketLocation\"\n");
break;
}
builder.append(" ],\n");
builder.append(" \"Effect\": \"Allow\",\n");
builder.append(" \"Principal\": \"*\",\n");
builder.append(" \"Resource\": \"arn:aws:s3:::");
builder.append(bucketName);
builder.append("\"\n");
builder.append(" },\n");
if (PolicyType.READ.equals(policyType)) {
builder.append(" {\n");
builder.append(" \"Action\": [\n");
builder.append(" \"s3:ListBucket\"\n");
builder.append(" ],\n");
builder.append(" \"Effect\": \"Deny\",\n");
builder.append(" \"Principal\": \"*\",\n");
builder.append(" \"Resource\": \"arn:aws:s3:::");
builder.append(bucketName);
builder.append("\"\n");
builder.append(" },\n");
}
builder.append(" {\n");
builder.append(" \"Action\": ");
switch (policyType) {
case WRITE:
builder.append("[\n");
builder.append(" \"s3:AbortMultipartUpload\",\n");
builder.append(" \"s3:DeleteObject\",\n");
builder.append(" \"s3:ListMultipartUploadParts\",\n");
builder.append(" \"s3:PutObject\"\n");
builder.append(" ],\n");
break;
case READ_WRITE:
builder.append("[\n");
builder.append(" \"s3:AbortMultipartUpload\",\n");
builder.append(" \"s3:DeleteObject\",\n");
builder.append(" \"s3:GetObject\",\n");
builder.append(" \"s3:ListMultipartUploadParts\",\n");
builder.append(" \"s3:PutObject\"\n");
builder.append(" ],\n");
break;
default:
builder.append("\"s3:GetObject\",\n");
break;
}
builder.append(" \"Effect\": \"Allow\",\n");
builder.append(" \"Principal\": \"*\",\n");
builder.append(" \"Resource\": \"arn:aws:s3:::");
builder.append(bucketName);
builder.append("/*\"\n");
builder.append(" }\n");
builder.append(" ],\n");
builder.append(" \"Version\": \"2012-10-17\"\n");
builder.append("}\n");
return builder.toString();
}
主要就是修改了生成policy 的json串的代码,经测试直接访问bucket会提示未授权,进入登陆界面,访问资源可以正常读取
再次感谢小莫兄弟!
扫一扫访问 Blade技术社区 移动端