diff --git a/config.js b/config.js index f3fb138..863d799 100644 --- a/config.js +++ b/config.js @@ -10,6 +10,10 @@ const application = { password: 'root', // 登录密码 host: '127.0.0.1', port: 3000, + sslEnabled: true, // 是否启用 https + sslCert: 'ssl/server.crt', // 证书 + sslKey: 'ssl/server.key', // 私钥 + sslKeyPassphrase: '', // 私钥密码,可选 } const session = { diff --git a/readme.md b/readme.md index 341b51d..48972ef 100644 --- a/readme.md +++ b/readme.md @@ -38,10 +38,14 @@ fava main.bean --host 127.0.0.1 --prefix /fava } const application = { - username: 'root', // 设置用户名 - password: 'root', // 设置登录密码 + username: 'root', // 登录用户名 + password: 'root', // 登录密码 host: '127.0.0.1', port: 3000, + sslEnabled: true, // 是否启用 https + sslCert: 'ssl/server.crt', // 证书 + sslKey: 'ssl/server.key', // 私钥 + sslKeyPassphrase: '', // 私钥密码,可选 } ``` @@ -50,6 +54,7 @@ fava main.bean --host 127.0.0.1 --prefix /fava ```sh npm start ``` +启动成功后打印:application is running on https://127.0.0.1:3000 ## 扩展 beancount-auth 默认会将 `/src/static/inject.js` 注入到 Fava 的 HTML,如果你需要扩展 Fava 的 UI,只要在这个文件里加入你的逻辑即可。 diff --git a/src/index.js b/src/index.js index 31d9013..63a790d 100644 --- a/src/index.js +++ b/src/index.js @@ -1,4 +1,7 @@ const path = require('path') +const fs = require('fs') +const https = require('https') +const http = require('http') const Koa = require('koa') const session = require('koa-session') const views = require('koa-views') @@ -54,6 +57,18 @@ app.use(bodyParser()) app.use(router.routes()).use(router.allowedMethods()) const {port, host} = applicationConf -app.listen(port, host, () => { - console.log(`application is running on ${host}:${port}`) -}) + +if (applicationConf.sslEnabled) { + const options = { + key: fs.readFileSync(path.resolve(process.cwd(), applicationConf.sslKey)), + cert: fs.readFileSync(path.resolve(process.cwd(), applicationConf.sslCert)), + passphrase: applicationConf.sslKeyPassphrase, + } + https.createServer(options, app.callback()).listen(port, host, () => { + console.log(`application is running on https://${host}:${port}`) + }) +} else { + http.createServer(app.callback()).listen(port, host, () => { + console.log(`application is running on http://${host}:${port}`) + }) +} diff --git a/src/middleware/inject.js b/src/middleware/inject.js index 2f7ef27..95e3d53 100644 --- a/src/middleware/inject.js +++ b/src/middleware/inject.js @@ -1,4 +1,5 @@ const http = require('http') +const url = require('url') const {injectContent} = require('../../config').beancount module.exports = (request, response, options) => { @@ -21,6 +22,13 @@ module.exports = (request, response, options) => { resolve() }) } else { + if (pResonse.statusCode === 302 || pResonse.statusCode === 301) { + response.setHeader( + 'location', + convertLocation(response.getHeader('location')), + ) + } + response.setHeader('X-Forwarded-Proto', 'https') pResonse.pipe(response) pResonse.on('end', resolve) } @@ -45,3 +53,11 @@ function contentIsHTML(resonseIncoming) { contentType.indexOf('text/html') === 0 ) } + +// 去除 302 location 中的协议,fava 重定向会默认使用 http 协议 +function convertLocation(location) { + if (!location) { + return location + } + return location.replace(/^https?\:/i, '') +} diff --git a/src/view/login.ejs b/src/view/login.ejs index bf89e49..66c9bdc 100644 --- a/src/view/login.ejs +++ b/src/view/login.ejs @@ -38,8 +38,9 @@ .then(res => { if (res.data && res.data.code === 0) { console.log('登录成功') - const redirect = new URL(location.href).searchParams.get('redirect') || '/' - location.href = redirect + const url = new URL(location.href) + url.pathname = url.searchParams.get('redirect') || '/' + location.href = url.href } else { alert(res.data.message) } diff --git a/ssl/server.crt b/ssl/server.crt new file mode 100644 index 0000000..a59ffbb --- /dev/null +++ b/ssl/server.crt @@ -0,0 +1,20 @@ +-----BEGIN CERTIFICATE----- +MIIDWzCCAkMCFDj/HcB7XNxxMbBt9hq3BtKP/AwgMA0GCSqGSIb3DQEBCwUAMGox +CzAJBgNVBAYTAkNOMRIwEAYDVQQIDAlHdWFuZ0RvbmcxDjAMBgNVBAcMBVNoemVu +MRAwDgYDVQQKDAdUZW5jZW50MQwwCgYDVQQLDANURUQxFzAVBgNVBAMMDjEyNy4w +LjAuMTozMDAwMB4XDTIwMTEyNjA1MTkxNVoXDTIxMTEyNjA1MTkxNVowajELMAkG +A1UEBhMCQ04xEjAQBgNVBAgMCUd1YW5nRG9uZzEOMAwGA1UEBwwFU2h6ZW4xEDAO +BgNVBAoMB1RlbmNlbnQxDDAKBgNVBAsMA1RFRDEXMBUGA1UEAwwOMTI3LjAuMC4x +OjMwMDAwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDG+hJBeXApbXi3 +NA6vhvYUF6b+Qz+x5Ydx4cN6bio9u6ms5i7YSg+6CuA204hiusSTA7sfD1vU0XHy +Rpjd4lcNN/st0ZknhCmZHU/UHo6UMWplXwj258Dq+b2iWJbwX4iFBS/cKtWBLMuR +788B5j83zW7SAPYY777u6/51ye3DC6HoeEdKewpJ0yWYGSVI6FG6EUXEmcnxA94p +LyFBMj//B1fCkWmqssXk0BwElY6GbLo3KFUhEDbDoab1MJXKLS2KDzkkV1hUpZGe +s9izpGQx0kCX2zrQ7cbRbWw5yWG0MGMiWhYHFRvT0L9fkZ2L7bA06sNiIZa6Lnjm +Yq4Cu0LFAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAAG+EUKuCh2ivs7m+pRqbnRz +Om+1SDrlKe4iIRksCucMYTrsQt6UOr692UVklR7q4vLNuKWjZlTRqYXnbiR/HIWW +J5cyhFAlOaIauYYLkTjnelMBGMNyn0CM/PuT92O/g+NvxWlJH4K0qXRqFc39lh9A +2QQpOLugKCkMi4D8o+1Bhz8Hnz8HzPhav3e+ut99OWwOaJt0bLmFfDcHWQz4nag2 +2GYp6MBMKSg0M/T99AtrI1orf4GRdQQ0Ib8yitfUw0IKMvKU4B3RT5EkF6GcI+51 +DuzMQiVW/4I7u8TLZwW+pBZsjJp2cU0FsNgZfAzk4IzFdivv3sPGSSF3Up3WSck= +-----END CERTIFICATE----- diff --git a/ssl/server.key b/ssl/server.key new file mode 100644 index 0000000..ba7590b --- /dev/null +++ b/ssl/server.key @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEAxvoSQXlwKW14tzQOr4b2FBem/kM/seWHceHDem4qPbuprOYu +2EoPugrgNtOIYrrEkwO7Hw9b1NFx8kaY3eJXDTf7LdGZJ4QpmR1P1B6OlDFqZV8I +9ufA6vm9oliW8F+IhQUv3CrVgSzLke/PAeY/N81u0gD2GO++7uv+dcntwwuh6HhH +SnsKSdMlmBklSOhRuhFFxJnJ8QPeKS8hQTI//wdXwpFpqrLF5NAcBJWOhmy6NyhV +IRA2w6Gm9TCVyi0tig85JFdYVKWRnrPYs6RkMdJAl9s60O3G0W1sOclhtDBjIloW +BxUb09C/X5Gdi+2wNOrDYiGWui545mKuArtCxQIDAQABAoIBAGRlCs8EYeZVOOJf +HsXLt9+9a2HBNqMg5607NzFP4npRdLQrVBmHjNXW5Phk1NzT1ZlD+acbTb9cijyv +CDR0Hm4p/89HgRoiIgcCdiPV4yS8pi1NvS0vE/S7W8ZNIqNX4H8VdeeFqUJLAs+4 +it8veFhEjBTjrUg5t0G/yx1NbGzLTvm4FiWZxFzsGV20DrUu/CUAxM6/wvzfjb7x +IKt/qRqCBuQy/oRs7UIJoExNTkHDs7t3Y0/e4O8Z3SLUI+/UoqSJt1/Eamhhq83X +5qLjGkkxJgcZH5chdBPNY9723bTWKWySmXFA49GSLr8Eka/d4YeopSbdNJggnWYk +yOiUooECgYEA5HGqcrvJEb3VOiwQBVQ1mzOhw0fU0Vgp+TfU9kOvFrC0JC7og3nN +p0ex0sIfMugczwYGORS6k5q0KNAcIKnr6OzJy/lwCiRROhSOekdy8y+5zZJAthPt +JN6GCMVk4uHmiJMVSfDSlZLsntco3aTsM8SI5cer7HnSmczMqtSyZOECgYEA3vp2 +KZyjkkGO3kEwXXiFZbk1FViuInfGE/5z0dh+9+VoBiNZekgf98fmlLZab7k1LKvX +O2aUctPelnzU7AKbYSw2zYDm1u1StPzUEWCXEUUk9Vyk5R9Y0Yk7TBo7oPEt9TOQ +9iRRBj0BM/qVaihth0QDKTTWVYWdrFalBAdSNmUCgYAAuoARp5mnjdRtQBC5A6C8 +IvkEF2mNVVuk6NGsC2E2kE+ywdeJ+8x1GRxvEKFq1ySoYFuKuQ8zQ04Jx0gfrosL +Dh5CoUQDNERyC/i8WRf7wI42Ip5ENmIOOQtyYbbFpnTGwLlTqAnz4ikRBJyjwE/k +hl7tZKqesXDDfsy0SsNa4QKBgQCLOSd+Y+dd8sEZ1Oo18oKYOUQDyBMyQkbTRRVb ++SmN7xc8feXojBApzg8S26ksCSBCfCkvVaVq7Q8WN2ta0WXjDpBJUCrSF+yERTjE +gOLSTbH94ZKz3Ra//kegBOEmZHCloUTp61ML6htOMTAJ0KRSyQyQNgV98Ke6a38t +PMUAYQKBgQDZ89faFDOwye4ptNBzzRYdPAuosdWy3cRJlFUC3ybp77LaUxpbMKqD +E5o0iE8RicYvPPBLggL1q0FWM9IdgpQ7X5e7HMpLFwhbifPRs/XLuRQ8adke/q+I +AloHrgzah2oS+/BNNyddA6r1ks5HDCIkUX3DaWE6n0bOAAU8YXXvUQ== +-----END RSA PRIVATE KEY-----