UNPKG

@mamba-le/auth

Version:
508 lines (437 loc) 12.8 kB
/** * @description 认证模块 * @version 0.3.7 * @author lengyingxin <lengyingxin8966@gmail.com> (https://github.com/LengYXin) */ import _isEqual from 'lodash/isEqual'; import _assign from 'lodash/assign'; import _map from 'lodash/map'; import _compact from 'lodash/compact'; import _head from 'lodash/head'; import _pick from 'lodash/pick'; import _merge from 'lodash/merge'; import _concat from 'lodash/concat'; import _eq from 'lodash/eq'; import { __awaiter, __generator, __decorate } from 'tslib'; import dayjs from 'dayjs'; import jsCookie from 'js-cookie'; import jwtDecode from 'jwt-decode'; import { BindAll } from 'lodash-decorators'; import { observable, computed, action } from 'mobx'; import { persist } from 'mobx-persist'; import { Subject, lastValueFrom } from 'rxjs'; import { AuthOptions } from './options'; var AuthController = /** @class */ function () { function AuthController(options) { if (options === void 0) { options = {}; } /** * 持久化初始化完成 Subject * @type {Promise<any>} * @memberof ControllerUser */ this.HydrateSubject = new Subject(); this.options = { StorageKey: 'mamba-auth', CookieKey: ['mamba-auth'], CookieDomain: ['.lenovo.com.cn', '.lenovo.com'], TokenType: 'JWT' }; /** * AccessToken * @protected * @memberof AuthController */ this._AccessToken = undefined; /** * 最后一次更新 值 HydrateisStopped 未完成前 存储 用于对比变化 default 表示默认无值 * @protected * @memberof AuthController */ this.lastValue = 'default'; this.resetConfig(options); this.createHydrate(); } Object.defineProperty(AuthController.prototype, "HydrateAsync", { /** * 持久化初始化完成 Promise * @type {Promise<any>} * @memberof ControllerUser */ get: function get() { return lastValueFrom(this.HydrateSubject, { defaultValue: undefined }); }, enumerable: false, configurable: true }); Object.defineProperty(AuthController.prototype, "HydrateisStopped", { /** * 异步 HydrateSubject 已经完成 * @readonly * @memberof PortalAuthController */ get: function get() { return this.HydrateSubject.isStopped; }, enumerable: false, configurable: true }); Object.defineProperty(AuthController.prototype, "JsCookie", { get: function get() { return jsCookie; }, enumerable: false, configurable: true }); Object.defineProperty(AuthController.prototype, "JWTDecode", { get: function get() { return jwtDecode; }, enumerable: false, configurable: true }); Object.defineProperty(AuthController.prototype, "IsJWT", { get: function get() { return _eq(this.options.TokenType, 'JWT'); }, enumerable: false, configurable: true }); Object.defineProperty(AuthController.prototype, "StorageKey", { /** * 存储 key * @readonly * @memberof AuthController */ get: function get() { return "_Auth_" + this.options.StorageKey; }, enumerable: false, configurable: true }); Object.defineProperty(AuthController.prototype, "CookieKey", { /** * CookieKey * @readonly * @memberof AuthController */ get: function get() { if (AuthOptions.browser) { return _concat([], this.options.CookieKey); } return []; }, enumerable: false, configurable: true }); Object.defineProperty(AuthController.prototype, "CookieDomain", { /** * Cookie 站点信息 * @readonly * @memberof AuthController */ get: function get() { if (AuthOptions.browser) { return _concat(["." + window.location.hostname], this.options.CookieDomain); } return []; }, enumerable: false, configurable: true }); Object.defineProperty(AuthController.prototype, "AllCookieKeys", { /** * 所有的 Cookie * @readonly * @memberof AuthController */ get: function get() { if (AuthOptions.browser) { try { var aKeys = document.cookie.replace(/((?:^|\s*;)[^\=]+)(?=;|$)|^\s*|\s*(?:\=[^;]*)?(?:\1|$)/g, "").split(/\s*(?:\=[^;]*)?;\s*/); for (var nIdx = 0; nIdx < aKeys.length; nIdx++) { aKeys[nIdx] = decodeURIComponent(aKeys[nIdx]); } return aKeys; } catch (error) { return []; } } }, enumerable: false, configurable: true }); /** * 重置配置 * @param options */ AuthController.prototype.resetConfig = function (options) { if (options === void 0) { options = {}; } try { AuthOptions.writeCheck(); _merge(this.options, _pick(options, ['StorageKey', 'CookieKey', 'CookieDomain'])); } catch (error) { AuthOptions.log('error', error); } }; Object.defineProperty(AuthController.prototype, "AccessToken", { /** * 提供外部访问的 AccessToken * @readonly * @memberof AuthController */ get: function get() { var AccessToken = this.getAccessToken(); var Decoded = this.getDecoded(AccessToken); if (Decoded && Decoded.overdue) { AuthOptions.log('Warning 已过期 不返回', Decoded, this); return undefined; } return AccessToken; }, enumerable: false, configurable: true }); Object.defineProperty(AuthController.prototype, "JwtDecoded", { /** * 解析后的 JWT * @readonly * @type {JWTDecoded} * @memberof AuthController */ get: function get() { return this.getDecoded(); }, enumerable: false, configurable: true }); Object.defineProperty(AuthController.prototype, "CookieAccessToken", { /** * Cookie 中存储的值 * @readonly * @private * @memberof AuthController */ get: function get() { // 微信小程序中不使用 cookie if (AuthOptions.isWeappBowser) { return undefined; } if (AuthOptions.browser) { try { return _head(_compact(_map(this.CookieKey, function (key) { return jsCookie.get(key); }))); } catch (error) { AuthOptions.log('error', this, error); return undefined; } } }, enumerable: false, configurable: true }); /** * 获取 JWT 解析后数据 * @returns */ AuthController.prototype.getDecoded = function (AccessToken) { if (AccessToken === void 0) { AccessToken = this.getAccessToken(); } try { if (!AccessToken || !this.IsJWT) { return {}; } var Decode = jwtDecode(AccessToken); return _assign(Decode, { expFormat: dayjs(Decode.exp * 1000).format('YYYY-MM-DD HH:mm:ss'), iatFormat: dayjs(Decode.iat * 1000).format('YYYY-MM-DD HH:mm:ss'), // 是否过期 overdue: dayjs(Decode.exp * 1000).isBefore(dayjs()) }); } catch (error) { // AuthOptions.log('error', 'Decoded', this, error) return { overdue: true }; } }; /** * 获取 AccessToken * @returns */ AuthController.prototype.getAccessToken = function () { return _head(_compact([this.CookieAccessToken, this._AccessToken])); }; /** * 保存 Token * @param _AccessToken * @returns */ AuthController.prototype.onSaveAccessToken = function (_AccessToken, setCookie) { var _this = this; if (_AccessToken === void 0) { _AccessToken = undefined; } if (setCookie === void 0) { setCookie = false; } try { AuthOptions.writeCheck(); AuthOptions.trace('Save AccessToken', _AccessToken, setCookie); if (_AccessToken && this.IsJWT) { var Decoded = this.getDecoded(_AccessToken); AuthOptions.log('AccessToken Decoded', Decoded); // if (!Decoded.aud) { // throw 'AccessToken 非法' // } if (Decoded.overdue) { throw 'AccessToken 已过期'; } } if (_AccessToken && _eq(this.getAccessToken(), _AccessToken)) { throw 'AccessToken 已存在 【 Cookie 存在将不在写入 】'; } if (!this.HydrateisStopped) { this.lastValue = _AccessToken; } this._AccessToken = _AccessToken; if (setCookie && AuthOptions.browser) { _map(this.CookieDomain, function (domain) { _map(_this.CookieKey, function (key) { AuthOptions.log('jsCookie set', key, _AccessToken, domain); jsCookie.set(key, _AccessToken); jsCookie.set(key, _AccessToken, { domain: domain }); }); }); } } catch (error) { AuthOptions.log('AccessToken Error', error, this); } }; /** * 清理所有的登录信息 * @return {*} * @memberof AuthController */ AuthController.prototype.onClear = function () { var _this = this; try { AuthOptions.writeCheck(); this._AccessToken = undefined; if (!this.HydrateisStopped) { this.lastValue = undefined; } this.onRemove(); _map(this.CookieDomain, function (domain) { return _this.onRemove({ domain: domain }); }); // return AuthOptions.LocalForage.clear(); } catch (error) { AuthOptions.log('error', error); } }; AuthController.prototype.onRemove = function (options) { if (AuthOptions.browser) { try { AuthOptions.writeCheck(); _map(this.CookieKey, function (key) { return jsCookie.remove(key, options); }); _map(this.AllCookieKeys, function (key) { return jsCookie.remove(key, options); }); } catch (error) { AuthOptions.log('error', error); } } }; /** * 创建持久化存储 * @memberof BaseModel */ AuthController.prototype.createHydrate = function () { return __awaiter(this, void 0, void 0, function () { var Hydrate, Decoded, error_1; var _this = this; return __generator(this, function (_a) { switch (_a.label) { case 0: _a.trys.push([0, 2,, 3]); if (!AuthOptions.browser) { throw '非浏览器环境 不进行 Hydrate'; } // 微信小程序中不使用 cookie if (AuthOptions.isWeappBowser) { this.onRemove(); _map(this.CookieDomain, function (domain) { return _this.onRemove({ domain: domain }); }); } Hydrate = AuthOptions.createHydrate(); persist({ _AccessToken: true })(this); AuthOptions.log("Storage " + this.StorageKey, this); return [4 /*yield*/ , Hydrate(this.StorageKey, this)]; case 1: _a.sent(); if (!_eq(this.lastValue, 'default') && !_isEqual(this._AccessToken, this.lastValue)) { AuthOptions.log("Storage " + this.StorageKey + " LastValue", this, this.lastValue); this.onSaveAccessToken(this.lastValue); } // jwt 校验正确性 if (this.IsJWT) { Decoded = this.getDecoded(); // 过期清理 或者无效 if (Decoded.overdue) { this.onClear(); } } // const CookieAccessToken = lodash.find(this.CookieAccessToken, lodash.identity); // if (!this._AccessToken && CookieAccessToken) { // this.onSaveAccessToken(CookieAccessToken) // } this.HydrateSubject.next(true); this.HydrateSubject.complete(); return [3 /*break*/ , 3]; case 2: error_1 = _a.sent(); if (AuthOptions.browser) { AuthOptions.log('error', error_1); } this.HydrateSubject.next(false); this.HydrateSubject.complete(); return [3 /*break*/ , 3]; case 3: return [2 /*return*/ ]; } }); }); }; __decorate([observable], AuthController.prototype, "_AccessToken", void 0); __decorate([computed], AuthController.prototype, "AccessToken", null); __decorate([computed], AuthController.prototype, "JwtDecoded", null); __decorate([action], AuthController.prototype, "onSaveAccessToken", null); __decorate([action], AuthController.prototype, "onClear", null); AuthController = __decorate([BindAll()], AuthController); return AuthController; }(); export { AuthController }; //# sourceMappingURL=auth.js.map