mirror of
http://git.haproxy.org/git/haproxy.git/
synced 2025-03-25 04:17:42 +00:00
[MINOR] redirect: add support for "set-cookie" and "clear-cookie"
It is now possible to set or clear a cookie during a redirection. This is useful for logout pages, or for protecting against some DoSes. Check the documentation for the options supported by the "redirect" keyword. (cherry-picked from commit 4af993822e880d8c932f4ad6920db4c9242b0981)
This commit is contained in:
parent
79da4697ca
commit
0140f2553c
@ -2336,34 +2336,68 @@ no option transparent
|
||||
"transparent" option of the "bind" keyword.
|
||||
|
||||
|
||||
redirect location <to> [code <code>] {if | unless} <condition>
|
||||
redirect prefix <to> [drop-query] [code <code>] {if | unless} <condition>
|
||||
redirect location <to> [code <code>] <option> {if | unless} <condition>
|
||||
redirect prefix <to> [code <code>] <option> {if | unless} <condition>
|
||||
Return an HTTP redirection if/unless a condition is matched
|
||||
May be used in sections : defaults | frontend | listen | backend
|
||||
no | yes | yes | yes
|
||||
|
||||
If/unless the condition is matched, the HTTP request will lead to a redirect
|
||||
response. There are currently two types of redirections : "location" and
|
||||
"prefix". With "location", the exact value in <to> is placed into the HTTP
|
||||
"Location" header. With "prefix", the "Location" header is built from the
|
||||
concatenation of <to> and the URI. If the optional "drop-query" keyword is
|
||||
used in a prefix-based redirection, then the location will be set without any
|
||||
possible query-string, which is useful for directing users to a non-secure
|
||||
page for instance. The "prefix" mode is particularly suited for global site
|
||||
redirections.
|
||||
response.
|
||||
|
||||
The code is optional. It indicates in <code> which type of HTTP redirection
|
||||
is desired. Only codes 301, 302 and 303 are supported. 302 is used if no code
|
||||
is specified.
|
||||
Arguments :
|
||||
<to> With "redirect location", the exact value in <to> is placed into
|
||||
the HTTP "Location" header. In case of "redirect prefix", the
|
||||
"Location" header is built from the concatenation of <to> and the
|
||||
complete URI, including the query string, unless the "drop-query"
|
||||
option is specified (see below).
|
||||
|
||||
<code> The code is optional. It indicates which type of HTTP redirection
|
||||
is desired. Only codes 301, 302 and 303 are supported, and 302 is
|
||||
used if no code is specified. 301 means "Moved permanently", and
|
||||
a browser may cache the Location. 302 means "Moved permanently"
|
||||
and means that the browser should not cache the redirection. 303
|
||||
is equivalent to 302 except that the browser will fetch the
|
||||
location with a GET method.
|
||||
|
||||
<option> There are several options which can be specified to adjust the
|
||||
expected behaviour of a redirection :
|
||||
|
||||
- "drop-query"
|
||||
When this keyword is used in a prefix-based redirection, then the
|
||||
location will be set without any possible query-string, which is useful
|
||||
for directing users to a non-secure page for instance. It has no effect
|
||||
with a location-type redirect.
|
||||
|
||||
- "set-cookie NAME[=value]"
|
||||
A "Set-Cookie" header will be added with NAME (and optionally "=value")
|
||||
to the response. This is sometimes used to indicate that a user has
|
||||
been seen, for instance to protect against some types of DoS. No other
|
||||
cookie option is added, so the cookie will be a session cookie. Note
|
||||
that for a browser, a sole cookie name without an equal sign is
|
||||
different from a cookie with an equal sign.
|
||||
|
||||
- "clear-cookie NAME[=]"
|
||||
A "Set-Cookie" header will be added with NAME (and optionally "="), but
|
||||
with the "Max-Age" attribute set to zero. This will tell the browser to
|
||||
delete this cookie. It is useful for instance on logout pages. It is
|
||||
important to note that clearing the cookie "NAME" will not remove a
|
||||
cookie set with "NAME=value". You have to clear the cookie "NAME=" for
|
||||
that, because the browser makes the difference.
|
||||
|
||||
Example: move the login URL only to HTTPS.
|
||||
acl clear dst_port 80
|
||||
acl secure dst_port 8080
|
||||
acl login_page url_beg /login
|
||||
acl logout url_beg /logout
|
||||
acl uid_given url_reg /login?userid=[^&]+
|
||||
acl cookie_set hdr_sub(cookie) SEEN=1
|
||||
|
||||
redirect prefix https://mysite.com set-cookie SEEN=1 if !cookie_set
|
||||
redirect prefix https://mysite.com if login_page !secure
|
||||
redirect prefix http://mysite.com drop-query if login_page !uid_given
|
||||
redirect location http://mysite.com/ if !login_page secure
|
||||
redirect location / clear-cookie USERID= if logout
|
||||
|
||||
See section 2.3 about ACL usage.
|
||||
|
||||
|
@ -267,6 +267,8 @@ struct redirect_rule {
|
||||
char *rdr_str;
|
||||
int code;
|
||||
unsigned int flags;
|
||||
int cookie_len;
|
||||
char *cookie_str;
|
||||
};
|
||||
|
||||
extern struct proxy *proxy;
|
||||
|
@ -1118,6 +1118,8 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
|
||||
int type = REDIRECT_TYPE_NONE;
|
||||
int code = 302;
|
||||
char *destination = NULL;
|
||||
char *cookie = NULL;
|
||||
int cookie_set = 0;
|
||||
unsigned int flags = REDIRECT_FLAG_NONE;
|
||||
|
||||
cur_arg = 1;
|
||||
@ -1144,6 +1146,28 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
|
||||
cur_arg++;
|
||||
destination = args[cur_arg];
|
||||
}
|
||||
else if (!strcmp(args[cur_arg], "set-cookie")) {
|
||||
if (!*args[cur_arg + 1]) {
|
||||
Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
|
||||
file, linenum, args[0], args[cur_arg]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
cur_arg++;
|
||||
cookie = args[cur_arg];
|
||||
cookie_set = 1;
|
||||
}
|
||||
else if (!strcmp(args[cur_arg], "clear-cookie")) {
|
||||
if (!*args[cur_arg + 1]) {
|
||||
Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
|
||||
file, linenum, args[0], args[cur_arg]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
cur_arg++;
|
||||
cookie = args[cur_arg];
|
||||
cookie_set = 0;
|
||||
}
|
||||
else if (!strcmp(args[cur_arg],"code")) {
|
||||
if (!*args[cur_arg + 1]) {
|
||||
Alert("parsing [%s:%d] : '%s': missing HTTP code.\n",
|
||||
@ -1202,6 +1226,20 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
|
||||
rule->cond = cond;
|
||||
rule->rdr_str = strdup(destination);
|
||||
rule->rdr_len = strlen(destination);
|
||||
if (cookie) {
|
||||
/* depending on cookie_set, either we want to set the cookie, or to clear it.
|
||||
* a clear consists in appending "; Max-Age=0" at the end.
|
||||
*/
|
||||
rule->cookie_len = strlen(cookie);
|
||||
if (cookie_set)
|
||||
rule->cookie_str = strdup(cookie);
|
||||
else {
|
||||
rule->cookie_str = malloc(rule->cookie_len + 12);
|
||||
memcpy(rule->cookie_str, cookie, rule->cookie_len);
|
||||
memcpy(rule->cookie_str + rule->cookie_len, "; Max-Age=0", 12);
|
||||
rule->cookie_len += 11;
|
||||
}
|
||||
}
|
||||
rule->type = type;
|
||||
rule->code = code;
|
||||
rule->flags = flags;
|
||||
|
@ -1932,6 +1932,15 @@ int http_process_request(struct session *s, struct buffer *req)
|
||||
break;
|
||||
}
|
||||
|
||||
if (rule->cookie_len) {
|
||||
memcpy(rdr.str + rdr.len, "\r\nSet-Cookie: ", 14);
|
||||
rdr.len += 14;
|
||||
memcpy(rdr.str + rdr.len, rule->cookie_str, rule->cookie_len);
|
||||
rdr.len += rule->cookie_len;
|
||||
memcpy(rdr.str + rdr.len, "\r\n", 2);
|
||||
rdr.len += 2;
|
||||
}
|
||||
|
||||
/* add end of headers */
|
||||
memcpy(rdr.str + rdr.len, "\r\n\r\n", 4);
|
||||
rdr.len += 4;
|
||||
|
@ -18,10 +18,17 @@ listen sample1
|
||||
acl url_test1 url_reg test1
|
||||
acl url_test2 url_reg test2
|
||||
acl url_test3 url_reg test3
|
||||
acl url_test4 url_reg test4
|
||||
|
||||
acl seen hdr_sub(cookie) SEEN=1
|
||||
|
||||
redirect location /abs/test code 301 if url_test1
|
||||
redirect prefix /pfx/test code 302 if url_test2
|
||||
redirect prefix /pfx/test code 303 drop-query if url_test3
|
||||
|
||||
redirect location /test4 code 302 set-cookie SEEN=1 if url_test4 !seen
|
||||
redirect location / code 302 clear-cookie SEEN= if url_test4 seen
|
||||
|
||||
### unconditional redirection
|
||||
#redirect location https://example.com/ if TRUE
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user