r.ParseForm字段顺序

huangapple go评论81阅读模式
英文:

r.ParseForm field order

问题

所以我想保留帖子字段的顺序。
但是现在使用http的ParseForm函数,它会将字段放入一个映射中,每次顺序都会不同。

原始查询:a=1&b=2&c=3 可能变成 b=2&c=3&a=1 或者任意随机顺序。

由于我对查询进行哈希处理,并将其与用户的查询哈希进行比较,由于字段的顺序是随机的,所以我这边的哈希值会不断变化。

代码:

func parsePostQuery(r *http.Request, hashQuery string) bool {
    urlquery := url.Values{}

    r.ParseForm()
    
    for k, p := range r.Form {
        urlquery.Set(k, p[0])
    }

    //一些伪代码
    if hashQuery == hash(urlquery.Encode()){
        return true
    }
    
    return false
}

如何解析用户提交的字段并保留用户的字段顺序?

附注:我事先不知道字段名称。

英文:

So I would like to preserve the order of the post fields.
But now using the http ParseForm function it will put the fields into a map which will have a different order each time.

The original query : a=1&b=2&c=3 can become b=2&c=3&a=1 or any random order.

Since I hash the query and compare it with the hash of the user his query the hash on my side changes all the time since the order of the fields are random.

Code:

func parsePostQuery(r *http.Request, hashQuery string) bool {
    urlquery := url.Values{}

    r.ParseForm()
    
    for k, p := range r.Form {
        urlquery.Set(k, p[0])
    }

    //some psuedo code
    if hashQuery == hash(urlquery.Encode()){
        return true
    }
    
    return false
}

How can I parse the fields that are submitted by the user and keep the field order of the user?

Sidenote: I do not know the field names in advance.

答案1

得分: 1

在与其他答案相同的领域中,您需要让客户端在计算哈希之前按字母顺序排列所有参数。您提供的代码应该可以正常工作;values.Encode()会自动按键对值进行排序

> Encode将值编码为“URL编码”形式(“bar=baz&foo=quux”),按键排序

无法保留客户端的顺序;实际上,您收到的顺序可能与客户端端的顺序不同。尽管可能性很小,但不能保证中间过程不会改变事物。

英文:

In the same area as other answers, you will need the clients to calculate their hash by alphabetizing all parameters before hashing. The code you've supplied should work fine; values.Encode() will sort the values by key on it's own:

> Encode encodes the values into “URL encoded” form ("bar=baz&foo=quux") sorted by key.

There's no way to preserve the ordering of the client; in fact, what you receive may not even be how it was ordered on the client end. However unlikely, there's no guarantee that intermediate processes won't change things.

答案2

得分: 0

你不能隐式地对map进行排序,因为map的底层数据结构是一个无序的映射关系。但是,你可以采取额外的步骤来以排序的方式访问map。

Go maps in action中展示了一种以排序方式访问map的简单方法。你可以创建一个键的切片,对该切片进行排序,并通过在排序后的切片上迭代键来访问map的值。

对于你的示例,代码如下:

package main

import (
	"crypto/md5"
	"fmt"
	"io"
	"sort"
)

func main() {
	// 这与url.Values()的结构相同
	var m map[string][]string = make(map[string][]string)
	m["c"] = []string{"19.95"}
	m["b"] = []string{"foo", "bar", "baz"}
	m["a"] = []string{"1"}

	// 注意,playground是确定性的,所以顺序应该在那里保留
	// 但在现实世界中,你不能依赖这一点
	fmt.Println("未排序")
	for k, v := range m {
		fmt.Println("键:", k, "值:", v)
	}

	var keys []string
	for k := range m {
		keys = append(keys, k)
	}
	sort.Strings(keys)

	hash := md5.New()
	fmt.Println("\n排序后")
	for _, k := range keys {

		fmt.Println("键:", k, "值:", m[k])

		// 将键/值对添加到哈希中
		fmt.Printf("\t将键'%s'添加到哈希中\n", k)
		io.WriteString(hash, k)
		for _, v := range m[k] {
			fmt.Printf("\t将值'%s'添加到哈希中\n", v)
			io.WriteString(hash, v)
		}
	}
	fmt.Printf("\n哈希值: %x", hash.Sum(nil))
}

你可以在Playground上运行以上代码

英文:

tl;dr: You can't implicitly. The underlying data structure is a map, for which the order is not guaranteed. You need to take additional steps.

However Go maps in action shows an easy way to access the map in a sorted way. You create a slice of the keys, sort that slice and access the map value by iterating over the keys in the sorted slice.

For your example, it would look something like this

package main

import (
	"crypto/md5"
	"fmt"
	"io"
	"sort"
)

func main() {
	// Which is the same structure as url.Values()
	var m map[string][]string = make(map[string][]string)
	m["c"] = []string{"19.95"}
	m["b"] = []string{"foo", "bar", "baz"}
	m["a"] = []string{"1"}

	// Note that playground is deterministic, so the order should be preserved there
	// However, you can not rely on that in the real world
	fmt.Println("Unsorted")
	for k, v := range m {
		fmt.Println("Key:", k, "Value:", v)
	}

	var keys []string
	for k := range m {
		keys = append(keys, k)
	}
	sort.Strings(keys)

	hash := md5.New()
	fmt.Println("\nSorted")
	for _, k := range keys {

		fmt.Println("Key:", k, "Value:", m[k])

		// Add Key/Value pair to hash
		fmt.Printf("\tAdding KEY '%s' to hash\n", k)
		io.WriteString(hash, k)
		for _, v := range m[k] {
			fmt.Printf("\tAdding VALUE '%s' to hash\n", v)
			io.WriteString(hash, v)
		}
	}
	fmt.Printf("\nHash: %x", hash.Sum(nil))
}

<kbd>Run above code on Playground</kbd>

答案3

得分: 0

你可以读取请求体并检查表单参数。它们将按照请求中的顺序出现(希望你的客户端应用程序也知道保持这个顺序)。

你可以创建一个用于读取请求体的读取器。一个示例代码如下:

body, err := ioutil.ReadAll(r.Body)
if err != nil {
    fmt.Println("读取错误")
    return
}
fmt.Println("请求体:", string(body))

注意:要注意内容类型。

英文:

You can read the request body and check for the form parameters. They will appear in the same order as in the request(hope your client application is also aware of this order preserving)

You can create a reader for reading the request body. A sample code looks like

body, err := ioutil.ReadAll(r.Body)
if err != nil {
	fmt.Println(&quot;Reading Error &quot;)
	return 
}
fmt.Println(&quot;Req Body  :  &quot;, string(body))

Note : Be aware of the content type

huangapple
  • 本文由 发表于 2016年2月3日 18:56:10
  • 转载请务必保留本文链接:https://go.coder-hub.com/35175107.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定