333
schangxiang@126.com
2025-09-19 18966e02fb573c7e2bb0c6426ed792b38b910940
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
'use strict';
 
const urlparse = require('url').parse;
const delegate = require('delegates');
 
module.exports = app => {
 
  /**
   * This is an unsafe redirection, and we WON'T check if the
   * destination url is safe or not.
   * Please DO NOT use this method unless in some very special cases,
   * otherwise there may be security vulnerabilities.
   *
   * @method Response#unsafeRedirect
   * @param {String} url URL to forward
   * @example
   * ```js
   * this.response.unsafeRedirect('http://www.domain.com');
   * this.unsafeRedirect('http://www.domain.com');
   * ```
   */
  app.response.unsafeRedirect = app.response.redirect;
  delegate(app.context, 'response').method('unsafeRedirect');
  /*eslint-disable */
  /**
   * A safe redirection, and we'll check if the URL is in
   * a safe domain or not.
   * We've overridden the default Koa's implementation by adding a 
   * white list as the filter for that.
   *
   * @method Response#redirect
   * @param {String} url URL to forward
   * @example
   * ```js
   * this.response.redirect('/login');
   * this.redirect('/login');
   * ```
   */
  /* eslint-enable */
  app.response.redirect = function redirect(url, alt) {
    url = (url || '/').trim();
 
    // Process with `//`
    if (url[0] === '/' && url[1] === '/') {
      url = '/';
    }
 
    // if begin with '/', it means an internal jump
    if (url[0] === '/' && url[1] !== '\\') {
      return this.unsafeRedirect(url, alt);
    }
 
    const info = urlparse(url);
    // use info.href instead of url
    // ensure illegal hosts are formatted
    // https://foo.bar%0a.com => https://foo.bar/%0a.com
    url = info.href;
 
    const domainWhiteList = this.app.config.security.domainWhiteList;
    if (info.protocol !== 'http:' && info.protocol !== 'https:') {
      url = '/';
    } else if (!info.hostname) {
      url = '/';
    } else {
      if (domainWhiteList && domainWhiteList.length !== 0) {
        if (!this.ctx.isSafeDomain(info.hostname)) {
          const message = `a security problem has been detected for url "${url}", redirection is prohibited.`;
          if (process.env.NODE_ENV === 'production') {
            this.ctx.coreLogger.warn('[egg-security:redirect] %s', message);
            url = '/';
          } else {
            // Exception will be thrown out in a non-PROD env.
            return this.ctx.throw(500, message);
          }
        }
      }
    }
    this.unsafeRedirect(url);
  };
};