Mercurial > gemma
comparison pkg/middleware/modifyquery.go @ 419:6627c48363a0
First attempt for user injection of proxy for using GeoServer with role based security.
author | Sascha L. Teichmann <sascha.teichmann@intevation.de> |
---|---|
date | Thu, 16 Aug 2018 13:39:13 +0200 |
parents | |
children | ffdb507d5b42 |
comparison
equal
deleted
inserted
replaced
418:c70ddc6eb168 | 419:6627c48363a0 |
---|---|
1 package middleware | |
2 | |
3 import ( | |
4 "log" | |
5 "net/http" | |
6 "net/url" | |
7 "strings" | |
8 | |
9 "gemma.intevation.de/gemma/pkg/auth" | |
10 ) | |
11 | |
12 // ParseQuery is a modified version of the internal query | |
13 // parser of the url.parseQuery of the standard library. | |
14 func ParseQuery( | |
15 m url.Values, | |
16 query string, | |
17 keySep, valueSep string, | |
18 unescape func(string) (string, error), | |
19 ) error { | |
20 if unescape == nil { | |
21 unescape = url.QueryUnescape | |
22 } | |
23 for query != "" { | |
24 key := query | |
25 if i := strings.Index(key, keySep); i >= 0 { | |
26 key, query = key[:i], key[i+1:] | |
27 | |
28 } else { | |
29 query = "" | |
30 } | |
31 if key == "" { | |
32 continue | |
33 } | |
34 value := "" | |
35 if i := strings.Index(key, valueSep); i >= 0 { | |
36 key, value = key[:i], key[i+1:] | |
37 } | |
38 key, err := unescape(key) | |
39 if err != nil { | |
40 return err | |
41 } | |
42 value, err = unescape(value) | |
43 if err != nil { | |
44 return err | |
45 } | |
46 m[key] = append(m[key], value) | |
47 } | |
48 return nil | |
49 } | |
50 | |
51 func ModifyQuery(next http.Handler, modify func(*http.Request, url.Values) error) http.Handler { | |
52 | |
53 return http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { | |
54 | |
55 // GeoServer query parameters contain ';' as sub key separators. | |
56 // If we would use req.URL.Query() this would be split | |
57 // at the wrong level resulting in broken key/value pairs. | |
58 // So we do the splitting ourselves. | |
59 | |
60 parameters := make(url.Values) | |
61 | |
62 if err := ParseQuery(parameters, req.URL.RawQuery, "&", "=", nil); err != nil { | |
63 log.Printf("parsing query failed: %v\n", err) | |
64 http.Error(rw, http.StatusText(http.StatusBadRequest), http.StatusBadRequest) | |
65 return | |
66 } | |
67 | |
68 if err := modify(req, parameters); err != nil { | |
69 log.Printf("modifying query parameters failed: %v\n", err) | |
70 http.Error(rw, http.StatusText(http.StatusBadRequest), http.StatusBadRequest) | |
71 } | |
72 | |
73 req.URL.RawQuery = parameters.Encode() | |
74 | |
75 next.ServeHTTP(rw, req) | |
76 }) | |
77 } | |
78 | |
79 func InjectUser(req *http.Request, parameters url.Values) error { | |
80 // To prevent SQL injections | |
81 parameters.Del("env") | |
82 | |
83 session, ok := auth.GetSession(req) | |
84 if ok && !strings.ContainsAny(session.User, `\"':;`) { | |
85 log.Printf("Injecting user %s\n", session.User) | |
86 parameters.Set("env", "user:"+session.User) | |
87 } | |
88 return nil | |
89 } |