日本熟妇hd丰满老熟妇,中文字幕一区二区三区在线不卡 ,亚洲成片在线观看,免费女同在线一区二区

為自定義域名配置簽名認證

函數計算支持為自定義配置簽名認證,當請求消息到達函數計算網關后,網關會對開啟簽名認證的自定義域名上的請求進行認證,您的函數無需再次對請求簽名進行認證,只需關注業務邏輯即可。本文介紹如何通過控制臺為自定義域名配置簽名認證。

前提條件

創建自定義域名

操作步驟

  1. 登錄函數計算控制臺,在左側導航欄,選擇高級功能 > 域名管理。

  2. 在頂部菜單欄,選擇地域,然后在域名管理頁面,單擊目標域名。

  3. 單擊右上角的編輯,在編輯自定義域名頁面的認證設置區域,認證方式設置為簽名認證,然后單擊保存

    image.png

結果驗證

在本地編寫代碼并執行代碼,代碼目錄結構如下。

image

代碼示例如下。

  • signature.go

    package sign
    
    import (
    	"bytes"
    	"crypto/hmac"
    	"crypto/sha1"
    	"encoding/base64"
    	"hash"
    	"io"
    	"net/http"
    	"sort"
    	"strings"
    )
    
    // GetPOPAuthStr ... GetAuthStr get signature strings
    //
    //	@param accessKeyID
    //	@param accessKeySecret
    //	@param req
    //	@return string
    func GetPOPAuthStr(accessKeyID string, accessKeySecret string, req *http.Request) string {
    	return "acs " + accessKeyID + ":" + GetPOPSignature(accessKeySecret, req)
    }
    
    // GetPOPSignature ... ...
    //
    //	@param akSecret
    //	@param req
    //	@return string
    func GetPOPSignature(akSecret string, req *http.Request) string {
    	stringToSign := getStringToSign(req)
    	// fmt.Printf("stringToSign: %s\n", stringToSign)
    	return GetROASignature(stringToSign, akSecret)
    }
    
    // GetROASignature ... ...
    //
    //	@param stringToSign
    //	@param secret
    //	@return string
    func GetROASignature(stringToSign string, secret string) string {
    	h := hmac.New(func() hash.Hash { return sha1.New() }, []byte(secret))
    	io.WriteString(h, stringToSign)
    	signedStr := base64.StdEncoding.EncodeToString(h.Sum(nil))
    	return signedStr
    }
    
    // getStringToSign ...
    func getStringToSign(req *http.Request) string {
    	queryParams := make(map[string]string)
    	for k, v := range req.URL.Query() {
    		queryParams[k] = v[0]
    	}
    	// sort QueryParams by key
    	var queryKeys []string
    	for key := range queryParams {
    		queryKeys = append(queryKeys, key)
    	}
    	sort.Strings(queryKeys)
    	tmp := ""
    	for i := 0; i < len(queryKeys); i++ {
    		queryKey := queryKeys[i]
    		v := queryParams[queryKey]
    		if v != "" {
    			tmp = tmp + "&" + queryKey + "=" + v
    		} else {
    			tmp = tmp + "&" + queryKey
    		}
    	}
    	resource := req.URL.EscapedPath()
    	if tmp != "" {
    		tmp = strings.TrimLeft(tmp, "&")
    		resource = resource + "?" + tmp
    	}
    	return getSignedStr(req, resource)
    }
    
    func getSignedStr(req *http.Request, canonicalizedResource string) string {
    	temp := make(map[string]string)
    
    	for k, v := range req.Header {
    		if strings.HasPrefix(strings.ToLower(k), "x-acs-") {
    			temp[strings.ToLower(k)] = v[0]
    		}
    	}
    	hs := newSorter(temp)
    
    	// Sort the temp by the ascending order
    	hs.Sort()
    
    	// Get the canonicalizedOSSHeaders
    	canonicalizedOSSHeaders := ""
    	for i := range hs.Keys {
    		canonicalizedOSSHeaders += hs.Keys[i] + ":" + hs.Vals[i] + "\n"
    	}
    
    	// Give other parameters values
    	// when sign URL, date is expires
    	date := req.Header.Get("Date")
    	accept := req.Header.Get("Accept")
    	contentType := req.Header.Get("Content-Type")
    	contentMd5 := req.Header.Get("Content-MD5")
    
    	signStr := req.Method + "\n" + accept + "\n" + contentMd5 + "\n" + contentType + "\n" +
    		date + "\n" + canonicalizedOSSHeaders + canonicalizedResource
    	return signStr
    }
    
    // Sorter ...
    type Sorter struct {
    	Keys []string
    	Vals []string
    }
    
    func newSorter(m map[string]string) *Sorter {
    	hs := &Sorter{
    		Keys: make([]string, 0, len(m)),
    		Vals: make([]string, 0, len(m)),
    	}
    
    	for k, v := range m {
    		hs.Keys = append(hs.Keys, k)
    		hs.Vals = append(hs.Vals, v)
    	}
    	return hs
    }
    
    // Sort is an additional function for function SignHeader.
    func (hs *Sorter) Sort() {
    	sort.Sort(hs)
    }
    
    // Len is an additional function for function SignHeader.
    func (hs *Sorter) Len() int {
    	return len(hs.Vals)
    }
    
    // Less is an additional function for function SignHeader.
    func (hs *Sorter) Less(i, j int) bool {
    	return bytes.Compare([]byte(hs.Keys[i]), []byte(hs.Keys[j])) < 0
    }
    
    // Swap is an additional function for function SignHeader.
    func (hs *Sorter) Swap(i, j int) {
    	hs.Vals[i], hs.Vals[j] = hs.Vals[j], hs.Vals[i]
    	hs.Keys[i], hs.Keys[j] = hs.Keys[j], hs.Keys[i]
    }
  • go.mod

    module auth.fc.aliyun.com
    
    go 1.17
  • main.go

    以下代碼示例使用環境變量獲取AccessKey的方式進行調用,僅供參考,建議使用更安全的STS方式。更多信息,請參見創建AccessKey管理訪問憑證。

    package main
    
    import (
    	"bytes"
    	"encoding/json"
    	"fmt"
    	"io/ioutil"
    	"net/http"
    	"os"
    	"time"
    
    	"auth.fc.aliyun.com/sign"
    )
    
    func main() {
    	// 請求的URL,請根據實際修改
    	url := "您的自定義域名或者 HTTP 觸發器地址"
     
            // 本示例將AccessKey ID和AccessKey Secret保存在環境變量中實現身份認證為例。
      // 請確保代碼運行環境設置了環境變量 ALIBABA_CLOUD_ACCESS_KEY_ID 和 ALIBABA_CLOUD_ACCESS_KEY_SECRET。
    	// 工程代碼泄露可能會導致 AccessKey 泄露,并威脅賬號下所有資源的安全性。
    	ak := os.Getenv("ALIBABA_CLOUD_ACCESS_KEY_ID")
    	sk := os.Getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET")
      
    	// 創建要發送的數據
    	data := map[string]interface{}{
    		"user": "FC 3.0",
    	}
    	jsonData, err := json.Marshal(data)
    	if err != nil {
    		fmt.Printf("Error encoding JSON: %s\n", err)
    		return
    	}
    
    	// 創建請求實例
    	request, err := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
    	if err != nil {
    		fmt.Printf("Error creating request: %s\n", err)
    		return
    	}
    
    	// 添加請求頭信息
    	request.Header.Set("Content-Type", "application/json")
    
    	addAuthInfo(request, ak, sk)
    
    	// 創建http.Client并發送請求
    	client := &http.Client{}
    	response, err := client.Do(request)
    	if err != nil {
    		fmt.Printf("Error sending request to server: %s\n", err)
    		return
    	}
    	defer response.Body.Close()
    
    	// 讀取響應內容
    	body, err := ioutil.ReadAll(response.Body)
    	if err != nil {
    		fmt.Printf("Error reading response body: %s\n", err)
    		return
    	}
    
    	// 打印響應內容
    	fmt.Printf("Response Status: %s\n", response.Status)
    	fmt.Printf("Response Body: %s\n", string(body))
    }
    
    func addAuthInfo(req *http.Request, ak, sk string) {
    	if req.Header.Get("Date") == "" {
    		req.Header.Set("Date", time.Now().UTC().Format(http.TimeFormat))
    	}
    	// copy from lambda-go-sdk sign-url-request
    	if req.URL.Path == "" {
    		req.URL.Path = "/"
    	}
    	authHeader := sign.GetPOPAuthStr(ak, sk, req)
    	req.Header.Set("Authorization", authHeader)
    }

執行成功后結果如下,表示已成功地獲取函數的Response。

Response Status: 200 OK
Response Body: Hello World!

常見問題

為什么自定義域名開啟簽名認證之后,通過自定義域名訪問函數提示:required HTTP header Date was not specified?

該提示說明認證失敗,可能原因如下:

  1. 沒有在請求中進行簽名。

  2. 在請求中做了簽名,但是沒有提供Date這個Header。

為什么自定義域名開啟簽名認證之后,通過自定義域名訪問函數提示:the difference between the request time 'Thu, 04 Jan 2024 01:33:13 GMT' and the current time 'Thu, 04 Jan 2024 08:34:58 GMT' is too large?

該提示說明簽名過期,請您重新使用當前時間進行簽名。

為什么自定義域名開啟簽名認證之后,通過自定義域名訪問函數提示:The request signature we calculated does not match the signature you provided. Check your access key and signing method?

請求中的簽名與函數計算計算得到的簽名不一致,認證失敗。