Showing
2 changed files
with
62 additions
and
57 deletions
| ... | @@ -3,72 +3,76 @@ | ... | @@ -3,72 +3,76 @@ |
| 3 | */ | 3 | */ |
| 4 | 4 | ||
| 5 | const Authenticator = function (secret, options) { | 5 | const Authenticator = function (secret, options) { |
| 6 | - if (!(this instanceof Authenticator)) { | 6 | + if (!(this instanceof Authenticator)) { |
| 7 | - return new Authenticator(secret, options) | 7 | + return new Authenticator(secret, options) |
| 8 | - } | 8 | + } |
| 9 | 9 | ||
| 10 | - const _ = require('lodash'), | 10 | + const _ = require('lodash'), |
| 11 | - speakeasy = require('speakeasy'), | 11 | + speakeasy = require('speakeasy'), |
| 12 | - qr = require('qr-image'); | 12 | + qr = require('qr-image'); |
| 13 | 13 | ||
| 14 | - options = options || {}; | 14 | + options = options || {}; |
| 15 | 15 | ||
| 16 | - this.secret = secret; | 16 | + this.secret = secret; |
| 17 | 17 | ||
| 18 | - const TOTP_OPTIONS = this.totp_options = { | 18 | + const TOTP_OPTIONS = this.totp_options = { |
| 19 | - secret: this.secret, | 19 | + secret: this.secret, |
| 20 | - encoding: options.encoding || 'base32', | 20 | + encoding: options.encoding || 'base32', |
| 21 | - step: options.step || 30, | 21 | + step: options.step || 30, |
| 22 | - algorithm: options.algorithm || 'sha512' | 22 | + algorithm: options.algorithm || 'sha512' |
| 23 | - }; | 23 | + }; |
| 24 | 24 | ||
| 25 | 25 | ||
| 26 | - /** | 26 | + /** |
| 27 | - * 验证token有效性 | 27 | + * 验证token有效性 |
| 28 | - * @param token | 28 | + * @param token |
| 29 | - */ | 29 | + */ |
| 30 | - this.verify = function(token) { | 30 | + this.verify = function (token) { |
| 31 | - return speakeasy.totp.verify(_.merge({}, TOTP_OPTIONS, {token: token})); | 31 | + return speakeasy.totp.verify(_.merge({}, TOTP_OPTIONS, {token: token})); |
| 32 | - }; | 32 | + }; |
| 33 | 33 | ||
| 34 | - /** | 34 | + /** |
| 35 | - * 在options.window的范围内验证token的有效性 | 35 | + * 在options.window的范围内验证token的有效性 |
| 36 | - * @param token | 36 | + * @param token |
| 37 | - * @param window | 37 | + * @param window |
| 38 | - */ | 38 | + */ |
| 39 | - this.verifyDelta = function(token, window) { | 39 | + this.verifyDelta = function (token, window) { |
| 40 | - return speakeasy.totp.verifyDelta(_.merge({}, TOTP_OPTIONS, {token: token, window: window})); | 40 | + return speakeasy.totp.verifyDelta(_.merge({}, TOTP_OPTIONS, {token: token, window: window})); |
| 41 | - }; | 41 | + }; |
| 42 | 42 | ||
| 43 | - /** | 43 | + /** |
| 44 | - * 获取授权定义地址 | 44 | + * 获取授权定义地址 |
| 45 | - * @param label | 45 | + * @param label |
| 46 | - * @param issuer | 46 | + * @param issuer |
| 47 | - * @return {string} | 47 | + * @return {string} |
| 48 | - */ | 48 | + */ |
| 49 | - this.getOtpAuthURL = function (label, issuer) { | 49 | + this.getOtpAuthURL = function (label, issuer) { |
| 50 | - return speakeasy.otpauthURL(_.merge({}, TOTP_OPTIONS, {label: title, issuer: issuer})); | 50 | + return speakeasy.otpauthURL(_.merge({}, TOTP_OPTIONS, {label: title, issuer: issuer})); |
| 51 | - }; | 51 | + }; |
| 52 | 52 | ||
| 53 | - /** | 53 | + /** |
| 54 | - * 生成svg的QR图片内容 | 54 | + * 生成svg的QR图片内容 |
| 55 | - * @param label | 55 | + * @param label |
| 56 | - * @param issuer | 56 | + * @param issuer |
| 57 | - * @return {*} | 57 | + * @return {{content: *, url: string}} |
| 58 | - */ | 58 | + */ |
| 59 | - this.getQR = function(label, issuer) { | 59 | + this.getQR = function (label, issuer) { |
| 60 | - return qr.imageSync(this.getOtpAuthURL(label, issuer), { type: 'svg' }); | 60 | + let url = this.getOtpAuthURL(label, issuer); |
| 61 | - }; | 61 | + return { |
| 62 | + content: qr.imageSync(url, { type: 'svg' }), | ||
| 63 | + url: url | ||
| 64 | + }; | ||
| 65 | + }; | ||
| 62 | 66 | ||
| 63 | - /** | 67 | + /** |
| 64 | - * 生成新的token | 68 | + * 生成新的token |
| 65 | - * @return {String} | 69 | + * @return {String} |
| 66 | - */ | 70 | + */ |
| 67 | - this.totp = function () { | 71 | + this.totp = function () { |
| 68 | - return speakeasy.totp(_.merge({}, TOTP_OPTIONS)); | 72 | + return speakeasy.totp(_.merge({}, TOTP_OPTIONS)); |
| 69 | - }; | 73 | + }; |
| 70 | 74 | ||
| 71 | - return this; | 75 | + return this; |
| 72 | }; | 76 | }; |
| 73 | 77 | ||
| 74 | module.exports = Authenticator; | 78 | module.exports = Authenticator; |
| ... | \ No newline at end of file | ... | \ No newline at end of file | ... | ... |
| ... | @@ -41,11 +41,12 @@ fs.ensureDir(img_path, function (err, added_root) { | ... | @@ -41,11 +41,12 @@ fs.ensureDir(img_path, function (err, added_root) { |
| 41 | } | 41 | } |
| 42 | added_root && console.log(chalk.green(img_path + ' is created')); | 42 | added_root && console.log(chalk.green(img_path + ' is created')); |
| 43 | 43 | ||
| 44 | + let qr = authenticator.getQR('totp@gitlab.kmlab.com', '通行密钥'); | ||
| 44 | let fd = fs.openSync(qr, 'w'); | 45 | let fd = fs.openSync(qr, 'w'); |
| 45 | - fs.writeSync(fd, authenticator.getQR('totp@gitlab.kmlab.com', '通行密钥')); | 46 | + fs.writeSync(fd, qr.content); |
| 46 | fs.closeSync(fd); | 47 | fs.closeSync(fd); |
| 47 | 48 | ||
| 48 | - console.log(chalk.green('密钥字符串'), chalk.yellow(authenticator.getOtpAuthURL('totp@gitlab.kmlab.com', '通行密钥'))) | 49 | + console.log(chalk.green('密钥字符串'), chalk.yellow(qr.url)) |
| 49 | }); | 50 | }); |
| 50 | 51 | ||
| 51 | console.log('QR SVG output is', img_path, qr); | 52 | console.log('QR SVG output is', img_path, qr); |
| ... | \ No newline at end of file | ... | \ No newline at end of file | ... | ... |
-
Please register or login to post a comment