防止在模板中转义正斜杠

时间:2016-06-26 10:36:25

标签: templates go go-templates

我正致力于将我的宠物项目从Python转换为Go,以帮助我熟悉该语言。我目前面临的一个问题是,它正在逃避我的正斜杠。所以它会收到一个字符串,如:

%2flocation%2fto%2fsomething

然后变成

<tr><td><a href="/file?file={{.FullFilePath}}">{{.FileName}}</a></td></tr>

现在,只有当它在链接中时才会这样做(从我读过这个转义是上下文的),所以这就是HTML模板中的行:

func renderTemplate(w http.ResponseWriter, tmpl string) {
    t, err := template.ParseFiles(templates_dir+"base.html", templates_dir+tmpl)
    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }
    if tmpl == "view.html" {
        err = t.Execute(w, FileList)
    } else {
        err = t.Execute(w, nil)
    }
    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
    }
}

如果可能,我如何在模板或代码本身中阻止这种情况?

这就是我的模板功能(是的,我知道它是hackish)

std::cout << static_cast<QDoubleSpinBox*>(ui->InitialValuesTable->cellWidget(2, 1))->value() << std::endl;

2 个答案:

答案 0 :(得分:2)

作为.FullFilePath的值,传递template.URL类型的值而不是string,这将告诉html/template包不要逃避它。

例如:

func main() {
    t := template.Must(template.New("").Parse(templ))

    m := map[string]interface{}{
        "FileName":     "something.txt",
        "FileFullPath": template.URL("/location/to/something"),
    }

    if err := t.Execute(os.Stdout, m); err != nil {
        panic(err)
    }
}

const templ = `<tr><td><a href="/file?file={{.FileFullPath}}">{{.FileName}}</a></td></tr>`

输出(在Go Playground上尝试):

<tr><td><a href="/file?file=/location/to/something">something.txt</a></td></tr>

请注意,即使URL中允许使用正斜杠/template包仍会对其进行编码的原因是因为它会分析URL并看到您要包含的值是值一个URL参数(file=XXX),因此它也对斜杠进行编码(这样您传入的所有内容都将成为file URL参数值的一部分)。

如果您打算从URL参数获取服务器端的此文件路径,那么template包的作用是正确的。

但要知道,通过这样做,您将失去阻止代码注入URL的安全性。如果您是提供价值的人并且您知道他们是安全的,那么没有问题。但是,如果数据来自用户输入,请不要这样做。

另请注意,如果您传递整个网址(而不仅仅是其中的一部分),则无需使用template.URL即可使用(在Go Playground上尝试此变体):

func main() {
    t := template.Must(template.New("").Parse(templ))

    m := map[string]interface{}{
        "FileName": "something.txt",
        "FileURL":  "/file?file=/location/to/something",
    }

    if err := t.Execute(os.Stdout, m); err != nil {
        panic(err)
    }
}

const templ = `<tr><td><a href="{{.FileURL}}">{{.FileName}}</a></td></tr>`

另请注意,我认为推荐的方法是将文件路径作为URL路径的一部分而不是参数的值,因此您应该创建这样的URL:

/file/location/to/something

将处理程序(提供文件内容,请参阅this answer作为示例)映射到/file/模式,当匹配并调用处理程序时,切断{{1}来自路径/file/的前缀,其余的将是完整的文件路径。如果您选择此选项,您也不会需要r.URL.Path转换(因为您包含的值不再是网址参数的值):

template.URL

Go Playground上尝试此操作。

同样非常重要:永远不要在处理函数中解析模板!详情请见:

It takes too much time when using "template" package to generate a dynamic web page to client in golang

答案 1 :(得分:0)

好的,所以我找到的解决方案(如果有更好的解决方案请发帖)是基于答案here

我改变了我正在使用的结构:

a = raw_input("Enter a: ")
b = raw_input("Enter b: ")
print "a + b as strings: %s" % a  + b
a = int(a)
b = int(b)
c = a + b
print "a + b as integers: %d" % c

对此:

type File struct {
    FullFilePath string
    FileName     string
}

将html移动到FullFilePath名称中,然后将其放在template.HTML中,这样我生成的每个FullFilePath名称都是这样完成的:

type File struct {
    FullFilePath template.HTML
    FileName     string
}

我的模板文件行已更改为:

file := File{template.HTML("<a href=\"/file?file=" + path + "\"</a>"), f.Name()}