mirror of
https://github.com/kataras/iris.git
synced 2025-02-02 15:30:36 +01:00
add Context.SetSameSite(integrates with sessions too) , iris.JSON.ASCII and iris.JSON.Secure option fields
Former-commit-id: fdf0dae234b219c9ca449ae8907d3e459d485dc7
This commit is contained in:
parent
6876f94e67
commit
f03afeef2f
|
@ -22,6 +22,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
"github.com/kataras/iris/v12/core/memstore"
|
"github.com/kataras/iris/v12/core/memstore"
|
||||||
|
|
||||||
|
@ -896,6 +897,14 @@ type Context interface {
|
||||||
//
|
//
|
||||||
// Example: https://github.com/kataras/iris/tree/master/_examples/cookies/basic
|
// Example: https://github.com/kataras/iris/tree/master/_examples/cookies/basic
|
||||||
SetCookie(cookie *http.Cookie, options ...CookieOption)
|
SetCookie(cookie *http.Cookie, options ...CookieOption)
|
||||||
|
// SetSameSite sets a same-site rule for cookies to set.
|
||||||
|
// SameSite allows a server to define a cookie attribute making it impossible for
|
||||||
|
// the browser to send this cookie along with cross-site requests. The main
|
||||||
|
// goal is to mitigate the risk of cross-origin information leakage, and provide
|
||||||
|
// some protection against cross-site request forgery attacks.
|
||||||
|
//
|
||||||
|
// See https://tools.ietf.org/html/draft-ietf-httpbis-cookie-same-site-00 for details.
|
||||||
|
SetSameSite(sameSite http.SameSite)
|
||||||
// SetCookieKV adds a cookie, requires the name(string) and the value(string).
|
// SetCookieKV adds a cookie, requires the name(string) and the value(string).
|
||||||
//
|
//
|
||||||
// By default it expires at 2 hours and it's added to the root path,
|
// By default it expires at 2 hours and it's added to the root path,
|
||||||
|
@ -3163,6 +3172,8 @@ type JSON struct {
|
||||||
UnescapeHTML bool
|
UnescapeHTML bool
|
||||||
Indent string
|
Indent string
|
||||||
Prefix string
|
Prefix string
|
||||||
|
ASCII bool // if true writes with unicode to ASCII content.
|
||||||
|
Secure bool // if true then it adds a "while(1);" when Go slice (to JSON Array) value.
|
||||||
}
|
}
|
||||||
|
|
||||||
// JSONP contains the options for the JSONP (Context's) Renderer.
|
// JSONP contains the options for the JSONP (Context's) Renderer.
|
||||||
|
@ -3187,7 +3198,7 @@ type Markdown struct {
|
||||||
|
|
||||||
var (
|
var (
|
||||||
newLineB = []byte("\n")
|
newLineB = []byte("\n")
|
||||||
// the html codes for unescaping
|
// the html codes for unescaping.
|
||||||
ltHex = []byte("\\u003c")
|
ltHex = []byte("\\u003c")
|
||||||
lt = []byte("<")
|
lt = []byte("<")
|
||||||
|
|
||||||
|
@ -3196,6 +3207,11 @@ var (
|
||||||
|
|
||||||
andHex = []byte("\\u0026")
|
andHex = []byte("\\u0026")
|
||||||
and = []byte("&")
|
and = []byte("&")
|
||||||
|
|
||||||
|
// secure JSON.
|
||||||
|
jsonArrayPrefix = []byte("[")
|
||||||
|
jsonArraySuffix = []byte("]")
|
||||||
|
secureJSONPrefix = []byte("while(1);")
|
||||||
)
|
)
|
||||||
|
|
||||||
// WriteJSON marshals the given interface object and writes the JSON response to the 'writer'.
|
// WriteJSON marshals the given interface object and writes the JSON response to the 'writer'.
|
||||||
|
@ -3237,6 +3253,27 @@ func WriteJSON(writer io.Writer, v interface{}, options JSON, optimize bool) (in
|
||||||
result = bytes.Replace(result, andHex, and, -1)
|
result = bytes.Replace(result, andHex, and, -1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if options.Secure {
|
||||||
|
if bytes.HasPrefix(result, jsonArrayPrefix) && bytes.HasSuffix(result, jsonArraySuffix) {
|
||||||
|
result = append(secureJSONPrefix, result...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if options.ASCII {
|
||||||
|
if len(result) > 0 {
|
||||||
|
buf := new(bytes.Buffer)
|
||||||
|
for _, s := range bytesToString(result) {
|
||||||
|
char := string(s)
|
||||||
|
if s >= 128 {
|
||||||
|
char = fmt.Sprintf("\\u%04x", int64(s))
|
||||||
|
}
|
||||||
|
buf.WriteString(char)
|
||||||
|
}
|
||||||
|
|
||||||
|
result = buf.Bytes()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if prefix := options.Prefix; prefix != "" {
|
if prefix := options.Prefix; prefix != "" {
|
||||||
result = append([]byte(prefix), result...)
|
result = append([]byte(prefix), result...)
|
||||||
}
|
}
|
||||||
|
@ -3244,6 +3281,11 @@ func WriteJSON(writer io.Writer, v interface{}, options JSON, optimize bool) (in
|
||||||
return writer.Write(result)
|
return writer.Write(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// See https://golang.org/src/strings/builder.go#L45
|
||||||
|
func bytesToString(b []byte) string {
|
||||||
|
return *(*string)(unsafe.Pointer(&b))
|
||||||
|
}
|
||||||
|
|
||||||
// DefaultJSONOptions is the optional settings that are being used
|
// DefaultJSONOptions is the optional settings that are being used
|
||||||
// inside `ctx.JSON`.
|
// inside `ctx.JSON`.
|
||||||
var DefaultJSONOptions = JSON{}
|
var DefaultJSONOptions = JSON{}
|
||||||
|
@ -3304,7 +3346,7 @@ func WriteJSONP(writer io.Writer, v interface{}, options JSONP, optimize bool) (
|
||||||
}
|
}
|
||||||
|
|
||||||
if !optimize && options.Indent == "" {
|
if !optimize && options.Indent == "" {
|
||||||
options.Indent = " "
|
options.Indent = " "
|
||||||
}
|
}
|
||||||
|
|
||||||
if indent := options.Indent; indent != "" {
|
if indent := options.Indent; indent != "" {
|
||||||
|
@ -4359,6 +4401,8 @@ func CookieDecode(decode CookieDecoder) CookieOption {
|
||||||
//
|
//
|
||||||
// Example: https://github.com/kataras/iris/tree/master/_examples/cookies/basic
|
// Example: https://github.com/kataras/iris/tree/master/_examples/cookies/basic
|
||||||
func (ctx *context) SetCookie(cookie *http.Cookie, options ...CookieOption) {
|
func (ctx *context) SetCookie(cookie *http.Cookie, options ...CookieOption) {
|
||||||
|
cookie.SameSite = ctx.getSameSite()
|
||||||
|
|
||||||
for _, opt := range options {
|
for _, opt := range options {
|
||||||
opt(cookie)
|
opt(cookie)
|
||||||
}
|
}
|
||||||
|
@ -4366,6 +4410,30 @@ func (ctx *context) SetCookie(cookie *http.Cookie, options ...CookieOption) {
|
||||||
http.SetCookie(ctx.writer, cookie)
|
http.SetCookie(ctx.writer, cookie)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const sameSiteContextKey = "iris.cookie_same_site"
|
||||||
|
|
||||||
|
// SetSameSite sets a same-site rule for cookies to set.
|
||||||
|
// SameSite allows a server to define a cookie attribute making it impossible for
|
||||||
|
// the browser to send this cookie along with cross-site requests. The main
|
||||||
|
// goal is to mitigate the risk of cross-origin information leakage, and provide
|
||||||
|
// some protection against cross-site request forgery attacks.
|
||||||
|
//
|
||||||
|
// See https://tools.ietf.org/html/draft-ietf-httpbis-cookie-same-site-00 for details.
|
||||||
|
func (ctx *context) SetSameSite(sameSite http.SameSite) {
|
||||||
|
ctx.Values().Set(sameSiteContextKey, sameSite)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ctx *context) getSameSite() http.SameSite {
|
||||||
|
if v := ctx.Values().Get(sameSiteContextKey); v != nil {
|
||||||
|
sameSite, ok := v.(http.SameSite)
|
||||||
|
if ok {
|
||||||
|
return sameSite
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return http.SameSiteDefaultMode
|
||||||
|
}
|
||||||
|
|
||||||
// SetCookieKV adds a cookie, requires the name(string) and the value(string).
|
// SetCookieKV adds a cookie, requires the name(string) and the value(string).
|
||||||
//
|
//
|
||||||
// By default it expires at 2 hours and it's added to the root path,
|
// By default it expires at 2 hours and it's added to the root path,
|
||||||
|
|
|
@ -95,7 +95,7 @@ func (s *Sessions) Start(ctx context.Context, cookieOptions ...context.CookieOpt
|
||||||
return s.provider.Read(cookieValue, s.config.Expires)
|
return s.provider.Read(cookieValue, s.config.Expires)
|
||||||
}
|
}
|
||||||
|
|
||||||
const contextSessionKey = "_iris_session"
|
const contextSessionKey = "iris.session"
|
||||||
|
|
||||||
// Handler returns a sessions middleware to register on application routes.
|
// Handler returns a sessions middleware to register on application routes.
|
||||||
func (s *Sessions) Handler(cookieOptions ...context.CookieOption) context.Handler {
|
func (s *Sessions) Handler(cookieOptions ...context.CookieOption) context.Handler {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user