如何设置多值的HTTP头,例如Content-Security-Policy?

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

How do I set multi-value HTTP headers, like Content-Security-Policy?

问题

我正在尝试在http.ResponseWriter对象上设置Content-Security-Policy头。这是一个具有多个值的头部。我的问题是,http.Header的所有方法都需要一个键和一个值。例如,Set()方法的形式如下:

func (h Header) Set(key, value string)

没有一种方法可以将值的切片分配给头字段。我想要一个看起来像这样的头部。

header := http.Header{
    "Content-Type": {"text/html; charset=UTF-8"},
    "Content-Security-Policy": {"default-src 'self'", "font-src themes.googleusercontent.com", "frame-src 'none'", "style-src 'self' fonts.googleapis.com"},
}

这将创建头部,但我不知道如何将其与http.ResponseWriter对象关联起来。此外,如果我以某种方式能够用上述头部替换ResponseWriter的头部,我是否需要手动设置Content-Length字段?

英文:

I'm trying to set the Content-Security-Policy header on a http.ResponseWriter object. This is a header with multiple values. My problem is that all the methods for http.Header take a single key and a single value. For example, the Set() method looks like this:

func (h Header) Set(key, value string)

There's no method for assigning a slice of values to a header field. I want a header that looks like this.

header := http.Header{
    "Content-Type": {"text/html; charset=UTF-8"},
    "Content-Security-Policy": {"default-src 'self'", "font-src themes.googleusercontent.com", "frame-src 'none'", "style-src 'self' fonts.googleapis.com"},
}

This will create the header, but I don't know how to associate it with the http.ResponseWriter object. Furthermore, if I were somehow able to replace the ResponseWriter's header with the header above, would I have to set the Content-Length field by hand?

答案1

得分: 4

我不确定我完全理解这个问题,但是Content-Security-Policy期望一个包含由;分隔的列表的头部。

如果你想使用一个切片,你可以像这样使用:

csp := []string{"default-src: 'self'", "font-src: 'fonts.googleapis.com'", "frame-src: 'none'"}
header := http.Header{
    "Content-Type": {"text/html; charset=UTF-8"},
}
header.Set("Content-Security-Policy", strings.Join(csp, "; "))

如果你想多次发送具有不同值的头部就像你最初打算的那样),你可以使用[`header.Add`](http://golang.org/pkg/net/http/#Header.Add)。

> Add将键值对添加到头部**它会追加**到与键关联的任何现有值

如果你想在你的http处理程序中使用它可以使用[ResponseWriter.Header()](http://golang.org/pkg/net/http/#ResponseWriter)获取头部:

```go
func Handler(rw http.ResponseWriter, req *http.Request) {
    header := rw.Header()
    csp := []string{"default-src: 'self'", "font-src: 'fonts.googleapis.com'", "frame-src: 'none'"}

    header.Set("Content-Type", "text/html; charset=UTF-8")
    header.Set("Content-Security-Policy", strings.Join(csp, "; "))
    rw.WriteHeader(200) //or write anything really
}
英文:

I'm not sure I fully understand the problem, however Content-Security-Policy expects one header that contains a list separated by ;.

If you want to use a slice you can always use something like this:

csp := []string{"default-src: 'self'", "font-src: 'fonts.googleapis.com'", "frame-src: 'none'"}
header := http.Header{
	"Content-Type": {"text/html; charset=UTF-8"},
}
header.Set("Content-Security-Policy", strings.Join(csp, "; "))

Also if you want to send the header multiple times with different values (like you originally intended, I think), you can use header.Add.

>Add adds the key, value pair to the header. It appends to any existing values associated with key.

If you want to use that in your http handler, get the header with ResponseWriter.Header():

func Handler(rw http.ResponseWriter, req *http.Request) {
	header := rw.Header()
	csp := []string{"default-src: 'self'", "font-src: 'fonts.googleapis.com'", "frame-src: 'none'"}

	header.Set("Content-Type": "text/html; charset=UTF-8")
	header.Set("Content-Security-Policy", strings.Join(csp, "; "))
	rw.WriteHeader(200) //or write anything really
}

答案2

得分: 1

这个链接是关于"the other 4"安全头部的,虽然没有直接涉及到CSP,但是可以参考一下。

英文:

This doesn't address CSP directly (yet), but it does cover "the other 4" security headers

http://godoc.org/github.com/kr/secureheader

答案3

得分: 0

我创建了一个中间件来设置CSP头部。

package main

import (
	"gorila-mux/ctrls"
	"log"
	"net/http"

	"github.com/gorilla/context"
	"github.com/gorilla/mux"
)

func main() {
	r := mux.NewRouter()

	r.HandleFunc("/", ctrls.HomeHandler)
	r.PathPrefix("/public/").Handler(http.StripPrefix("/public/", http.FileServer(http.Dir("public/"))))
	http.Handle("/", r)
	r.Use(setCSPHeaders)
	log.Print("Project is serving on port 7000 : http://localhost:7000")
	http.ListenAndServe(":7000", context.ClearHandler(http.DefaultServeMux))

}

func setCSPHeaders(next http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		//	w.Header().Set("Content-Type", "application/json; charset=utf-8")
		w.Header().Set("Content-Security-Policy", "default-src 'self'; script-src 'self'; object-src 'self';style-src 'self' img-src 'self'; media-src 'self'; frame-ancestors 'self'; frame-src 'self'; connect-src 'self'")
		next.ServeHTTP(w, r)
	})
}

以上是要翻译的内容。

英文:

I created a middleware to set the CSP header.

package main

import (
	"gorila-mux/ctrls"
	"log"
	"net/http"

	"github.com/gorilla/context"
	"github.com/gorilla/mux"
)

func main() {
	r := mux.NewRouter()

	r.HandleFunc("/", ctrls.HomeHandler)
	r.PathPrefix("/public/").Handler(http.StripPrefix("/public/", http.FileServer(http.Dir("public/"))))
	http.Handle("/", r)
	r.Use(setCSPHeaders)
	log.Print("Project is serving on port 7000 : http://localhost:7000")
	http.ListenAndServe(":7000", context.ClearHandler(http.DefaultServeMux))

}


func setCSPHeaders(next http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		//	w.Header().Set("Content-Type", "application/json; charset=utf-8")
		w.Header().Set("Content-Security-Policy", "default-src 'self'; script-src 'self'; object-src 'self';style-src 'self' img-src 'self'; media-src 'self'; frame-ancestors 'self'; frame-src 'self'; connect-src 'self'")
		next.ServeHTTP(w, r)
	})
}

huangapple
  • 本文由 发表于 2014年7月30日 11:46:56
  • 转载请务必保留本文链接:https://go.coder-hub.com/25028441.html
匿名

发表评论

匿名网友

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

确定