@midwayjs/security 3.0.0-beta.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +0 -0
- package/README.md +166 -0
- package/dist/config/config.default.d.ts +3 -0
- package/dist/config/config.default.js +39 -0
- package/dist/configuration.d.ts +8 -0
- package/dist/configuration.js +72 -0
- package/dist/error.d.ts +5 -0
- package/dist/error.js +12 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.js +24 -0
- package/dist/interface.d.ts +43 -0
- package/dist/interface.js +3 -0
- package/dist/middleware/base.d.ts +8 -0
- package/dist/middleware/base.js +33 -0
- package/dist/middleware/csp.d.ts +5 -0
- package/dist/middleware/csp.js +81 -0
- package/dist/middleware/csrf.d.ts +11 -0
- package/dist/middleware/csrf.js +161 -0
- package/dist/middleware/hsts.d.ts +5 -0
- package/dist/middleware/hsts.js +27 -0
- package/dist/middleware/noopen.d.ts +5 -0
- package/dist/middleware/noopen.js +23 -0
- package/dist/middleware/nosniff.d.ts +5 -0
- package/dist/middleware/nosniff.js +26 -0
- package/dist/middleware/xframe.d.ts +5 -0
- package/dist/middleware/xframe.js +25 -0
- package/dist/middleware/xssProtection.d.ts +5 -0
- package/dist/middleware/xssProtection.js +23 -0
- package/dist/utils.d.ts +3 -0
- package/dist/utils.js +37 -0
- package/index.d.ts +8 -0
- package/package.json +40 -0
package/CHANGELOG.md
ADDED
|
File without changes
|
package/README.md
ADDED
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
# Security 安全组件
|
|
2
|
+
|
|
3
|
+
适用于 `@midwayjs/faas` 、`@midwayjs/web` 、`@midwayjs/koa` 和 `@midwayjs/express` 多种框架的通用安全组件,支持 `csrf` 、`xss` 等多种安全策略。
|
|
4
|
+
|
|
5
|
+
## 安装使用
|
|
6
|
+
|
|
7
|
+
1. 安装依赖
|
|
8
|
+
```shell
|
|
9
|
+
tnpm i @midwayjs/security --save
|
|
10
|
+
```
|
|
11
|
+
2. 在 configuration 中引入组件,
|
|
12
|
+
```ts
|
|
13
|
+
import * as Security from '@midwayjs/security';
|
|
14
|
+
@Configuration({
|
|
15
|
+
imports: [
|
|
16
|
+
// ...other components
|
|
17
|
+
Security
|
|
18
|
+
],
|
|
19
|
+
})
|
|
20
|
+
export class AutoConfiguration {}
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
## 配置
|
|
26
|
+
```ts
|
|
27
|
+
// 默认配置
|
|
28
|
+
export const security = {
|
|
29
|
+
csrf: {
|
|
30
|
+
enable: true,
|
|
31
|
+
type: 'ctoken',
|
|
32
|
+
useSession: false,
|
|
33
|
+
cookieName: 'csrfToken',
|
|
34
|
+
sessionName: 'csrfToken',
|
|
35
|
+
headerName: 'x-csrf-token',
|
|
36
|
+
bodyName: '_csrf',
|
|
37
|
+
queryName: '_csrf',
|
|
38
|
+
refererWhiteList: [],
|
|
39
|
+
},
|
|
40
|
+
xframe: {
|
|
41
|
+
enable: true,
|
|
42
|
+
value: 'SAMEORIGIN',
|
|
43
|
+
},
|
|
44
|
+
csp: {
|
|
45
|
+
enable: false,
|
|
46
|
+
},
|
|
47
|
+
hsts: {
|
|
48
|
+
enable: false,
|
|
49
|
+
maxAge: 365 * 24 * 3600,
|
|
50
|
+
includeSubdomains: false,
|
|
51
|
+
},
|
|
52
|
+
noopen: {
|
|
53
|
+
enable: false,
|
|
54
|
+
},
|
|
55
|
+
nosniff: {
|
|
56
|
+
enable: false,
|
|
57
|
+
},
|
|
58
|
+
xssProtection: {
|
|
59
|
+
enable: true,
|
|
60
|
+
value: '1; mode=block',
|
|
61
|
+
},
|
|
62
|
+
}
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### csrf
|
|
66
|
+
|
|
67
|
+
| 配置项 | 类型 | 作用描述 | 默认值 |
|
|
68
|
+
| --- | --- | --- | --- |
|
|
69
|
+
| enable | boolean | 是否开启 | true |
|
|
70
|
+
| type | 'all' / 'any' / 'ctoken' / 'referer' | csrf 校验类型,all/any 等于 ctoken + referer | 'ctoken' 从query/header/body 中获取 csrf token |
|
|
71
|
+
| useSession | boolean | csrf token 是否存放在 session 中 | false,默认存放在 cookies 中 |
|
|
72
|
+
| cookieName | string | token 在 cookie 中存放的 字段 | 'csrfToken' |
|
|
73
|
+
| sessionName | string | token 在 session 中存放的 字段 | 'csrfToken' |
|
|
74
|
+
| headerName | string | token 在 header 中存放的 字段 | 'x-csrf-token' |
|
|
75
|
+
| bodyName | string | token 在 body 中存放的 字段 | '_csrf' |
|
|
76
|
+
| queryName | string | token 在 query 中存放的 字段 | '_csrf' |
|
|
77
|
+
| refererWhiteList | Array<string> | 允许的来源白名单 | [] |
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
### xframe
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
xframe 用来配置 `X-Frame-Options` 响应头,用来给浏览器指示允许一个页面可否在 `frame`, `iframe`, `embed` 或者 `object` 中展现的标记。站点可以通过确保网站没有被嵌入到别人的站点里面,从而避免 `clickjacking` 攻击。
|
|
84
|
+
|
|
85
|
+
`X-Frame-Options` 有三个可能的值:
|
|
86
|
+
|
|
87
|
+
+ X-Frame-Options: deny:页面不允许在 frame 中展示
|
|
88
|
+
+ X-Frame-Options: sameorigin:该页面可以在相同域名页面的 frame 中展示
|
|
89
|
+
+ X-Frame-Options: allow-from https://example.com/:该页面可以在指定来源的 frame 中展示
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
| 配置项 | 类型 | 作用描述 | 默认值 |
|
|
94
|
+
| --- | --- | --- | --- |
|
|
95
|
+
| enable | boolean | 是否开启 | true |
|
|
96
|
+
| value | string | X-Frame-Options 值 | 'SAMEORIGIN' |
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
### hsts
|
|
101
|
+
|
|
102
|
+
`HTTP Strict Transport Security`(通常简称为 `HSTS` )是一个安全功能,它告诉浏览器只能通过 `HTTPS` 访问当前资源,而不是 `HTTP`。
|
|
103
|
+
|
|
104
|
+
| 配置项 | 类型 | 作用描述 | 默认值 |
|
|
105
|
+
| --- | --- | --- | --- |
|
|
106
|
+
| enable | boolean | 是否开启 | false |
|
|
107
|
+
| maxAge | number | 在浏览器收到这个请求后的多少 `秒` 时间内凡是访问这个域名下的请求都使用HTTPS请求 | `365 * 24 * 3600` 即一年 |
|
|
108
|
+
| includeSubdomains | boolean | 此规则是否适用于该网站的所有子域名 | false |
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
### csp
|
|
112
|
+
|
|
113
|
+
HTTP 响应头 `Content-Security-Policy` 允许站点管理者控制指定的页面加载哪些资源。这将帮助防止跨站脚本攻击(XSS)。
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
| 配置项 | 类型 | 作用描述 | 默认值 |
|
|
117
|
+
| --- | --- | --- | --- |
|
|
118
|
+
| enable | boolean | 是否开启 | false |
|
|
119
|
+
| policy | Object<key: string, value: string / string[] / boolean> | 策略列表 | {} |
|
|
120
|
+
| reportOnly | boolean | 是否开启 | false |
|
|
121
|
+
| supportIE | boolean | 是否支持IE浏览器 | false |
|
|
122
|
+
|
|
123
|
+
详细的 `policy` 配置可以参考: [Content Security Policy (CSP) 是什么?阿里聚安全](https://www.zhihu.com/question/21979782/answer/122682029)
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
### noopen
|
|
127
|
+
|
|
128
|
+
用于指定 `IE 8` 以上版本的用户不打开文件而直接保存文件。在下载对话框中不显示“打开”选项。
|
|
129
|
+
|
|
130
|
+
| 配置项 | 类型 | 作用描述 | 默认值 |
|
|
131
|
+
| --- | --- | --- | --- |
|
|
132
|
+
| enable | boolean | 是否开启 | false |
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
### nosniff
|
|
138
|
+
|
|
139
|
+
开启后,如果从 `script` 或 `stylesheet` 读入的文件的 `MIME` 类型与指定 `MIME` 类型不匹配,不允许读取该文件。用于防止 `XSS` 等跨站脚本攻击。
|
|
140
|
+
|
|
141
|
+
| 配置项 | 类型 | 作用描述 | 默认值 |
|
|
142
|
+
| --- | --- | --- | --- |
|
|
143
|
+
| enable | boolean | 是否开启 | false |
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
### xssProtection
|
|
149
|
+
|
|
150
|
+
用于启用浏览器的XSS过滤功能,以防止 `XSS` 跨站脚本攻击。
|
|
151
|
+
|
|
152
|
+
`X-XSS-Protection` 响应头是 `IE`,`Chrome` 和 `Safari` 的一个特性,当检测到跨站脚本攻击 (XSS (en-US))时,浏览器将停止加载页面。若网站设置了良好的 `Content-Security-Policy` 来禁用内联 JavaScript ('unsafe-inline'),现代浏览器不太需要这些保护, 但其仍然可以为尚不支持 `CSP` 的旧版浏览器的用户提供保护。
|
|
153
|
+
|
|
154
|
+
`X-XSS-Protection` 可以配置下述四个值
|
|
155
|
+
|
|
156
|
+
+ `0`: 禁止XSS过滤。
|
|
157
|
+
+ `1`:启用XSS过滤(通常浏览器是默认的)。 如果检测到跨站脚本攻击,浏览器将清除页面(删除不安全的部分)。
|
|
158
|
+
+ `1;mode=block`:启用XSS过滤。 如果检测到攻击,浏览器将不会清除页面,而是阻止页面加载。
|
|
159
|
+
+ `1; report=<reporting-URI>`: Chromium only,启用XSS过滤。 如果检测到跨站脚本攻击,浏览器将清除页面并使用CSP report-uri (en-US)指令的功能发送违规报告。
|
|
160
|
+
|
|
161
|
+
| 配置项 | 类型 | 作用描述 | 默认值 |
|
|
162
|
+
| --- | --- | --- | --- |
|
|
163
|
+
| enable | boolean | 是否开启 | false |
|
|
164
|
+
| value | string | X-XSS-Protection 配置 | `1; mode=block` |
|
|
165
|
+
|
|
166
|
+
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.security = void 0;
|
|
4
|
+
exports.security = {
|
|
5
|
+
csrf: {
|
|
6
|
+
enable: true,
|
|
7
|
+
type: 'ctoken',
|
|
8
|
+
useSession: false,
|
|
9
|
+
cookieName: 'csrfToken',
|
|
10
|
+
sessionName: 'csrfToken',
|
|
11
|
+
headerName: 'x-csrf-token',
|
|
12
|
+
bodyName: '_csrf',
|
|
13
|
+
queryName: '_csrf',
|
|
14
|
+
refererWhiteList: [],
|
|
15
|
+
},
|
|
16
|
+
xframe: {
|
|
17
|
+
enable: true,
|
|
18
|
+
value: 'SAMEORIGIN',
|
|
19
|
+
},
|
|
20
|
+
csp: {
|
|
21
|
+
enable: false,
|
|
22
|
+
},
|
|
23
|
+
hsts: {
|
|
24
|
+
enable: false,
|
|
25
|
+
maxAge: 365 * 24 * 3600,
|
|
26
|
+
includeSubdomains: false,
|
|
27
|
+
},
|
|
28
|
+
noopen: {
|
|
29
|
+
enable: false,
|
|
30
|
+
},
|
|
31
|
+
nosniff: {
|
|
32
|
+
enable: false,
|
|
33
|
+
},
|
|
34
|
+
xssProtection: {
|
|
35
|
+
enable: true,
|
|
36
|
+
value: '1; mode=block',
|
|
37
|
+
},
|
|
38
|
+
};
|
|
39
|
+
//# sourceMappingURL=config.default.js.map
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { MidwayApplicationManager } from '@midwayjs/core';
|
|
2
|
+
import { SecurityOptions } from './interface';
|
|
3
|
+
export declare class SecurityConfiguration {
|
|
4
|
+
applicationManager: MidwayApplicationManager;
|
|
5
|
+
security: SecurityOptions;
|
|
6
|
+
onReady(): Promise<void>;
|
|
7
|
+
}
|
|
8
|
+
//# sourceMappingURL=configuration.d.ts.map
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.SecurityConfiguration = void 0;
|
|
13
|
+
const decorator_1 = require("@midwayjs/decorator");
|
|
14
|
+
const DefaultConfig = require("./config/config.default");
|
|
15
|
+
const core_1 = require("@midwayjs/core");
|
|
16
|
+
const csrf_1 = require("./middleware/csrf");
|
|
17
|
+
const xframe_1 = require("./middleware/xframe");
|
|
18
|
+
const hsts_1 = require("./middleware/hsts");
|
|
19
|
+
const noopen_1 = require("./middleware/noopen");
|
|
20
|
+
const _1 = require(".");
|
|
21
|
+
const xssProtection_1 = require("./middleware/xssProtection");
|
|
22
|
+
const csp_1 = require("./middleware/csp");
|
|
23
|
+
let SecurityConfiguration = class SecurityConfiguration {
|
|
24
|
+
async onReady() {
|
|
25
|
+
this.applicationManager
|
|
26
|
+
.getApplications(['koa', 'faas', 'express', 'egg'])
|
|
27
|
+
.forEach(app => {
|
|
28
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
29
|
+
if ((_a = this.security.csrf) === null || _a === void 0 ? void 0 : _a.enable) {
|
|
30
|
+
app.useMiddleware(csrf_1.CSRFMiddleware);
|
|
31
|
+
}
|
|
32
|
+
if ((_b = this.security.csp) === null || _b === void 0 ? void 0 : _b.enable) {
|
|
33
|
+
app.useMiddleware(csp_1.CSPMiddleware);
|
|
34
|
+
}
|
|
35
|
+
if ((_c = this.security.xframe) === null || _c === void 0 ? void 0 : _c.enable) {
|
|
36
|
+
app.useMiddleware(xframe_1.XFrameMiddleware);
|
|
37
|
+
}
|
|
38
|
+
if ((_d = this.security.hsts) === null || _d === void 0 ? void 0 : _d.enable) {
|
|
39
|
+
app.useMiddleware(hsts_1.HSTSMiddleware);
|
|
40
|
+
}
|
|
41
|
+
if ((_e = this.security.noopen) === null || _e === void 0 ? void 0 : _e.enable) {
|
|
42
|
+
app.useMiddleware(noopen_1.NoOpenMiddleware);
|
|
43
|
+
}
|
|
44
|
+
if ((_f = this.security.nosniff) === null || _f === void 0 ? void 0 : _f.enable) {
|
|
45
|
+
app.useMiddleware(_1.NoSniffMiddleware);
|
|
46
|
+
}
|
|
47
|
+
if ((_g = this.security.xssProtection) === null || _g === void 0 ? void 0 : _g.enable) {
|
|
48
|
+
app.useMiddleware(xssProtection_1.XSSProtectionMiddleware);
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
__decorate([
|
|
54
|
+
(0, decorator_1.Inject)(),
|
|
55
|
+
__metadata("design:type", core_1.MidwayApplicationManager)
|
|
56
|
+
], SecurityConfiguration.prototype, "applicationManager", void 0);
|
|
57
|
+
__decorate([
|
|
58
|
+
(0, decorator_1.Config)('security'),
|
|
59
|
+
__metadata("design:type", Object)
|
|
60
|
+
], SecurityConfiguration.prototype, "security", void 0);
|
|
61
|
+
SecurityConfiguration = __decorate([
|
|
62
|
+
(0, decorator_1.Configuration)({
|
|
63
|
+
namespace: 'security',
|
|
64
|
+
importConfigs: [
|
|
65
|
+
{
|
|
66
|
+
default: DefaultConfig,
|
|
67
|
+
},
|
|
68
|
+
],
|
|
69
|
+
})
|
|
70
|
+
], SecurityConfiguration);
|
|
71
|
+
exports.SecurityConfiguration = SecurityConfiguration;
|
|
72
|
+
//# sourceMappingURL=configuration.js.map
|
package/dist/error.d.ts
ADDED
package/dist/error.js
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CSRFError = void 0;
|
|
4
|
+
const core_1 = require("@midwayjs/core");
|
|
5
|
+
// csrf 403
|
|
6
|
+
class CSRFError extends core_1.httpError.ForbiddenError {
|
|
7
|
+
constructor(message) {
|
|
8
|
+
super(message || 'csrf error');
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
exports.CSRFError = CSRFError;
|
|
12
|
+
//# sourceMappingURL=error.js.map
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export { SecurityConfiguration as Configuration } from './configuration';
|
|
2
|
+
export * from './interface';
|
|
3
|
+
export * from './middleware/csrf';
|
|
4
|
+
export * from './middleware/xframe';
|
|
5
|
+
export * from './middleware/hsts';
|
|
6
|
+
export * from './middleware/noopen';
|
|
7
|
+
export * from './middleware/nosniff';
|
|
8
|
+
export * from './middleware/xssProtection';
|
|
9
|
+
export * from './middleware/csp';
|
|
10
|
+
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
|
|
5
|
+
}) : (function(o, m, k, k2) {
|
|
6
|
+
if (k2 === undefined) k2 = k;
|
|
7
|
+
o[k2] = m[k];
|
|
8
|
+
}));
|
|
9
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
10
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
11
|
+
};
|
|
12
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
+
exports.Configuration = void 0;
|
|
14
|
+
var configuration_1 = require("./configuration");
|
|
15
|
+
Object.defineProperty(exports, "Configuration", { enumerable: true, get: function () { return configuration_1.SecurityConfiguration; } });
|
|
16
|
+
__exportStar(require("./interface"), exports);
|
|
17
|
+
__exportStar(require("./middleware/csrf"), exports);
|
|
18
|
+
__exportStar(require("./middleware/xframe"), exports);
|
|
19
|
+
__exportStar(require("./middleware/hsts"), exports);
|
|
20
|
+
__exportStar(require("./middleware/noopen"), exports);
|
|
21
|
+
__exportStar(require("./middleware/nosniff"), exports);
|
|
22
|
+
__exportStar(require("./middleware/xssProtection"), exports);
|
|
23
|
+
__exportStar(require("./middleware/csp"), exports);
|
|
24
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
export interface SecurityOptions {
|
|
2
|
+
csrf: Partial<SecurityCSRFOptions>;
|
|
3
|
+
csp: Partial<SecurityCSPOptions>;
|
|
4
|
+
xframe: Partial<SecurityXFrameOptions>;
|
|
5
|
+
hsts: Partial<SecurityHSTSOptions>;
|
|
6
|
+
noopen: Partial<SecurityEnableOptions>;
|
|
7
|
+
nosniff: Partial<SecurityEnableOptions>;
|
|
8
|
+
xssProtection: Partial<SecurityXSSProtectionOptions>;
|
|
9
|
+
}
|
|
10
|
+
export interface SecurityCSRFOptions extends SecurityEnableOptions {
|
|
11
|
+
type: SecurityCSRFType;
|
|
12
|
+
useSession: boolean;
|
|
13
|
+
cookieName: string | string[];
|
|
14
|
+
sessionName: string;
|
|
15
|
+
headerName: string;
|
|
16
|
+
bodyName: string;
|
|
17
|
+
queryName: string;
|
|
18
|
+
refererWhiteList: string[];
|
|
19
|
+
cookieDomain: (context: any) => string;
|
|
20
|
+
matching: (context: any) => boolean;
|
|
21
|
+
}
|
|
22
|
+
export interface SecurityXFrameOptions extends SecurityEnableOptions {
|
|
23
|
+
value: string;
|
|
24
|
+
}
|
|
25
|
+
export interface SecurityHSTSOptions extends SecurityEnableOptions {
|
|
26
|
+
maxAge: number;
|
|
27
|
+
includeSubdomains: boolean;
|
|
28
|
+
}
|
|
29
|
+
export interface SecurityXSSProtectionOptions extends SecurityEnableOptions {
|
|
30
|
+
value: string;
|
|
31
|
+
}
|
|
32
|
+
export interface SecurityCSPOptions extends SecurityEnableOptions {
|
|
33
|
+
policy: {
|
|
34
|
+
[otherPolicy: string]: string | string[] | boolean;
|
|
35
|
+
};
|
|
36
|
+
reportOnly: boolean;
|
|
37
|
+
supportIE: boolean;
|
|
38
|
+
}
|
|
39
|
+
export interface SecurityEnableOptions {
|
|
40
|
+
enable: boolean;
|
|
41
|
+
}
|
|
42
|
+
export declare type SecurityCSRFType = 'all' | 'any' | 'ctoken' | 'referer';
|
|
43
|
+
//# sourceMappingURL=interface.d.ts.map
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { IMiddleware } from '@midwayjs/core';
|
|
2
|
+
import { SecurityOptions } from '../interface';
|
|
3
|
+
export declare abstract class BaseMiddleware implements IMiddleware<any, any> {
|
|
4
|
+
security: SecurityOptions;
|
|
5
|
+
resolve(app: any): (req: any, res: any, next: any) => Promise<any>;
|
|
6
|
+
abstract compatibleMiddleware(context: any, req: any, res: any, next: any): any;
|
|
7
|
+
}
|
|
8
|
+
//# sourceMappingURL=base.d.ts.map
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.BaseMiddleware = void 0;
|
|
13
|
+
const decorator_1 = require("@midwayjs/decorator");
|
|
14
|
+
class BaseMiddleware {
|
|
15
|
+
resolve(app) {
|
|
16
|
+
if (app.getFrameworkType() === decorator_1.MidwayFrameworkType.WEB_EXPRESS) {
|
|
17
|
+
return async (req, res, next) => {
|
|
18
|
+
return this.compatibleMiddleware(req, req, res, next);
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
else {
|
|
22
|
+
return async (ctx, next) => {
|
|
23
|
+
return this.compatibleMiddleware(ctx, ctx.request, ctx, next);
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
__decorate([
|
|
29
|
+
(0, decorator_1.Config)('security'),
|
|
30
|
+
__metadata("design:type", Object)
|
|
31
|
+
], BaseMiddleware.prototype, "security", void 0);
|
|
32
|
+
exports.BaseMiddleware = BaseMiddleware;
|
|
33
|
+
//# sourceMappingURL=base.js.map
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.CSPMiddleware = void 0;
|
|
10
|
+
const decorator_1 = require("@midwayjs/decorator");
|
|
11
|
+
const base_1 = require("./base");
|
|
12
|
+
const platform_1 = require("platform");
|
|
13
|
+
const non_secure_1 = require("nanoid/non-secure");
|
|
14
|
+
const HEADER = ['x-content-security-policy', 'content-security-policy'];
|
|
15
|
+
const REPORT_ONLY_HEADER = [
|
|
16
|
+
'x-content-security-policy-report-only',
|
|
17
|
+
'content-security-policy-report-only',
|
|
18
|
+
];
|
|
19
|
+
const NONCE = Symbol('midway-security#NONCE');
|
|
20
|
+
let CSPMiddleware = class CSPMiddleware extends base_1.BaseMiddleware {
|
|
21
|
+
async compatibleMiddleware(context, req, res, next) {
|
|
22
|
+
Object.defineProperty(context, 'nonce', {
|
|
23
|
+
get: () => {
|
|
24
|
+
if (!context[NONCE]) {
|
|
25
|
+
context[NONCE] = non_secure_1.nanoid(16);
|
|
26
|
+
}
|
|
27
|
+
return context[NONCE];
|
|
28
|
+
},
|
|
29
|
+
});
|
|
30
|
+
const result = await next();
|
|
31
|
+
let finalHeader;
|
|
32
|
+
let value;
|
|
33
|
+
const { policy = {}, reportOnly, supportIE } = this.security.csp;
|
|
34
|
+
const isIE = (0, platform_1.parse)(req.header['user-agent']).name === 'IE';
|
|
35
|
+
const bufArray = [];
|
|
36
|
+
const headers = reportOnly ? REPORT_ONLY_HEADER : HEADER;
|
|
37
|
+
if (isIE && supportIE) {
|
|
38
|
+
finalHeader = headers[0];
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
finalHeader = headers[1];
|
|
42
|
+
}
|
|
43
|
+
for (const key in policy) {
|
|
44
|
+
value = policy[key];
|
|
45
|
+
value = Array.isArray(value) ? value : [value];
|
|
46
|
+
switch (key) {
|
|
47
|
+
case 'sandbox':
|
|
48
|
+
if (value[0] === true) {
|
|
49
|
+
bufArray.push(key);
|
|
50
|
+
}
|
|
51
|
+
break;
|
|
52
|
+
default:
|
|
53
|
+
if (key === 'script-src') {
|
|
54
|
+
const hasNonce = value.find(val => {
|
|
55
|
+
return val.includes('nonce-');
|
|
56
|
+
});
|
|
57
|
+
if (!hasNonce) {
|
|
58
|
+
value.push(`'nonce-${context.nonce}'`);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
value = value.map(d => {
|
|
62
|
+
if (d.startsWith('.')) {
|
|
63
|
+
d = '*' + d;
|
|
64
|
+
}
|
|
65
|
+
return d;
|
|
66
|
+
});
|
|
67
|
+
bufArray.push(key + ' ' + value.join(' '));
|
|
68
|
+
break;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
const headerString = bufArray.join(';');
|
|
72
|
+
res.set(finalHeader, headerString);
|
|
73
|
+
res.set('x-csp-nonce', context.nonce);
|
|
74
|
+
return result;
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
CSPMiddleware = __decorate([
|
|
78
|
+
(0, decorator_1.Middleware)()
|
|
79
|
+
], CSPMiddleware);
|
|
80
|
+
exports.CSPMiddleware = CSPMiddleware;
|
|
81
|
+
//# sourceMappingURL=csp.js.map
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { BaseMiddleware } from './base';
|
|
2
|
+
export declare class CSRFMiddleware extends BaseMiddleware {
|
|
3
|
+
compatibleMiddleware(context: any, req: any, res: any, next: any): Promise<any>;
|
|
4
|
+
assertCsrf(context: any, request: any): void;
|
|
5
|
+
getCSRFSecret(context: any): any;
|
|
6
|
+
getInputToken(context: any, request: any): any;
|
|
7
|
+
private checkCSRFToken;
|
|
8
|
+
private checkCSRFReferer;
|
|
9
|
+
private ensureCsrfSecret;
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=csrf.d.ts.map
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.CSRFMiddleware = void 0;
|
|
10
|
+
const decorator_1 = require("@midwayjs/decorator");
|
|
11
|
+
const error_1 = require("../error");
|
|
12
|
+
const CsrfTokens = require("csrf");
|
|
13
|
+
const utils_1 = require("../utils");
|
|
14
|
+
const base_1 = require("./base");
|
|
15
|
+
const _CSRF_SECRET = Symbol('midway-security#_CSRF_SECRET');
|
|
16
|
+
const NEW_CSRF_SECRET = Symbol('midway-security#NEW_CSRF_SECRET');
|
|
17
|
+
const tokens = new CsrfTokens();
|
|
18
|
+
let CSRFMiddleware = class CSRFMiddleware extends base_1.BaseMiddleware {
|
|
19
|
+
async compatibleMiddleware(context, req, res, next) {
|
|
20
|
+
context.assertCsrf = () => {
|
|
21
|
+
this.assertCsrf(context, req);
|
|
22
|
+
};
|
|
23
|
+
// Must call this method when user login to ensure each user has independent secret.
|
|
24
|
+
context.rotateCsrfSecret = () => {
|
|
25
|
+
if (!context[NEW_CSRF_SECRET] && this.getCSRFSecret(context)) {
|
|
26
|
+
this.ensureCsrfSecret(context, req, res, true);
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
Object.defineProperty(context, 'csrf', {
|
|
30
|
+
get: () => {
|
|
31
|
+
const secret = context[NEW_CSRF_SECRET] || this.getCSRFSecret(context);
|
|
32
|
+
return secret ? tokens.create(secret) : '';
|
|
33
|
+
},
|
|
34
|
+
});
|
|
35
|
+
// ensure csrf token exists
|
|
36
|
+
if (['any', 'all', 'ctoken'].includes(this.security.csrf.type)) {
|
|
37
|
+
this.ensureCsrfSecret(context, req, res);
|
|
38
|
+
}
|
|
39
|
+
// ignore requests: get, head, options and trace
|
|
40
|
+
const method = req.method.toUpperCase();
|
|
41
|
+
const ignoreMethods = ['GET', 'HEAD', 'OPTIONS', 'TRACE'];
|
|
42
|
+
if (!ignoreMethods.includes(method)) {
|
|
43
|
+
context.assertCsrf();
|
|
44
|
+
}
|
|
45
|
+
return next();
|
|
46
|
+
}
|
|
47
|
+
assertCsrf(context, request) {
|
|
48
|
+
const { type } = this.security.csrf;
|
|
49
|
+
switch (type) {
|
|
50
|
+
case 'ctoken':
|
|
51
|
+
this.checkCSRFToken(context, request);
|
|
52
|
+
break;
|
|
53
|
+
case 'referer':
|
|
54
|
+
this.checkCSRFReferer(context, request);
|
|
55
|
+
break;
|
|
56
|
+
case 'all':
|
|
57
|
+
case 'any':
|
|
58
|
+
this.checkCSRFToken(context, request);
|
|
59
|
+
this.checkCSRFReferer(context, request);
|
|
60
|
+
break;
|
|
61
|
+
default:
|
|
62
|
+
throw new error_1.CSRFError();
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
getCSRFSecret(context) {
|
|
66
|
+
var _a, _b;
|
|
67
|
+
if (context[_CSRF_SECRET]) {
|
|
68
|
+
return context[_CSRF_SECRET];
|
|
69
|
+
}
|
|
70
|
+
const { useSession, sessionName } = this.security.csrf;
|
|
71
|
+
let { cookieName } = this.security.csrf;
|
|
72
|
+
// // get secret from session or cookie
|
|
73
|
+
if (useSession) {
|
|
74
|
+
context[_CSRF_SECRET] = context.session[sessionName] || '';
|
|
75
|
+
}
|
|
76
|
+
else {
|
|
77
|
+
// cookieName support array. so we can change csrf cookie name smoothly
|
|
78
|
+
if (!Array.isArray(cookieName)) {
|
|
79
|
+
cookieName = [cookieName];
|
|
80
|
+
}
|
|
81
|
+
for (const name of cookieName) {
|
|
82
|
+
context[_CSRF_SECRET] =
|
|
83
|
+
((_b = (_a = context.cookies).get) === null || _b === void 0 ? void 0 : _b.call(_a, name, { signed: false })) ||
|
|
84
|
+
context.cookies[name] ||
|
|
85
|
+
'';
|
|
86
|
+
if (context[_CSRF_SECRET]) {
|
|
87
|
+
break;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
return context[_CSRF_SECRET];
|
|
92
|
+
}
|
|
93
|
+
getInputToken(context, request) {
|
|
94
|
+
var _a, _b;
|
|
95
|
+
const { headerName, bodyName, queryName } = this.security.csrf;
|
|
96
|
+
return (((_a = context.query) === null || _a === void 0 ? void 0 : _a[queryName]) ||
|
|
97
|
+
((_b = request.body) === null || _b === void 0 ? void 0 : _b[bodyName]) ||
|
|
98
|
+
(headerName && context.get(headerName)));
|
|
99
|
+
}
|
|
100
|
+
checkCSRFToken(context, request) {
|
|
101
|
+
const tokenSecret = this.getCSRFSecret(context);
|
|
102
|
+
if (!tokenSecret) {
|
|
103
|
+
throw new error_1.CSRFError('missing csrf token');
|
|
104
|
+
}
|
|
105
|
+
const token = this.getInputToken(context, request);
|
|
106
|
+
if (token !== tokenSecret && !tokens.verify(tokenSecret, token)) {
|
|
107
|
+
throw new error_1.CSRFError('invalid csrf token');
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
checkCSRFReferer(context, request) {
|
|
111
|
+
const { refererWhiteList } = this.security.csrf;
|
|
112
|
+
const referer = (context.get('referer') || '').toLowerCase();
|
|
113
|
+
if (!referer) {
|
|
114
|
+
throw new error_1.CSRFError('missing csrf referer');
|
|
115
|
+
}
|
|
116
|
+
const host = (0, utils_1.parseUrl)(referer, 'host');
|
|
117
|
+
const domainList = refererWhiteList.concat(request.host);
|
|
118
|
+
if (!host || !(0, utils_1.isSafeDomain)(host, domainList)) {
|
|
119
|
+
throw new error_1.CSRFError('invalid csrf referer');
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
ensureCsrfSecret(context, request, response, rotate) {
|
|
123
|
+
var _a;
|
|
124
|
+
const tokenSecret = this.getCSRFSecret(context);
|
|
125
|
+
if (tokenSecret && !rotate) {
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
const secret = tokens.secretSync();
|
|
129
|
+
context[NEW_CSRF_SECRET] = secret;
|
|
130
|
+
const { useSession, sessionName, cookieDomain } = this.security.csrf;
|
|
131
|
+
let { cookieName } = this.security.csrf;
|
|
132
|
+
if (useSession) {
|
|
133
|
+
context.session[sessionName] = secret;
|
|
134
|
+
}
|
|
135
|
+
else {
|
|
136
|
+
const cookieOpts = {
|
|
137
|
+
domain: cookieDomain && cookieDomain(request),
|
|
138
|
+
signed: false,
|
|
139
|
+
httpOnly: false,
|
|
140
|
+
overwrite: true,
|
|
141
|
+
};
|
|
142
|
+
// cookieName support array. so we can change csrf cookie name smoothly
|
|
143
|
+
if (!Array.isArray(cookieName)) {
|
|
144
|
+
cookieName = [cookieName];
|
|
145
|
+
}
|
|
146
|
+
for (const name of cookieName) {
|
|
147
|
+
if ((_a = response.cookies) === null || _a === void 0 ? void 0 : _a.set) {
|
|
148
|
+
response.cookies.set(name, secret, cookieOpts);
|
|
149
|
+
}
|
|
150
|
+
else {
|
|
151
|
+
response.cookie(name, secret, cookieOpts);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
};
|
|
157
|
+
CSRFMiddleware = __decorate([
|
|
158
|
+
(0, decorator_1.Middleware)()
|
|
159
|
+
], CSRFMiddleware);
|
|
160
|
+
exports.CSRFMiddleware = CSRFMiddleware;
|
|
161
|
+
//# sourceMappingURL=csrf.js.map
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.HSTSMiddleware = void 0;
|
|
10
|
+
const decorator_1 = require("@midwayjs/decorator");
|
|
11
|
+
const base_1 = require("./base");
|
|
12
|
+
let HSTSMiddleware = class HSTSMiddleware extends base_1.BaseMiddleware {
|
|
13
|
+
async compatibleMiddleware(context, req, res, next) {
|
|
14
|
+
const result = await next();
|
|
15
|
+
let val = 'max-age=' + this.security.hsts.maxAge;
|
|
16
|
+
if (this.security.hsts.includeSubdomains) {
|
|
17
|
+
val += '; includeSubdomains';
|
|
18
|
+
}
|
|
19
|
+
res.set('strict-transport-security', val);
|
|
20
|
+
return result;
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
HSTSMiddleware = __decorate([
|
|
24
|
+
(0, decorator_1.Middleware)()
|
|
25
|
+
], HSTSMiddleware);
|
|
26
|
+
exports.HSTSMiddleware = HSTSMiddleware;
|
|
27
|
+
//# sourceMappingURL=hsts.js.map
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.NoOpenMiddleware = void 0;
|
|
10
|
+
const decorator_1 = require("@midwayjs/decorator");
|
|
11
|
+
const base_1 = require("./base");
|
|
12
|
+
let NoOpenMiddleware = class NoOpenMiddleware extends base_1.BaseMiddleware {
|
|
13
|
+
async compatibleMiddleware(context, req, res, next) {
|
|
14
|
+
const result = await next();
|
|
15
|
+
res.set('x-download-options', 'noopen');
|
|
16
|
+
return result;
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
NoOpenMiddleware = __decorate([
|
|
20
|
+
(0, decorator_1.Middleware)()
|
|
21
|
+
], NoOpenMiddleware);
|
|
22
|
+
exports.NoOpenMiddleware = NoOpenMiddleware;
|
|
23
|
+
//# sourceMappingURL=noopen.js.map
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.NoSniffMiddleware = void 0;
|
|
10
|
+
const decorator_1 = require("@midwayjs/decorator");
|
|
11
|
+
const base_1 = require("./base");
|
|
12
|
+
let NoSniffMiddleware = class NoSniffMiddleware extends base_1.BaseMiddleware {
|
|
13
|
+
async compatibleMiddleware(context, req, res, next) {
|
|
14
|
+
const result = await next();
|
|
15
|
+
if (res.status >= 300 && res.status <= 308) {
|
|
16
|
+
return result;
|
|
17
|
+
}
|
|
18
|
+
res.set('x-content-type-options', 'nosniff');
|
|
19
|
+
return result;
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
NoSniffMiddleware = __decorate([
|
|
23
|
+
(0, decorator_1.Middleware)()
|
|
24
|
+
], NoSniffMiddleware);
|
|
25
|
+
exports.NoSniffMiddleware = NoSniffMiddleware;
|
|
26
|
+
//# sourceMappingURL=nosniff.js.map
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.XFrameMiddleware = void 0;
|
|
10
|
+
const decorator_1 = require("@midwayjs/decorator");
|
|
11
|
+
const base_1 = require("./base");
|
|
12
|
+
let XFrameMiddleware = class XFrameMiddleware extends base_1.BaseMiddleware {
|
|
13
|
+
async compatibleMiddleware(context, req, res, next) {
|
|
14
|
+
var _a;
|
|
15
|
+
const result = await next();
|
|
16
|
+
const value = ((_a = this.security.xframe) === null || _a === void 0 ? void 0 : _a.value) || 'SAMEORIGIN';
|
|
17
|
+
res.set('x-frame-options', value);
|
|
18
|
+
return result;
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
XFrameMiddleware = __decorate([
|
|
22
|
+
(0, decorator_1.Middleware)()
|
|
23
|
+
], XFrameMiddleware);
|
|
24
|
+
exports.XFrameMiddleware = XFrameMiddleware;
|
|
25
|
+
//# sourceMappingURL=xframe.js.map
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.XSSProtectionMiddleware = void 0;
|
|
10
|
+
const decorator_1 = require("@midwayjs/decorator");
|
|
11
|
+
const base_1 = require("./base");
|
|
12
|
+
let XSSProtectionMiddleware = class XSSProtectionMiddleware extends base_1.BaseMiddleware {
|
|
13
|
+
async compatibleMiddleware(context, req, res, next) {
|
|
14
|
+
const result = await next();
|
|
15
|
+
res.set('x-xss-protection', this.security.xssProtection.value);
|
|
16
|
+
return result;
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
XSSProtectionMiddleware = __decorate([
|
|
20
|
+
(0, decorator_1.Middleware)()
|
|
21
|
+
], XSSProtectionMiddleware);
|
|
22
|
+
exports.XSSProtectionMiddleware = XSSProtectionMiddleware;
|
|
23
|
+
//# sourceMappingURL=xssProtection.js.map
|
package/dist/utils.d.ts
ADDED
package/dist/utils.js
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.isSafeDomain = exports.parseUrl = void 0;
|
|
4
|
+
const url_1 = require("url");
|
|
5
|
+
const pm = require("picomatch");
|
|
6
|
+
const parseUrl = (url, prop) => {
|
|
7
|
+
try {
|
|
8
|
+
const parsed = new url_1.URL(url);
|
|
9
|
+
return prop ? parsed[prop] : parsed;
|
|
10
|
+
}
|
|
11
|
+
catch (err) {
|
|
12
|
+
return null;
|
|
13
|
+
}
|
|
14
|
+
};
|
|
15
|
+
exports.parseUrl = parseUrl;
|
|
16
|
+
const isSafeDomain = (domain, whiteList) => {
|
|
17
|
+
if (typeof domain !== 'string') {
|
|
18
|
+
return false;
|
|
19
|
+
}
|
|
20
|
+
domain = domain.toLowerCase();
|
|
21
|
+
const hostname = '.' + domain;
|
|
22
|
+
return whiteList.some(rule => {
|
|
23
|
+
// Check whether we've got '*' as a wild character symbol()
|
|
24
|
+
if (rule.includes('*')) {
|
|
25
|
+
return pm(rule)(domain);
|
|
26
|
+
}
|
|
27
|
+
if (domain === rule) {
|
|
28
|
+
return true;
|
|
29
|
+
}
|
|
30
|
+
if (!/^\./.test(rule)) {
|
|
31
|
+
rule = `.${rule}`;
|
|
32
|
+
}
|
|
33
|
+
return hostname.endsWith(rule);
|
|
34
|
+
});
|
|
35
|
+
};
|
|
36
|
+
exports.isSafeDomain = isSafeDomain;
|
|
37
|
+
//# sourceMappingURL=utils.js.map
|
package/index.d.ts
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@midwayjs/security",
|
|
3
|
+
"version": "3.0.0-beta.16",
|
|
4
|
+
"description": "Midway Security Component",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"typings": "index.d.ts",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"build": "tsc",
|
|
9
|
+
"test": "node --require=ts-node/register ../../node_modules/.bin/jest --runInBand",
|
|
10
|
+
"cov": "node --require=ts-node/register ../../node_modules/.bin/jest --runInBand --coverage --forceExit",
|
|
11
|
+
"ci": "npm run test"
|
|
12
|
+
},
|
|
13
|
+
"keywords": [],
|
|
14
|
+
"author": "",
|
|
15
|
+
"files": [
|
|
16
|
+
"dist/**/*.js",
|
|
17
|
+
"dist/**/*.d.ts",
|
|
18
|
+
"index.d.ts"
|
|
19
|
+
],
|
|
20
|
+
"engines": {
|
|
21
|
+
"node": ">=12"
|
|
22
|
+
},
|
|
23
|
+
"license": "MIT",
|
|
24
|
+
"dependencies": {
|
|
25
|
+
"csrf": "3.1.0",
|
|
26
|
+
"nanoid": "3.2.0",
|
|
27
|
+
"picomatch": "2.3.1",
|
|
28
|
+
"platform": "1.3.6"
|
|
29
|
+
},
|
|
30
|
+
"devDependencies": {
|
|
31
|
+
"@midwayjs/core": "^3.0.0-beta.16",
|
|
32
|
+
"@midwayjs/decorator": "^3.0.0-beta.16",
|
|
33
|
+
"@midwayjs/express": "^3.0.0-beta.16",
|
|
34
|
+
"@midwayjs/faas": "^3.0.0-beta.16",
|
|
35
|
+
"@midwayjs/koa": "^3.0.0-beta.16",
|
|
36
|
+
"@midwayjs/mock": "^3.0.0-beta.16",
|
|
37
|
+
"@midwayjs/serverless-app": "^3.0.0-beta.16",
|
|
38
|
+
"@midwayjs/web": "^3.0.0-beta.16"
|
|
39
|
+
}
|
|
40
|
+
}
|