minio 从头编译(增加web api 跨域安全性 )
遇到个问题安全检查出来minio的9000端口有CORS(跨站资源共享)原始验证失败问题和不安全的crossdomain.xml文件问题,这边找了网上的配置多次尝试无果,找到一个方案,直接编译源码,修改相关逻辑就ok,我这边测试验证没问题。
因为这个项目是go语言写的,顺便学了一下go,目前感觉go确实很简单,但是它的包也不小,跟node.js有一拼了。
直接使用或者参考
直接参考 Success目录。
https://github.com/kesshei/minio_compile
下载源码
项目主要通过monio.exe 通过命令直接运行,所以,需要打包生成minio.exe 命令。
这边可以通过以下命令
minio.exe --version
来获取 minio的版本信息

然后,到minio的官网上进行下载相关的包
github仓库地址:https://github.com/minio/minio/releases
gitee镜像仓库:https://gitee.com/mirrors/minio/tags
直接找自己的包,我找的是 RELEASE.2022-05-08T23-50-31Z,找到后,下载这个压缩包

下载后,解压完如下所示:

打开 go.mod

可以看到 需要go的版本是 1.17,直接下载指定版本即可。
go 环境搭建
go 环境需要官网下载,找到 我这边是需要 1.17版本
go 下载地址: https://go.dev/dl/
我需要的算是老版本,所以要继续往下拉

我是window 10 64 ,直接下载这个版本就可以了。

下载完后,直接双击安装,直接安装完

安装完就可以在控制台使用go命令了,以下命令可以看go的版本信息.
go version

go 环境变量配置
go 用的时候,还是需要配置以下,它的大部分资源都是国外资源,国内没法用。
虽然可以命令行输入,但是,系统级的还是需要手动操作一下更为稳妥。
我的电脑->属性->高级系统属性

点击 系统变量

点击新建 (系统变量)

输入内容,key - value 结构,然后,确定即可

以下是需要增加的变量
GO111MODULE=on
GOPROXY=https://goproxy.cn,direct
GOSUMDB=sum.golang.google.cn
GOROOT=C:\Program Files\Go
其中GOROOT为go的安装目录,其中bin目录 安装包已经自己设置过了,所以不需要设置了。
minio 编译
环境变量设置后,就可以进行编译操作了
go 默认下载的包位于当前用户下的go 目录里 ,我用户名为admin 位于 C:\Users\admin\go\pkg\mod
需要以下相关命令
go clean -modcache // 清理包的缓存信息
go mod download // 下载全部的包 go.mod 里的
以下是编译命令
go build -ldflags "-s -w" -o C:\Users\admin\Desktop\minio-RELEASE.2022-05-08T23-50-31Z\build\minio.exe github.com/minio/minio
因为我这边编译过了,我就先清理包的缓存信息
go clean -modcache
然后,执行
go mod download
minio 逻辑更改
主要是解决跨域问题
http 响应头 cros 修改
主要修改 cmd-> generic-handlers.go 的 addCustomHeaders 方法
const rootdir = "minioConfig"
var Origin = "*"
var Origin_path = filepath.Join(rootdir, "Access_Control_Allow_Origin.txt")
var Methods = "*"
var Methods_path = filepath.Join(rootdir, "AccessControl_Allow_Methods.txt")
var Headers = "*"
var Headers_path = filepath.Join(rootdir, "Access_Control_Allow_Headers.txt")
// addCustomHeaders adds various HTTP(S) response headers.
// Security Headers enable various security protections behaviors in the client's browser.
func addCustomHeaders(h http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
header := w.Header()
header.Set("X-XSS-Protection", "1; mode=block") // Prevents against XSS attacks
header.Set("Content-Security-Policy", "block-all-mixed-content") // prevent mixed (HTTP / HTTPS content)
header.Set("X-Content-Type-Options", "nosniff") // Prevent mime-sniff
header.Set("Strict-Transport-Security", "max-age=31536000; includeSubDomains") // HSTS mitigates variants of MITM attacks
// 追加其他的请求头(安全漏洞提示处理)
header.Set("X-Permitted-Cross-Domain-Policies", "master-only")
header.Set("Referrer-Policy", "strict-origin-when-cross-origin")
header.Set("X-Frame-Options", "SAMEORIGIN")
if Origin == "*" {
// 检查文件是否存在
if _, err := os.Stat(Origin_path); err == nil {
// 文件存在,读取内容
content, err := os.ReadFile(Origin_path)
if err != nil {
fmt.Printf("读取文件时出错: %v\n", err)
return
}
Origin = string(content)
fmt.Printf("成功读取 %s 文件\n", Origin_path)
}
}
if Methods == "*" {
// 检查文件是否存在
if _, err := os.Stat(Methods_path); err == nil {
// 文件存在,读取内容
content, err := os.ReadFile(Methods_path)
if err != nil {
fmt.Printf("读取文件时出错: %v\n", err)
return
}
Methods = string(content)
fmt.Printf("成功读取 %s 文件\n", Methods_path)
}
}
if Headers == "*" {
// 检查文件是否存在
if _, err := os.Stat(Headers_path); err == nil {
// 文件存在,读取内容
content, err := os.ReadFile(Headers_path)
if err != nil {
fmt.Printf("读取文件时出错: %v\n", err)
return
}
Headers = string(content)
fmt.Printf("成功读取 %s 文件\n", Headers_path)
}
}
header.Set("Access-Control-Allow-Origin", Origin)
header.Set("Access-Control-Allow-Methods", Methods)
header.Set("Access-Control-Allow-Headers", Headers)
// Previously, this value was set right before a response was sent to
// the client. So, logger and Error response XML were not using this
// value. This is set here so that this header can be logged as
// part of the log entry, Error response XML and auditing.
// Set custom headers such as x-amz-request-id for each request.
w.Header().Set(xhttp.AmzRequestID, mustGetRequestID(UTCNow()))
h.ServeHTTP(logger.NewResponseWriter(w), r)
})
}
crossdomain.xml文件安全修改
主要修改 cmd -> crossdomain-xml-handler.go 的 setCrossDomainPolicy 方法
var crossdomainPath = filepath.Join("minioConfig", "crossdomain.xml")
var temp = crossDomainXML
// 配置直接读取当前应用下的crossdomain.xml文件,判断文件是否存在,存在则读取文件内容
// A cross-domain policy file is an XML document that grants a web client, such as Adobe Flash Player
// or Adobe Acrobat (though not necessarily limited to these), permission to handle data across domains.
// When clients request content hosted on a particular source domain and that content make requests
// directed towards a domain other than its own, the remote domain needs to host a cross-domain
// policy file that grants access to the source domain, allowing the client to continue the transaction.
func setCrossDomainPolicy(h http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// Look for 'crossdomain.xml' in the incoming request.
switch r.URL.Path {
case crossDomainXMLEntity:
if temp == crossDomainXML {
// 检查文件是否存在
if _, err := os.Stat(crossdomainPath); err == nil {
// 文件存在,读取内容
content, err := os.ReadFile(crossdomainPath)
if err != nil {
fmt.Printf("读取文件时出错: %v\n", err)
return
}
temp = string(content)
fmt.Printf("成功读取 %s 文件\n", crossdomainPath)
}
}
// Write the standard cross domain policy xml.
w.Write([]byte(temp))
// Request completed, no need to serve to other handlers.
return
}
h.ServeHTTP(w, r)
})
}
minio Server 响应 服务名修改
主要修改 cmd -> api-headers.go 的 setCommonHeaders 函数
var ServerName = "MinIO"
var ServerName_path = filepath.Join("minioConfig", "ServerName.txt")
// Write http common headers
func setCommonHeaders(w http.ResponseWriter) {
if ServerName == "MinIO" {
// 检查文件是否存在
if _, err := os.Stat(ServerName_path); err == nil {
// 文件存在,读取内容
content, err := os.ReadFile(ServerName_path)
if err != nil {
fmt.Printf("读取文件时出错: %v\n", err)
return
}
ServerName = string(content)
fmt.Printf("成功读取 %s 文件\n", ServerName_path)
}
}
// Set the "Server" http header.
w.Header().Set(xhttp.ServerInfo, ServerName)
// Set `x-amz-bucket-region` only if region is set on the server
// by default minio uses an empty region.
if region := globalSite.Region; region != "" {
w.Header().Set(xhttp.AmzBucketRegion, region)
}
w.Header().Set(xhttp.AcceptRanges, "bytes")
// Remove sensitive information
crypto.RemoveSensitiveHeaders(w.Header())
}
效果预览
最后是以下文件结构
文件夹

配置的内容

执行以下命令后启动服务
.\minio.exe server C:\Users\win\Desktop\minio2\data
当访问下载地址的时候就可以看到,相关的配置文件都被读取了

可以看到,已经增加了相关的文件头信息了

访问http://127.0.0.1:9000/crossdomain.xml 地址,也看到,这个里面的内容也被修改了.

参考博客
https://www.cnblogs.com/lixingwu/p/17933091.html

浙公网安备 33010602011771号