我正在加載一個文本文件,其中有換行符,並將其傳遞給html/templates
。html/templates - 用<br>代替換行
將\n
替換爲加載字符串中的<br>
,它們被模板轉義爲html <br>
並顯示在瀏覽器中,而不是導致行返回。
如何在不切換到text/templates
(沒有XSS保護)的情況下更改此行爲?
我正在加載一個文本文件,其中有換行符,並將其傳遞給html/templates
。html/templates - 用<br>代替換行
將\n
替換爲加載字符串中的<br>
,它們被模板轉義爲html <br>
並顯示在瀏覽器中,而不是導致行返回。
如何在不切換到text/templates
(沒有XSS保護)的情況下更改此行爲?
看來,你可以在你的文本串template.HTMLEscape()第一次消毒,然後做\ n到您信任的替代品
,然後將其用作預先轉義和可信的模板數據。
更新:擴大對柯卡的例子,這是我腦子裏想的:
package main
import (
"html/template"
"os"
"strings"
)
const page = `<!DOCTYPE html>
<html>
<head>
</head>
<body>
<p>{{.}}</p>
</body>
</html>`
const text = `first line
<script>dangerous</script>
last line`
func main() {
t := template.Must(template.New("page").Parse(page))
safe := template.HTMLEscapeString(text)
safe = strings.Replace(safe, "\n", "<br>", -1)
t.Execute(os.Stdout, template.HTML(safe)) // template.HTML encapsulates a known safe HTML document fragment.
}
http://play.golang.org/p/JiH0uD5Zh2
輸出是
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<p>first line<br><script>dangerous</script><br>last line</p>
</body>
</html>
和文本瀏覽器中呈現爲
first line
<script>dangerous</script>
last line
不知道你在哪裏爲<br>
代\n
但如果是在旅途中,你可以投字符串作爲template.HTML
,所以它沒有逃過。
參見:http://golang.org/pkg/html/template/#HTML
如果它在一個模板,應該有可用的管道,{{. | html}}
你可以這樣說:
package main
import (
"html/template"
"os"
)
const page = `<!DOCTYPE html>
<html>
<head>
</head>
<body>
<p>{{.}}</p>
</body>
</html>`
func main() {
t := template.Must(template.New("page").Parse(page))
t.Execute(os.Stdout, template.HTML("<br>"))
}
這實際上是正確的軌道---但看到,輸入不是保存,這需要更多的處理,正如接受的答案中所做的那樣。 – JohnDoe
沒有必要通過整個模板作爲一個不安全的模板(這是不好的做法)。
您應該將地圖傳遞給您的模板,並且只顯式「不安全」您要使用的元素,例如。
package main
import "bytes"
import "fmt"
import "html/template"
import "strings"
var input = `
{{ define "LAYOUT" }}
<html>
<body>
{{ template "CONTENT" . }}
</body>
</html>
{{ end }}
{{ define "CONTENT" }}
Unsafe content: {{ .Unsafe }}
Newlines converted to <br/> follow:
{{ .Normal }}
{{ end }}
{{ template "LAYOUT" . }}
`
var other = `
Hello
World
Again
`
var other2 = `
<script>alert("Owned!");</script>
`
func main() {
var t, err = template.New("sample").Parse(input)
if err != nil {
panic(err)
}
var fixed = strings.Replace(other, "\n", "\n<br/>", -1)
var model = map[string]interface{}{
"Normal": template.HTML(fixed),
"Unsafe": other2,
}
var out bytes.Buffer
t.Execute(&out, model) # <--- !! Notice the model is NOT an HTML type.
var raw = out.String()
fmt.Printf("%s", raw)
}
產量:
Unsafe content: <script>alert("Owned!");</script> Newlines converted to <br/> follow: <br/> Hello <br/> World <br/> Again <br/> </body> </html>
雖然這個想法是正確的,但實現是錯誤的:通過將字符串包裝在「template.HTML(...)」中禁用所有其他轉義,例如將字符串標記爲「安全」。 'other'中的任何單行'
因爲我的字符串是不是安全的,我不能把它轉換成'template.HTML'。 你能詳細說明一下釣魚技巧嗎?非常感謝 –
如果字符串不安全,那麼管道也無濟於事。嘗試在'「\ n」'上分割字符串並將生成的片段傳遞到模板中。使用'range'打印字符串並插入'
'。例如: 'Arr:= strings.Split(myString,「\ n」)''在代碼中,並且 '{{range Arr}} {{。}}
{{end}}'in the模板。 – dskinner
@dskinner,我知道已經晚了,但你應該寫出你的答案。這是一個更清潔的解決方案。 – Nashenas