Golang中Soap、x509与wsse的实现与应用
Golang中Soap、x509与wsse的实现与应用 你好
我正在寻找是否存在任何Go语言库,其中已经实现了SOAP的WSSE安全功能? 我需要这个用于一个项目。
谢谢
1 回复
更多关于Golang中Soap、x509与wsse的实现与应用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
在Go语言中,实现SOAP的WSSE(WS-Security)安全功能通常需要结合多个库来处理SOAP协议、XML签名和x509证书。虽然Go标准库和第三方库没有直接提供完整的WSSE实现,但可以通过以下方式构建:
- SOAP处理:使用第三方库如
github.com/hooklift/gowsdl生成SOAP客户端代码,或手动构建SOAP信封。 - WSSE头生成:手动创建WSSE安全头,包括UsernameToken或x509证书信息。
- x509证书处理:使用Go标准库
crypto/x509和crypto/tls加载和验证证书。 - XML签名:使用
github.com/russellhaering/goxmldsig库进行XML签名和验证,这是WSSE的核心部分。
下面是一个示例代码,展示如何构建一个简单的SOAP请求,并添加WSSE安全头(使用UsernameToken)。注意,这只是一个基础示例,实际WSSE实现可能更复杂,涉及时间戳、非ce和签名。
package main
import (
"bytes"
"crypto/sha1"
"encoding/base64"
"encoding/xml"
"fmt"
"io/ioutil"
"net/http"
"time"
)
// 定义SOAP信封结构
type Envelope struct {
XMLName xml.Name `xml:"soap:Envelope"`
Soap string `xml:"xmlns:soap,attr"`
Header Header `xml:"soap:Header"`
Body Body `xml:"soap:Body"`
}
type Header struct {
Security Security `xml:"wsse:Security"`
}
type Security struct {
XMLName xml.Name `xml:"wsse:Security"`
Wsse string `xml:"xmlns:wsse,attr"`
Timestamp Timestamp `xml:"wsu:Timestamp"`
Token UsernameToken
}
type Timestamp struct {
XMLName xml.Name `xml:"wsu:Timestamp"`
Wsu string `xml:"xmlns:wsu,attr"`
Created string `xml:"wsu:Created"`
Expires string `xml:"wsu:Expires"`
}
type UsernameToken struct {
XMLName xml.Name `xml:"wsse:UsernameToken"`
Username string `xml:"wsse:Username"`
Password Password `xml:"wsse:Password"`
Nonce Nonce `xml:"wsse:Nonce"`
Created string `xml:"wsu:Created"`
}
type Password struct {
Type string `xml:"Type,attr"`
Value string `xml:",chardata"`
}
type Nonce struct {
Type string `xml:"EncodingType,attr"`
Value string `xml:",chardata"`
}
type Body struct {
Content string `xml:",innerxml"` // 替换为实际SOAP体内容
}
// 生成WSSE头(使用UsernameToken)
func generateWSSEHeader(username, password string) Security {
nonce := make([]byte, 16)
// 在实际应用中,应使用crypto/rand生成随机nonce
// rand.Read(nonce)
nonceEncoded := base64.StdEncoding.EncodeToString(nonce)
created := time.Now().UTC().Format("2006-01-02T15:04:05Z")
expires := time.Now().Add(5 * time.Minute).UTC().Format("2006-01-02T15:04:05Z")
// 计算密码摘要(WSSE规范)
hasher := sha1.New()
hasher.Write(nonce)
hasher.Write([]byte(created))
hasher.Write([]byte(password))
passwordDigest := base64.StdEncoding.EncodeToString(hasher.Sum(nil))
return Security{
Wsse: "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd",
Timestamp: Timestamp{
Wsu: "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd",
Created: created,
Expires: expires,
},
Token: UsernameToken{
Username: username,
Password: Password{
Type: "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest",
Value: passwordDigest,
},
Nonce: Nonce{
Type: "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary",
Value: nonceEncoded,
},
Created: created,
},
}
}
func main() {
username := "your-username"
password := "your-password"
// 构建SOAP信封
envelope := Envelope{
Soap: "http://schemas.xmlsoap.org/soap/envelope/",
Header: Header{
Security: generateWSSEHeader(username, password),
},
Body: Body{
Content: "<your-soap-body>Replace with actual SOAP body content</your-soap-body>",
},
}
// 序列化为XML
xmlData, err := xml.MarshalIndent(envelope, "", " ")
if err != nil {
panic(err)
}
// 发送SOAP请求
client := &http.Client{}
req, err := http.NewRequest("POST", "https://your-soap-endpoint.com", bytes.NewBuffer(xmlData))
if err != nil {
panic(err)
}
req.Header.Set("Content-Type", "text/xml; charset=utf-8")
req.Header.Set("SOAPAction", "your-soap-action") // 如果端点需要
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println("Response:", string(body))
}
对于x509证书的WSSE实现,需要使用crypto/x509加载证书和私钥,并通过goxmldsig库进行XML签名。以下是添加x509签名的简要示例:
import (
"crypto/x509"
"encoding/pem"
"github.com/russellhaering/goxmldsig"
)
// 加载x509证书和私钥
func loadCertificateAndKey(certPath, keyPath string) (*x509.Certificate, interface{}, error) {
certPEM, err := ioutil.ReadFile(certPath)
if err != nil {
return nil, nil, err
}
block, _ := pem.Decode(certPEM)
cert, err := x509.ParseCertificate(block.Bytes)
if err != nil {
return nil, nil, err
}
keyPEM, err := ioutil.ReadFile(keyPath)
if err != nil {
return nil, nil, err
}
keyBlock, _ := pem.Decode(keyPEM)
privateKey, err := x509.ParsePKCS1PrivateKey(keyBlock.Bytes) // 或使用其他解析方法
if err != nil {
return nil, nil, err
}
return cert, privateKey, nil
}
// 使用goxmldsig签名SOAP体
func signSOAPBody(bodyContent string, cert *x509.Certificate, privateKey interface{}) (string, error) {
ctx := dsig.NewDefaultSigningContext(dsig.TLSCertKeyStore(cert, privateKey))
signed, err := ctx.SignString(bodyContent)
if err != nil {
return "", err
}
return signed, nil
}
在实际项目中,您需要根据WSSE规范调整这些代码,并可能处理更复杂的安全策略。建议参考OASIS WSSE标准文档以确保兼容性。

