@delon/auth 15.2.1 → 16.0.0-beta.0
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/esm2022/src/auth.module.mjs +13 -0
- package/esm2022/src/social/social.service.mjs +107 -0
- package/esm2022/src/token/base.interceptor.mjs +75 -0
- package/esm2022/src/token/jwt/jwt.guard.mjs +64 -0
- package/esm2022/src/token/jwt/jwt.interceptor.mjs +35 -0
- package/esm2022/src/token/simple/simple.guard.mjs +63 -0
- package/esm2022/src/token/simple/simple.interceptor.mjs +52 -0
- package/esm2022/src/token/token.service.mjs +92 -0
- package/{fesm2020 → fesm2022}/auth.mjs +25 -25
- package/{fesm2015 → fesm2022}/auth.mjs.map +1 -1
- package/package.json +6 -12
- package/esm2020/src/auth.module.mjs +0 -12
- package/esm2020/src/social/social.service.mjs +0 -106
- package/esm2020/src/token/base.interceptor.mjs +0 -74
- package/esm2020/src/token/jwt/jwt.guard.mjs +0 -63
- package/esm2020/src/token/jwt/jwt.interceptor.mjs +0 -34
- package/esm2020/src/token/simple/simple.guard.mjs +0 -62
- package/esm2020/src/token/simple/simple.interceptor.mjs +0 -51
- package/esm2020/src/token/token.service.mjs +0 -91
- package/fesm2015/auth.mjs +0 -734
- package/fesm2020/auth.mjs.map +0 -1
- /package/{esm2020 → esm2022}/auth.mjs +0 -0
- /package/{esm2020 → esm2022}/index.mjs +0 -0
- /package/{esm2020 → esm2022}/src/auth.config.mjs +0 -0
- /package/{esm2020 → esm2022}/src/store/cookie-storage.service.mjs +0 -0
- /package/{esm2020 → esm2022}/src/store/interface.mjs +0 -0
- /package/{esm2020 → esm2022}/src/store/local-storage.service.mjs +0 -0
- /package/{esm2020 → esm2022}/src/store/memory.service.mjs +0 -0
- /package/{esm2020 → esm2022}/src/store/session-storage.service.mjs +0 -0
- /package/{esm2020 → esm2022}/src/token/helper.mjs +0 -0
- /package/{esm2020 → esm2022}/src/token/interface.mjs +0 -0
- /package/{esm2020 → esm2022}/src/token/jwt/jwt.helper.mjs +0 -0
- /package/{esm2020 → esm2022}/src/token/jwt/jwt.model.mjs +0 -0
- /package/{esm2020 → esm2022}/src/token/simple/simple.model.mjs +0 -0
- /package/{esm2020 → esm2022}/src/token.mjs +0 -0
package/fesm2015/auth.mjs
DELETED
|
@@ -1,734 +0,0 @@
|
|
|
1
|
-
import { DOCUMENT } from '@angular/common';
|
|
2
|
-
import * as i0 from '@angular/core';
|
|
3
|
-
import { InjectionToken, inject, Injectable, Inject, Optional, NgModule } from '@angular/core';
|
|
4
|
-
import { Subject, BehaviorSubject, share, interval, map, filter, Observable } from 'rxjs';
|
|
5
|
-
import * as i1 from '@delon/util/config';
|
|
6
|
-
import { AlainConfigService } from '@delon/util/config';
|
|
7
|
-
import * as i1$1 from '@angular/router';
|
|
8
|
-
import { Router } from '@angular/router';
|
|
9
|
-
import { HttpContextToken, HttpErrorResponse, HTTP_INTERCEPTORS } from '@angular/common/http';
|
|
10
|
-
|
|
11
|
-
const AUTH_DEFAULT_CONFIG = {
|
|
12
|
-
store_key: `_token`,
|
|
13
|
-
token_invalid_redirect: true,
|
|
14
|
-
token_exp_offset: 10,
|
|
15
|
-
token_send_key: `token`,
|
|
16
|
-
token_send_template: '${token}',
|
|
17
|
-
token_send_place: 'header',
|
|
18
|
-
login_url: '/login',
|
|
19
|
-
ignores: [/\/login/, /assets\//, /passport\//],
|
|
20
|
-
executeOtherInterceptors: true,
|
|
21
|
-
refreshTime: 3000,
|
|
22
|
-
refreshOffset: 6000
|
|
23
|
-
};
|
|
24
|
-
function mergeConfig(srv) {
|
|
25
|
-
return srv.merge('auth', AUTH_DEFAULT_CONFIG);
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
function DA_STORE_TOKEN_LOCAL_FACTORY() {
|
|
29
|
-
return new LocalStorageStore();
|
|
30
|
-
}
|
|
31
|
-
/**
|
|
32
|
-
* `localStorage` storage, **not lost after closing the browser**.
|
|
33
|
-
*
|
|
34
|
-
* ```ts
|
|
35
|
-
* // global-config.module.ts
|
|
36
|
-
* { provide: DA_STORE_TOKEN, useClass: LocalStorageStore }
|
|
37
|
-
* ```
|
|
38
|
-
*/
|
|
39
|
-
class LocalStorageStore {
|
|
40
|
-
get(key) {
|
|
41
|
-
return JSON.parse(localStorage.getItem(key) || '{}') || {};
|
|
42
|
-
}
|
|
43
|
-
set(key, value) {
|
|
44
|
-
localStorage.setItem(key, JSON.stringify(value));
|
|
45
|
-
return true;
|
|
46
|
-
}
|
|
47
|
-
remove(key) {
|
|
48
|
-
localStorage.removeItem(key);
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
const DA_STORE_TOKEN = new InjectionToken('AUTH_STORE_TOKEN', {
|
|
53
|
-
providedIn: 'root',
|
|
54
|
-
factory: DA_STORE_TOKEN_LOCAL_FACTORY
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
function DA_SERVICE_TOKEN_FACTORY() {
|
|
58
|
-
return new TokenService(inject(AlainConfigService), inject(DA_STORE_TOKEN));
|
|
59
|
-
}
|
|
60
|
-
/**
|
|
61
|
-
* 维护Token信息服务,[在线文档](https://ng-alain.com/auth)
|
|
62
|
-
*/
|
|
63
|
-
class TokenService {
|
|
64
|
-
constructor(configSrv, store) {
|
|
65
|
-
this.store = store;
|
|
66
|
-
this.refresh$ = new Subject();
|
|
67
|
-
this.change$ = new BehaviorSubject(null);
|
|
68
|
-
this._referrer = {};
|
|
69
|
-
this._options = mergeConfig(configSrv);
|
|
70
|
-
}
|
|
71
|
-
get refresh() {
|
|
72
|
-
this.builderRefresh();
|
|
73
|
-
return this.refresh$.pipe(share());
|
|
74
|
-
}
|
|
75
|
-
get login_url() {
|
|
76
|
-
return this._options.login_url;
|
|
77
|
-
}
|
|
78
|
-
get referrer() {
|
|
79
|
-
return this._referrer;
|
|
80
|
-
}
|
|
81
|
-
get options() {
|
|
82
|
-
return this._options;
|
|
83
|
-
}
|
|
84
|
-
set(data) {
|
|
85
|
-
const res = this.store.set(this._options.store_key, data);
|
|
86
|
-
this.change$.next(data);
|
|
87
|
-
return res;
|
|
88
|
-
}
|
|
89
|
-
get(type) {
|
|
90
|
-
const data = this.store.get(this._options.store_key);
|
|
91
|
-
return type ? Object.assign(new type(), data) : data;
|
|
92
|
-
}
|
|
93
|
-
clear(options = { onlyToken: false }) {
|
|
94
|
-
let data = null;
|
|
95
|
-
if (options.onlyToken === true) {
|
|
96
|
-
data = this.get();
|
|
97
|
-
data.token = ``;
|
|
98
|
-
this.set(data);
|
|
99
|
-
}
|
|
100
|
-
else {
|
|
101
|
-
this.store.remove(this._options.store_key);
|
|
102
|
-
}
|
|
103
|
-
this.change$.next(data);
|
|
104
|
-
}
|
|
105
|
-
change() {
|
|
106
|
-
return this.change$.pipe(share());
|
|
107
|
-
}
|
|
108
|
-
builderRefresh() {
|
|
109
|
-
const { refreshTime, refreshOffset } = this._options;
|
|
110
|
-
this.cleanRefresh();
|
|
111
|
-
this.interval$ = interval(refreshTime)
|
|
112
|
-
.pipe(map(() => {
|
|
113
|
-
const item = this.get();
|
|
114
|
-
const expired = item.expired || item.exp || 0;
|
|
115
|
-
if (expired <= 0) {
|
|
116
|
-
return null;
|
|
117
|
-
}
|
|
118
|
-
const curTime = new Date().valueOf() + refreshOffset;
|
|
119
|
-
return expired <= curTime ? item : null;
|
|
120
|
-
}), filter(v => v != null))
|
|
121
|
-
.subscribe(res => this.refresh$.next(res));
|
|
122
|
-
}
|
|
123
|
-
cleanRefresh() {
|
|
124
|
-
if (this.interval$ && !this.interval$.closed) {
|
|
125
|
-
this.interval$.unsubscribe();
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
ngOnDestroy() {
|
|
129
|
-
this.cleanRefresh();
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
TokenService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: TokenService, deps: [{ token: i1.AlainConfigService }, { token: DA_STORE_TOKEN }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
133
|
-
TokenService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: TokenService });
|
|
134
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: TokenService, decorators: [{
|
|
135
|
-
type: Injectable
|
|
136
|
-
}], ctorParameters: function () {
|
|
137
|
-
return [{ type: i1.AlainConfigService }, { type: undefined, decorators: [{
|
|
138
|
-
type: Inject,
|
|
139
|
-
args: [DA_STORE_TOKEN]
|
|
140
|
-
}] }];
|
|
141
|
-
} });
|
|
142
|
-
|
|
143
|
-
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
144
|
-
const DA_SERVICE_TOKEN = new InjectionToken('DA_SERVICE_TOKEN', {
|
|
145
|
-
providedIn: 'root',
|
|
146
|
-
factory: DA_SERVICE_TOKEN_FACTORY
|
|
147
|
-
});
|
|
148
|
-
|
|
149
|
-
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
150
|
-
const OPENTYPE = '_delonAuthSocialType';
|
|
151
|
-
const HREFCALLBACK = '_delonAuthSocialCallbackByHref';
|
|
152
|
-
class SocialService {
|
|
153
|
-
constructor(tokenService, doc, router) {
|
|
154
|
-
this.tokenService = tokenService;
|
|
155
|
-
this.doc = doc;
|
|
156
|
-
this.router = router;
|
|
157
|
-
this._win = null;
|
|
158
|
-
}
|
|
159
|
-
/**
|
|
160
|
-
* 跳转至登录页,若为 `type=window` 时,返回值是 `Observable<ITokenModel>`
|
|
161
|
-
*
|
|
162
|
-
* @param url 获取授权地址
|
|
163
|
-
* @param callback 当 `type=href` 成功时的回调路由地址
|
|
164
|
-
* @param options.type 打开方式,默认 `window`
|
|
165
|
-
* @param options.windowFeatures 等同 `window.open` 的 `features` 参数值
|
|
166
|
-
*/
|
|
167
|
-
login(url, callback = '/', options = {}) {
|
|
168
|
-
options = Object.assign({ type: 'window', windowFeatures: 'location=yes,height=570,width=520,scrollbars=yes,status=yes' }, options);
|
|
169
|
-
localStorage.setItem(OPENTYPE, options.type);
|
|
170
|
-
localStorage.setItem(HREFCALLBACK, callback);
|
|
171
|
-
if (options.type === 'href') {
|
|
172
|
-
this.doc.location.href = url;
|
|
173
|
-
return;
|
|
174
|
-
}
|
|
175
|
-
this._win = window.open(url, '_blank', options.windowFeatures);
|
|
176
|
-
this._winTime = setInterval(() => {
|
|
177
|
-
if (this._win && this._win.closed) {
|
|
178
|
-
this.ngOnDestroy();
|
|
179
|
-
let model = this.tokenService.get();
|
|
180
|
-
if (model && !model.token)
|
|
181
|
-
model = null;
|
|
182
|
-
// 触发变更通知
|
|
183
|
-
if (model) {
|
|
184
|
-
this.tokenService.set(model);
|
|
185
|
-
}
|
|
186
|
-
this.observer.next(model);
|
|
187
|
-
this.observer.complete();
|
|
188
|
-
}
|
|
189
|
-
}, 100);
|
|
190
|
-
return new Observable((observer) => {
|
|
191
|
-
this.observer = observer;
|
|
192
|
-
});
|
|
193
|
-
}
|
|
194
|
-
/**
|
|
195
|
-
* 授权成功后的回调处理
|
|
196
|
-
*
|
|
197
|
-
* @param rawData 指定回调认证信息,为空时从根据当前URL解析
|
|
198
|
-
*/
|
|
199
|
-
callback(rawData) {
|
|
200
|
-
// from uri
|
|
201
|
-
if (!rawData && this.router.url.indexOf('?') === -1) {
|
|
202
|
-
throw new Error(`url muse contain a ?`);
|
|
203
|
-
}
|
|
204
|
-
// parse
|
|
205
|
-
let data = { token: `` };
|
|
206
|
-
if (typeof rawData === 'string') {
|
|
207
|
-
const rightUrl = rawData.split('?')[1].split('#')[0];
|
|
208
|
-
data = this.router.parseUrl(`./?${rightUrl}`).queryParams;
|
|
209
|
-
}
|
|
210
|
-
else {
|
|
211
|
-
data = rawData;
|
|
212
|
-
}
|
|
213
|
-
if (!data || !data.token)
|
|
214
|
-
throw new Error(`invalide token data`);
|
|
215
|
-
this.tokenService.set(data);
|
|
216
|
-
const url = localStorage.getItem(HREFCALLBACK) || '/';
|
|
217
|
-
localStorage.removeItem(HREFCALLBACK);
|
|
218
|
-
const type = localStorage.getItem(OPENTYPE);
|
|
219
|
-
localStorage.removeItem(OPENTYPE);
|
|
220
|
-
if (type === 'window') {
|
|
221
|
-
window.close();
|
|
222
|
-
}
|
|
223
|
-
else {
|
|
224
|
-
this.router.navigateByUrl(url);
|
|
225
|
-
}
|
|
226
|
-
return data;
|
|
227
|
-
}
|
|
228
|
-
ngOnDestroy() {
|
|
229
|
-
clearInterval(this._winTime);
|
|
230
|
-
this._winTime = null;
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
SocialService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: SocialService, deps: [{ token: DA_SERVICE_TOKEN }, { token: DOCUMENT }, { token: i1$1.Router }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
234
|
-
SocialService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: SocialService });
|
|
235
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: SocialService, decorators: [{
|
|
236
|
-
type: Injectable
|
|
237
|
-
}], ctorParameters: function () {
|
|
238
|
-
return [{ type: undefined, decorators: [{
|
|
239
|
-
type: Inject,
|
|
240
|
-
args: [DA_SERVICE_TOKEN]
|
|
241
|
-
}] }, { type: undefined, decorators: [{
|
|
242
|
-
type: Inject,
|
|
243
|
-
args: [DOCUMENT]
|
|
244
|
-
}] }, { type: i1$1.Router }];
|
|
245
|
-
} });
|
|
246
|
-
|
|
247
|
-
/**
|
|
248
|
-
* 内存存储,关掉浏览器标签后**丢失**。
|
|
249
|
-
*
|
|
250
|
-
* ```ts
|
|
251
|
-
* // global-config.module.ts
|
|
252
|
-
* { provide: DA_STORE_TOKEN, useClass: MemoryStore }
|
|
253
|
-
* ```
|
|
254
|
-
*/
|
|
255
|
-
class MemoryStore {
|
|
256
|
-
constructor() {
|
|
257
|
-
this.cache = {};
|
|
258
|
-
}
|
|
259
|
-
get(key) {
|
|
260
|
-
return this.cache[key] || {};
|
|
261
|
-
}
|
|
262
|
-
set(key, value) {
|
|
263
|
-
this.cache[key] = value;
|
|
264
|
-
return true;
|
|
265
|
-
}
|
|
266
|
-
remove(key) {
|
|
267
|
-
this.cache[key] = null;
|
|
268
|
-
}
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
/**
|
|
272
|
-
* `sessionStorage` storage, **lost after closing the browser**.
|
|
273
|
-
*
|
|
274
|
-
* ```ts
|
|
275
|
-
* // global-config.module.ts
|
|
276
|
-
* { provide: DA_STORE_TOKEN, useClass: SessionStorageStore }
|
|
277
|
-
* ```
|
|
278
|
-
*/
|
|
279
|
-
class SessionStorageStore {
|
|
280
|
-
get(key) {
|
|
281
|
-
return JSON.parse(sessionStorage.getItem(key) || '{}') || {};
|
|
282
|
-
}
|
|
283
|
-
set(key, value) {
|
|
284
|
-
sessionStorage.setItem(key, JSON.stringify(value));
|
|
285
|
-
return true;
|
|
286
|
-
}
|
|
287
|
-
remove(key) {
|
|
288
|
-
sessionStorage.removeItem(key);
|
|
289
|
-
}
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
/**
|
|
293
|
-
* `cookie` storage
|
|
294
|
-
*
|
|
295
|
-
* ```ts
|
|
296
|
-
* // global-config.module.ts
|
|
297
|
-
* { provide: DA_STORE_TOKEN, useClass: CookieStorageStore, deps: [CookieService] }
|
|
298
|
-
* ```
|
|
299
|
-
*/
|
|
300
|
-
class CookieStorageStore {
|
|
301
|
-
constructor(srv) {
|
|
302
|
-
this.srv = srv;
|
|
303
|
-
}
|
|
304
|
-
get(key) {
|
|
305
|
-
try {
|
|
306
|
-
return JSON.parse(this.srv.get(key) || '{}');
|
|
307
|
-
}
|
|
308
|
-
catch (ex) {
|
|
309
|
-
if (typeof ngDevMode === 'undefined' || ngDevMode) {
|
|
310
|
-
console.error(`CookieStorageStore: Invalid key-value format ${key}`, ex);
|
|
311
|
-
}
|
|
312
|
-
return {};
|
|
313
|
-
}
|
|
314
|
-
}
|
|
315
|
-
set(key, value) {
|
|
316
|
-
this.srv.put(key, value != null ? JSON.stringify(value) : '{}');
|
|
317
|
-
return true;
|
|
318
|
-
}
|
|
319
|
-
remove(key) {
|
|
320
|
-
this.srv.remove(key);
|
|
321
|
-
}
|
|
322
|
-
}
|
|
323
|
-
|
|
324
|
-
/**
|
|
325
|
-
* Whether to allow anonymous login
|
|
326
|
-
*
|
|
327
|
-
* 是否允许匿名登录
|
|
328
|
-
*
|
|
329
|
-
* @example
|
|
330
|
-
* this.http.post(`login`, {
|
|
331
|
-
* name: 'cipchk', pwd: '123456'
|
|
332
|
-
* }, {
|
|
333
|
-
* context: new HttpContext().set(ALLOW_ANONYMOUS, true)
|
|
334
|
-
* })
|
|
335
|
-
*/
|
|
336
|
-
const ALLOW_ANONYMOUS = new HttpContextToken(() => false);
|
|
337
|
-
|
|
338
|
-
function CheckSimple(model) {
|
|
339
|
-
return model != null && typeof model.token === 'string' && model.token.length > 0;
|
|
340
|
-
}
|
|
341
|
-
function CheckJwt(model, offset) {
|
|
342
|
-
try {
|
|
343
|
-
return model != null && !!model.token && !model.isExpired(offset);
|
|
344
|
-
}
|
|
345
|
-
catch (err) {
|
|
346
|
-
if (typeof ngDevMode === 'undefined' || ngDevMode) {
|
|
347
|
-
console.warn(`${err.message}, jump to login_url`);
|
|
348
|
-
}
|
|
349
|
-
return false;
|
|
350
|
-
}
|
|
351
|
-
}
|
|
352
|
-
function ToLogin(options, injector, url) {
|
|
353
|
-
const router = injector.get(Router);
|
|
354
|
-
injector.get(DA_SERVICE_TOKEN).referrer.url = url || router.url;
|
|
355
|
-
if (options.token_invalid_redirect === true) {
|
|
356
|
-
setTimeout(() => {
|
|
357
|
-
if (/^https?:\/\//g.test(options.login_url)) {
|
|
358
|
-
injector.get(DOCUMENT).location.href = options.login_url;
|
|
359
|
-
}
|
|
360
|
-
else {
|
|
361
|
-
router.navigate([options.login_url]);
|
|
362
|
-
}
|
|
363
|
-
});
|
|
364
|
-
}
|
|
365
|
-
}
|
|
366
|
-
|
|
367
|
-
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
368
|
-
class HttpAuthInterceptorHandler {
|
|
369
|
-
constructor(next, interceptor) {
|
|
370
|
-
this.next = next;
|
|
371
|
-
this.interceptor = interceptor;
|
|
372
|
-
}
|
|
373
|
-
handle(req) {
|
|
374
|
-
return this.interceptor.intercept(req, this.next);
|
|
375
|
-
}
|
|
376
|
-
}
|
|
377
|
-
class BaseInterceptor {
|
|
378
|
-
constructor(injector) {
|
|
379
|
-
this.injector = injector;
|
|
380
|
-
}
|
|
381
|
-
intercept(req, next) {
|
|
382
|
-
if (req.context.get(ALLOW_ANONYMOUS))
|
|
383
|
-
return next.handle(req);
|
|
384
|
-
const options = mergeConfig(this.injector.get(AlainConfigService));
|
|
385
|
-
if (Array.isArray(options.ignores)) {
|
|
386
|
-
for (const item of options.ignores) {
|
|
387
|
-
if (item.test(req.url))
|
|
388
|
-
return next.handle(req);
|
|
389
|
-
}
|
|
390
|
-
}
|
|
391
|
-
if (this.isAuth(options)) {
|
|
392
|
-
req = this.setReq(req, options);
|
|
393
|
-
}
|
|
394
|
-
else {
|
|
395
|
-
ToLogin(options, this.injector);
|
|
396
|
-
// Interrupt Http request, so need to generate a new Observable
|
|
397
|
-
const err$ = new Observable((observer) => {
|
|
398
|
-
let statusText = '';
|
|
399
|
-
if (typeof ngDevMode === 'undefined' || ngDevMode) {
|
|
400
|
-
statusText = `来自 @delon/auth 的拦截,所请求URL未授权,若是登录API可加入 [url?_allow_anonymous=true] 来表示忽略校验,更多方法请参考: https://ng-alain.com/auth/getting-started#AlainAuthConfig\nThe interception from @delon/auth, the requested URL is not authorized. If the login API can add [url?_allow_anonymous=true] to ignore the check, please refer to: https://ng-alain.com/auth/getting-started#AlainAuthConfig`;
|
|
401
|
-
}
|
|
402
|
-
const res = new HttpErrorResponse({
|
|
403
|
-
url: req.url,
|
|
404
|
-
headers: req.headers,
|
|
405
|
-
status: 401,
|
|
406
|
-
statusText
|
|
407
|
-
});
|
|
408
|
-
observer.error(res);
|
|
409
|
-
});
|
|
410
|
-
if (options.executeOtherInterceptors) {
|
|
411
|
-
const interceptors = this.injector.get(HTTP_INTERCEPTORS, []);
|
|
412
|
-
const lastInterceptors = interceptors.slice(interceptors.indexOf(this) + 1);
|
|
413
|
-
if (lastInterceptors.length > 0) {
|
|
414
|
-
const chain = lastInterceptors.reduceRight((_next, _interceptor) => new HttpAuthInterceptorHandler(_next, _interceptor), {
|
|
415
|
-
handle: (_) => err$
|
|
416
|
-
});
|
|
417
|
-
return chain.handle(req);
|
|
418
|
-
}
|
|
419
|
-
}
|
|
420
|
-
return err$;
|
|
421
|
-
}
|
|
422
|
-
return next.handle(req);
|
|
423
|
-
}
|
|
424
|
-
}
|
|
425
|
-
BaseInterceptor.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: BaseInterceptor, deps: [{ token: i0.Injector, optional: true }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
426
|
-
BaseInterceptor.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: BaseInterceptor });
|
|
427
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: BaseInterceptor, decorators: [{
|
|
428
|
-
type: Injectable
|
|
429
|
-
}], ctorParameters: function () {
|
|
430
|
-
return [{ type: i0.Injector, decorators: [{
|
|
431
|
-
type: Optional
|
|
432
|
-
}] }];
|
|
433
|
-
} });
|
|
434
|
-
|
|
435
|
-
function urlBase64Decode(str) {
|
|
436
|
-
let output = str.replace(/-/g, '+').replace(/_/g, '/');
|
|
437
|
-
switch (output.length % 4) {
|
|
438
|
-
case 0: {
|
|
439
|
-
break;
|
|
440
|
-
}
|
|
441
|
-
case 2: {
|
|
442
|
-
output += '==';
|
|
443
|
-
break;
|
|
444
|
-
}
|
|
445
|
-
case 3: {
|
|
446
|
-
output += '=';
|
|
447
|
-
break;
|
|
448
|
-
}
|
|
449
|
-
default: {
|
|
450
|
-
throw new Error(`'atob' failed: The string to be decoded is not correctly encoded.`);
|
|
451
|
-
}
|
|
452
|
-
}
|
|
453
|
-
return b64DecodeUnicode(output);
|
|
454
|
-
}
|
|
455
|
-
function b64decode(str) {
|
|
456
|
-
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
|
|
457
|
-
let output = '';
|
|
458
|
-
str = String(str).replace(/=+$/, '');
|
|
459
|
-
for (
|
|
460
|
-
// initialize result and counters
|
|
461
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
462
|
-
let bc = 0, bs, buffer, idx = 0;
|
|
463
|
-
// get next character
|
|
464
|
-
(buffer = str.charAt(idx++));
|
|
465
|
-
// character found in table? initialize bit storage and add its ascii value;
|
|
466
|
-
~buffer &&
|
|
467
|
-
((bs = bc % 4 ? bs * 64 + buffer : buffer),
|
|
468
|
-
// and if not first of each 4 characters,
|
|
469
|
-
// convert the first 8 bits to one ascii character
|
|
470
|
-
bc++ % 4)
|
|
471
|
-
? (output += String.fromCharCode(255 & (bs >> ((-2 * bc) & 6))))
|
|
472
|
-
: 0) {
|
|
473
|
-
// try to find character in table (0-63, not found => -1)
|
|
474
|
-
buffer = chars.indexOf(buffer);
|
|
475
|
-
}
|
|
476
|
-
return output;
|
|
477
|
-
}
|
|
478
|
-
// https://developer.mozilla.org/en/docs/Web/API/WindowBase64/Base64_encoding_and_decoding#The_Unicode_Problem
|
|
479
|
-
function b64DecodeUnicode(str) {
|
|
480
|
-
return decodeURIComponent(Array.prototype.map
|
|
481
|
-
.call(b64decode(str), (c) => {
|
|
482
|
-
return `%${`00${c.charCodeAt(0).toString(16)}`.slice(-2)}`;
|
|
483
|
-
})
|
|
484
|
-
.join(''));
|
|
485
|
-
}
|
|
486
|
-
|
|
487
|
-
class JWTTokenModel {
|
|
488
|
-
/**
|
|
489
|
-
* 获取载荷信息
|
|
490
|
-
*/
|
|
491
|
-
get payload() {
|
|
492
|
-
const parts = (this.token || '').split('.');
|
|
493
|
-
if (parts.length !== 3)
|
|
494
|
-
throw new Error('JWT must have 3 parts');
|
|
495
|
-
const decoded = urlBase64Decode(parts[1]);
|
|
496
|
-
return JSON.parse(decoded);
|
|
497
|
-
}
|
|
498
|
-
/**
|
|
499
|
-
* 获取过期时间戳(单位:ms)
|
|
500
|
-
*/
|
|
501
|
-
get exp() {
|
|
502
|
-
const decoded = this.payload;
|
|
503
|
-
if (!decoded.hasOwnProperty('exp'))
|
|
504
|
-
return null;
|
|
505
|
-
const date = new Date(0);
|
|
506
|
-
date.setUTCSeconds(decoded.exp);
|
|
507
|
-
return date.valueOf();
|
|
508
|
-
}
|
|
509
|
-
/**
|
|
510
|
-
* 检查Token是否过期,当`payload` 包含 `exp` 字段时有效,若无 `exp` 字段直接返回 `null`
|
|
511
|
-
*
|
|
512
|
-
* @param offsetSeconds 偏移量
|
|
513
|
-
*/
|
|
514
|
-
isExpired(offsetSeconds = 0) {
|
|
515
|
-
const exp = this.exp;
|
|
516
|
-
if (exp == null)
|
|
517
|
-
return null;
|
|
518
|
-
return !(exp > new Date().valueOf() + offsetSeconds * 1000);
|
|
519
|
-
}
|
|
520
|
-
}
|
|
521
|
-
|
|
522
|
-
/**
|
|
523
|
-
* JWT 拦截器
|
|
524
|
-
*
|
|
525
|
-
* ```
|
|
526
|
-
* // app.module.ts
|
|
527
|
-
* { provide: HTTP_INTERCEPTORS, useClass: JWTInterceptor, multi: true}
|
|
528
|
-
* ```
|
|
529
|
-
*/
|
|
530
|
-
class JWTInterceptor extends BaseInterceptor {
|
|
531
|
-
isAuth(options) {
|
|
532
|
-
this.model = this.injector.get(DA_SERVICE_TOKEN).get(JWTTokenModel);
|
|
533
|
-
return CheckJwt(this.model, options.token_exp_offset);
|
|
534
|
-
}
|
|
535
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
536
|
-
setReq(req, _options) {
|
|
537
|
-
return req.clone({
|
|
538
|
-
setHeaders: {
|
|
539
|
-
Authorization: `Bearer ${this.model.token}`
|
|
540
|
-
}
|
|
541
|
-
});
|
|
542
|
-
}
|
|
543
|
-
}
|
|
544
|
-
JWTInterceptor.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: JWTInterceptor, deps: null, target: i0.ɵɵFactoryTarget.Injectable });
|
|
545
|
-
JWTInterceptor.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: JWTInterceptor });
|
|
546
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: JWTInterceptor, decorators: [{
|
|
547
|
-
type: Injectable
|
|
548
|
-
}] });
|
|
549
|
-
|
|
550
|
-
/**
|
|
551
|
-
* JWT 路由守卫, [ACL Document](https://ng-alain.com/auth/guard).
|
|
552
|
-
*
|
|
553
|
-
* ```ts
|
|
554
|
-
* data: {
|
|
555
|
-
* path: 'home',
|
|
556
|
-
* canActivate: [ JWTGuard ]
|
|
557
|
-
* },
|
|
558
|
-
* {
|
|
559
|
-
* path: 'my',
|
|
560
|
-
* canActivateChild: [JWTGuard],
|
|
561
|
-
* children: [
|
|
562
|
-
* { path: 'profile', component: MockComponent }
|
|
563
|
-
* ],
|
|
564
|
-
* },
|
|
565
|
-
* ```
|
|
566
|
-
*/
|
|
567
|
-
class JWTGuard {
|
|
568
|
-
get cog() {
|
|
569
|
-
return this.srv.options;
|
|
570
|
-
}
|
|
571
|
-
constructor(srv, injector) {
|
|
572
|
-
this.srv = srv;
|
|
573
|
-
this.injector = injector;
|
|
574
|
-
}
|
|
575
|
-
process() {
|
|
576
|
-
const res = CheckJwt(this.srv.get(JWTTokenModel), this.cog.token_exp_offset);
|
|
577
|
-
if (!res) {
|
|
578
|
-
ToLogin(this.cog, this.injector, this.url);
|
|
579
|
-
}
|
|
580
|
-
return res;
|
|
581
|
-
}
|
|
582
|
-
// lazy loading
|
|
583
|
-
canMatch(route) {
|
|
584
|
-
this.url = route.path;
|
|
585
|
-
return this.process();
|
|
586
|
-
}
|
|
587
|
-
// all children route
|
|
588
|
-
canActivateChild(_childRoute, state) {
|
|
589
|
-
this.url = state.url;
|
|
590
|
-
return this.process();
|
|
591
|
-
}
|
|
592
|
-
// route
|
|
593
|
-
canActivate(_route, state) {
|
|
594
|
-
this.url = state.url;
|
|
595
|
-
return this.process();
|
|
596
|
-
}
|
|
597
|
-
}
|
|
598
|
-
JWTGuard.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: JWTGuard, deps: [{ token: DA_SERVICE_TOKEN }, { token: i0.Injector }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
599
|
-
JWTGuard.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: JWTGuard, providedIn: 'root' });
|
|
600
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: JWTGuard, decorators: [{
|
|
601
|
-
type: Injectable,
|
|
602
|
-
args: [{ providedIn: 'root' }]
|
|
603
|
-
}], ctorParameters: function () {
|
|
604
|
-
return [{ type: undefined, decorators: [{
|
|
605
|
-
type: Inject,
|
|
606
|
-
args: [DA_SERVICE_TOKEN]
|
|
607
|
-
}] }, { type: i0.Injector }];
|
|
608
|
-
} });
|
|
609
|
-
|
|
610
|
-
class SimpleTokenModel {
|
|
611
|
-
}
|
|
612
|
-
|
|
613
|
-
/**
|
|
614
|
-
* Simple 拦截器
|
|
615
|
-
*
|
|
616
|
-
* ```
|
|
617
|
-
* // app.module.ts
|
|
618
|
-
* { provide: HTTP_INTERCEPTORS, useClass: SimpleInterceptor, multi: true}
|
|
619
|
-
* ```
|
|
620
|
-
*/
|
|
621
|
-
class SimpleInterceptor extends BaseInterceptor {
|
|
622
|
-
isAuth(_options) {
|
|
623
|
-
this.model = this.injector.get(DA_SERVICE_TOKEN).get();
|
|
624
|
-
return CheckSimple(this.model);
|
|
625
|
-
}
|
|
626
|
-
setReq(req, options) {
|
|
627
|
-
const { token_send_template, token_send_key } = options;
|
|
628
|
-
const token = token_send_template.replace(/\$\{([\w]+)\}/g, (_, g) => this.model[g]);
|
|
629
|
-
switch (options.token_send_place) {
|
|
630
|
-
case 'header':
|
|
631
|
-
const obj = {};
|
|
632
|
-
obj[token_send_key] = token;
|
|
633
|
-
req = req.clone({
|
|
634
|
-
setHeaders: obj
|
|
635
|
-
});
|
|
636
|
-
break;
|
|
637
|
-
case 'body':
|
|
638
|
-
const body = req.body || {};
|
|
639
|
-
body[token_send_key] = token;
|
|
640
|
-
req = req.clone({
|
|
641
|
-
body
|
|
642
|
-
});
|
|
643
|
-
break;
|
|
644
|
-
case 'url':
|
|
645
|
-
req = req.clone({
|
|
646
|
-
params: req.params.append(token_send_key, token)
|
|
647
|
-
});
|
|
648
|
-
break;
|
|
649
|
-
}
|
|
650
|
-
return req;
|
|
651
|
-
}
|
|
652
|
-
}
|
|
653
|
-
SimpleInterceptor.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: SimpleInterceptor, deps: null, target: i0.ɵɵFactoryTarget.Injectable });
|
|
654
|
-
SimpleInterceptor.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: SimpleInterceptor });
|
|
655
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: SimpleInterceptor, decorators: [{
|
|
656
|
-
type: Injectable
|
|
657
|
-
}] });
|
|
658
|
-
|
|
659
|
-
/**
|
|
660
|
-
* Simple 路由守卫, [ACL Document](https://ng-alain.com/auth/guard).
|
|
661
|
-
*
|
|
662
|
-
* ```ts
|
|
663
|
-
* data: {
|
|
664
|
-
* path: 'home',
|
|
665
|
-
* canActivate: [ SimpleGuard ]
|
|
666
|
-
* },
|
|
667
|
-
* {
|
|
668
|
-
* path: 'my',
|
|
669
|
-
* canActivateChild: [SimpleGuard],
|
|
670
|
-
* children: [
|
|
671
|
-
* { path: 'profile', component: MockComponent }
|
|
672
|
-
* ],
|
|
673
|
-
* },
|
|
674
|
-
* ```
|
|
675
|
-
*/
|
|
676
|
-
class SimpleGuard {
|
|
677
|
-
get cog() {
|
|
678
|
-
return this.srv.options;
|
|
679
|
-
}
|
|
680
|
-
constructor(srv, injector) {
|
|
681
|
-
this.srv = srv;
|
|
682
|
-
this.injector = injector;
|
|
683
|
-
}
|
|
684
|
-
process() {
|
|
685
|
-
const res = CheckSimple(this.srv.get());
|
|
686
|
-
if (!res) {
|
|
687
|
-
ToLogin(this.cog, this.injector, this.url);
|
|
688
|
-
}
|
|
689
|
-
return res;
|
|
690
|
-
}
|
|
691
|
-
// lazy loading
|
|
692
|
-
canMatch(route) {
|
|
693
|
-
this.url = route.path;
|
|
694
|
-
return this.process();
|
|
695
|
-
}
|
|
696
|
-
// all children route
|
|
697
|
-
canActivateChild(_childRoute, state) {
|
|
698
|
-
this.url = state.url;
|
|
699
|
-
return this.process();
|
|
700
|
-
}
|
|
701
|
-
// route
|
|
702
|
-
canActivate(_route, state) {
|
|
703
|
-
this.url = state.url;
|
|
704
|
-
return this.process();
|
|
705
|
-
}
|
|
706
|
-
}
|
|
707
|
-
SimpleGuard.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: SimpleGuard, deps: [{ token: DA_SERVICE_TOKEN }, { token: i0.Injector }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
708
|
-
SimpleGuard.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: SimpleGuard, providedIn: 'root' });
|
|
709
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: SimpleGuard, decorators: [{
|
|
710
|
-
type: Injectable,
|
|
711
|
-
args: [{ providedIn: 'root' }]
|
|
712
|
-
}], ctorParameters: function () {
|
|
713
|
-
return [{ type: undefined, decorators: [{
|
|
714
|
-
type: Inject,
|
|
715
|
-
args: [DA_SERVICE_TOKEN]
|
|
716
|
-
}] }, { type: i0.Injector }];
|
|
717
|
-
} });
|
|
718
|
-
|
|
719
|
-
class DelonAuthModule {
|
|
720
|
-
}
|
|
721
|
-
DelonAuthModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: DelonAuthModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
722
|
-
DelonAuthModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "15.2.9", ngImport: i0, type: DelonAuthModule });
|
|
723
|
-
DelonAuthModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: DelonAuthModule });
|
|
724
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: DelonAuthModule, decorators: [{
|
|
725
|
-
type: NgModule,
|
|
726
|
-
args: [{}]
|
|
727
|
-
}] });
|
|
728
|
-
|
|
729
|
-
/**
|
|
730
|
-
* Generated bundle index. Do not edit.
|
|
731
|
-
*/
|
|
732
|
-
|
|
733
|
-
export { ALLOW_ANONYMOUS, AUTH_DEFAULT_CONFIG, BaseInterceptor, CookieStorageStore, DA_SERVICE_TOKEN, DA_SERVICE_TOKEN_FACTORY, DA_STORE_TOKEN, DA_STORE_TOKEN_LOCAL_FACTORY, DelonAuthModule, JWTGuard, JWTInterceptor, JWTTokenModel, LocalStorageStore, MemoryStore, SessionStorageStore, SimpleGuard, SimpleInterceptor, SimpleTokenModel, SocialService, TokenService, mergeConfig, urlBase64Decode };
|
|
734
|
-
//# sourceMappingURL=auth.mjs.map
|