@pubinfo/module-auth 2.0.12 → 2.0.14
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/dist/core.d.ts +1 -6
- package/dist/helper.d.ts +22 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +102 -87
- package/dist/interface.d.ts +7 -11
- package/dist/pages/auth.d.ts +2 -2
- package/dist/providers/4A.d.ts +13 -3
- package/dist/providers/4A.js +5 -5
- package/dist/providers/credentials.d.ts +3 -5
- package/dist/providers/credentials.js +3 -4
- package/dist/providers/ding-zj.d.ts +7 -4
- package/dist/providers/ding-zj.js +6 -6
- package/dist/providers/sso.d.ts +19 -0
- package/dist/providers/sso.js +23 -0
- package/package.json +3 -3
- package/src/components/LoginWithFourA/index.ts +2 -2
- package/src/components/RedirectLogin/index.ts +2 -1
- package/src/core.ts +17 -47
- package/src/helper.ts +77 -0
- package/src/index.ts +3 -3
- package/src/interface.ts +7 -13
- package/src/pages/auth.ts +13 -2
- package/src/providers/4A.ts +17 -5
- package/src/providers/credentials.ts +4 -8
- package/src/providers/ding-zj.ts +13 -7
- package/src/providers/sso.ts +44 -0
package/dist/interface.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ export type Recordable = Record<string, any>;
|
|
|
3
3
|
export type Fn<T = any, K = any> = (params?: Recordable & T) => Promise<K> | K;
|
|
4
4
|
export type FnApi<T = any> = (params: Recordable & T, baseURL: string) => Promise<any>;
|
|
5
5
|
export interface AuthOptions {
|
|
6
|
-
/**
|
|
6
|
+
/** 登录后默认重定向至 */
|
|
7
7
|
redirectTo?: RouteLocationRaw | Fn;
|
|
8
8
|
/** 页面配置 */
|
|
9
9
|
pages?: {
|
|
@@ -12,17 +12,17 @@ export interface AuthOptions {
|
|
|
12
12
|
};
|
|
13
13
|
/** 接口的baseURL */
|
|
14
14
|
baseURL: string;
|
|
15
|
-
providers?:
|
|
15
|
+
providers?: ProviderOptions[];
|
|
16
16
|
}
|
|
17
17
|
export interface InternalContext {
|
|
18
18
|
/** 接口的baseURL */
|
|
19
19
|
baseURL: string;
|
|
20
|
-
providers?:
|
|
20
|
+
providers?: ProviderOptions[];
|
|
21
21
|
}
|
|
22
22
|
/** 第三方类型 */
|
|
23
23
|
export type ThirdParty = string;
|
|
24
|
-
export type
|
|
25
|
-
export interface
|
|
24
|
+
export type ProviderUserOptions = Partial<ProviderOptions>;
|
|
25
|
+
export interface ProviderOptions {
|
|
26
26
|
/** 唯一值 */
|
|
27
27
|
id: string;
|
|
28
28
|
/** 名称 */
|
|
@@ -35,13 +35,9 @@ export interface ProviderConfig {
|
|
|
35
35
|
*/
|
|
36
36
|
type: 'oauth' | 'cas' | 'custom';
|
|
37
37
|
/** 授权登录地址 */
|
|
38
|
-
|
|
39
|
-
/** `client_id` */
|
|
40
|
-
clientId?: string;
|
|
41
|
-
/** `redirect_uri` */
|
|
42
|
-
redirectUri?: string;
|
|
38
|
+
signIn?: Authorization | Fn;
|
|
43
39
|
/** 授权登录接口 */
|
|
44
|
-
|
|
40
|
+
authenticate?: string | FnApi;
|
|
45
41
|
/** 初始化二维码 */
|
|
46
42
|
initQRCode?: (url: string, params: {
|
|
47
43
|
id: string;
|
package/dist/pages/auth.d.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
export declare const PageAuth: import('../../../../node_modules/.pnpm/vue@3.5.17_typescript@5.8.3/node_modules/vue').DefineComponent<import('../../../../node_modules/.pnpm/vue@3.5.17_typescript@5.8.3/node_modules/vue').ExtractPropTypes<{
|
|
2
2
|
type: StringConstructor;
|
|
3
3
|
redirectTo: FunctionConstructor;
|
|
4
|
-
|
|
4
|
+
authenticate: FunctionConstructor;
|
|
5
5
|
}>, () => import('../../../../node_modules/.pnpm/vue@3.5.17_typescript@5.8.3/node_modules/vue').VNode<import('../../../../node_modules/.pnpm/vue@3.5.17_typescript@5.8.3/node_modules/vue').RendererNode, import('../../../../node_modules/.pnpm/vue@3.5.17_typescript@5.8.3/node_modules/vue').RendererElement, {
|
|
6
6
|
[key: string]: any;
|
|
7
7
|
}>, {}, {}, {}, import('../../../../node_modules/.pnpm/vue@3.5.17_typescript@5.8.3/node_modules/vue').ComponentOptionsMixin, import('../../../../node_modules/.pnpm/vue@3.5.17_typescript@5.8.3/node_modules/vue').ComponentOptionsMixin, {}, string, import('../../../../node_modules/.pnpm/vue@3.5.17_typescript@5.8.3/node_modules/vue').PublicProps, Readonly<import('../../../../node_modules/.pnpm/vue@3.5.17_typescript@5.8.3/node_modules/vue').ExtractPropTypes<{
|
|
8
8
|
type: StringConstructor;
|
|
9
9
|
redirectTo: FunctionConstructor;
|
|
10
|
-
|
|
10
|
+
authenticate: FunctionConstructor;
|
|
11
11
|
}>> & Readonly<{}>, {}, {}, {}, {}, string, import('../../../../node_modules/.pnpm/vue@3.5.17_typescript@5.8.3/node_modules/vue').ComponentProvideOptions, true, {}, any>;
|
package/dist/providers/4A.d.ts
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ProviderOptions, ProviderUserOptions } from '../interface';
|
|
2
|
+
export interface FourAOptions extends ProviderUserOptions {
|
|
3
|
+
/** `client_id` */
|
|
4
|
+
clientId?: string;
|
|
5
|
+
/** `redirect_uri` */
|
|
6
|
+
redirectUri?: string;
|
|
7
|
+
}
|
|
2
8
|
/**
|
|
3
|
-
* 4A
|
|
9
|
+
* `4A 统一认证`
|
|
10
|
+
*
|
|
11
|
+
* - 携带 `client_id` 和 `redirect_uri`,前往 [4A认证中心](http://134.108.76.137:7001/index) 进行登录;
|
|
12
|
+
* - 成功登录后,4A认证中心会回调 `redirect_uri` 并携带参数;
|
|
13
|
+
* - 当前 `provider` 将获取参数值并调用 `/bs/loginBy4a` 完成登录认证。
|
|
4
14
|
*/
|
|
5
|
-
export default function FourA(options:
|
|
15
|
+
export default function FourA(options: FourAOptions): ProviderOptions;
|
package/dist/providers/4A.js
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
function i(e) {
|
|
2
|
-
const { clientId:
|
|
2
|
+
const { clientId: t, redirectUri: r } = e;
|
|
3
3
|
return {
|
|
4
4
|
id: "4A",
|
|
5
5
|
name: "4A登录",
|
|
6
6
|
type: "oauth",
|
|
7
|
-
|
|
7
|
+
signIn: {
|
|
8
8
|
url: "http://134.108.76.137:7001/index",
|
|
9
9
|
params: {
|
|
10
10
|
response_type: "code",
|
|
11
|
-
client_id:
|
|
12
|
-
redirect_uri:
|
|
11
|
+
client_id: t,
|
|
12
|
+
redirect_uri: r
|
|
13
13
|
}
|
|
14
14
|
},
|
|
15
|
-
|
|
15
|
+
authenticate: "/bs/loginBy4a",
|
|
16
16
|
...e
|
|
17
17
|
};
|
|
18
18
|
}
|
|
@@ -1,9 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
interface
|
|
3
|
-
authorize: Fn<any>;
|
|
1
|
+
import { ProviderOptions, ProviderUserOptions } from '../interface';
|
|
2
|
+
export interface CredentialsOptions extends ProviderUserOptions {
|
|
4
3
|
}
|
|
5
4
|
/**
|
|
6
5
|
* 凭证登录
|
|
7
6
|
*/
|
|
8
|
-
export default function Credentials(options
|
|
9
|
-
export {};
|
|
7
|
+
export default function Credentials(options?: CredentialsOptions): ProviderOptions;
|
|
@@ -1,14 +1,17 @@
|
|
|
1
|
-
import {
|
|
2
|
-
interface
|
|
1
|
+
import { ProviderOptions, ProviderUserOptions } from '../interface';
|
|
2
|
+
export interface DingZJOptions extends ProviderUserOptions {
|
|
3
3
|
/**
|
|
4
4
|
* 登录方式
|
|
5
5
|
* - `redirect` 跳转浙政钉的扫码页面
|
|
6
6
|
* - `embed` 内嵌浙政钉的登录二维码
|
|
7
7
|
*/
|
|
8
8
|
mode: 'redirect' | 'embed';
|
|
9
|
+
/** `client_id` */
|
|
10
|
+
clientId?: string;
|
|
11
|
+
/** `redirect_uri` */
|
|
12
|
+
redirectUri?: string;
|
|
9
13
|
}
|
|
10
14
|
/**
|
|
11
15
|
* 浙政钉扫码登录
|
|
12
16
|
*/
|
|
13
|
-
export default function DingZJ(options:
|
|
14
|
-
export {};
|
|
17
|
+
export default function DingZJ(options: DingZJOptions): ProviderOptions;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
function
|
|
1
|
+
function g(e) {
|
|
2
2
|
const { clientId: i, redirectUri: n } = e, a = {
|
|
3
3
|
/** 跳转外部页面 */
|
|
4
4
|
redirect: {
|
|
@@ -27,10 +27,10 @@ function m(e) {
|
|
|
27
27
|
if (!document.getElementById(t.id))
|
|
28
28
|
throw new Error(`未找到id为${t.id}的DOM元素`);
|
|
29
29
|
const r = document.createElement("iframe");
|
|
30
|
-
r.src = c, r.width = "200", r.height = "200", document.appendChild(r), window.addEventListener("message", (
|
|
30
|
+
r.src = c, r.width = "200", r.height = "200", document.appendChild(r), window.addEventListener("message", (s) => {
|
|
31
31
|
if (t.redirectUri) {
|
|
32
32
|
const d = new URL(t.redirectUri);
|
|
33
|
-
d.search = new URLSearchParams(
|
|
33
|
+
d.search = new URLSearchParams(s.data).toString(), window.location.href = d.toString();
|
|
34
34
|
}
|
|
35
35
|
});
|
|
36
36
|
};
|
|
@@ -38,12 +38,12 @@ function m(e) {
|
|
|
38
38
|
id: "ding-zj",
|
|
39
39
|
name: "浙政钉登录",
|
|
40
40
|
type: "oauth",
|
|
41
|
-
|
|
42
|
-
|
|
41
|
+
signIn: a[e.mode],
|
|
42
|
+
authenticate: "/bs/loginByDingZJ",
|
|
43
43
|
initQRCode: e.mode === "embed" ? o : void 0,
|
|
44
44
|
...e
|
|
45
45
|
};
|
|
46
46
|
}
|
|
47
47
|
export {
|
|
48
|
-
|
|
48
|
+
g as default
|
|
49
49
|
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { ProviderOptions, ProviderUserOptions } from '../interface';
|
|
2
|
+
export interface SsoOptions extends ProviderUserOptions {
|
|
3
|
+
/**
|
|
4
|
+
* 登录类型,根据调用 `/app/oauth/generateCode` 接口时传递的 `grantType` 参数值判断:
|
|
5
|
+
*
|
|
6
|
+
* - `OAUTH2` -> `defaultOauth2`
|
|
7
|
+
* - `SIMPLE_ENCRYPT` -> `encrypt`
|
|
8
|
+
*
|
|
9
|
+
* @default `defaultOauth2`
|
|
10
|
+
*/
|
|
11
|
+
loginType?: 'defaultOauth2' | 'encrypt';
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* `SSO 统一账号登录`
|
|
15
|
+
*
|
|
16
|
+
* - 主系统调用 `/app/oauth/generateCode?appKey=xxx` 获取 `code`,并作为参数跳转至子系统;
|
|
17
|
+
* - 当前 `provider` 将获取 `code` 并调用 `/auth/ssoLogin` 完成登录认证。
|
|
18
|
+
*/
|
|
19
|
+
export default function Sso(options?: SsoOptions): ProviderOptions;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
function o(t = {}) {
|
|
2
|
+
const { loginType: e = "defaultOauth2" } = t;
|
|
3
|
+
return {
|
|
4
|
+
id: "sso",
|
|
5
|
+
name: "SSO统一账号登录",
|
|
6
|
+
type: "custom",
|
|
7
|
+
authenticate: async (a, n) => await (await fetch(
|
|
8
|
+
`${n}/auth/ssoLogin`,
|
|
9
|
+
{
|
|
10
|
+
headers: { "Content-Type": "application/json" },
|
|
11
|
+
method: "POST",
|
|
12
|
+
body: JSON.stringify({
|
|
13
|
+
...a,
|
|
14
|
+
loginType: e
|
|
15
|
+
})
|
|
16
|
+
}
|
|
17
|
+
)).json(),
|
|
18
|
+
...t
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
export {
|
|
22
|
+
o as default
|
|
23
|
+
};
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pubinfo/module-auth",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "2.0.
|
|
4
|
+
"version": "2.0.14",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": {
|
|
7
7
|
"types": "./dist/index.d.ts",
|
|
@@ -23,10 +23,10 @@
|
|
|
23
23
|
"node": "^20.19.0 || >=22.12.0"
|
|
24
24
|
},
|
|
25
25
|
"peerDependencies": {
|
|
26
|
-
"pubinfo": "2.0.
|
|
26
|
+
"pubinfo": "2.0.14"
|
|
27
27
|
},
|
|
28
28
|
"devDependencies": {
|
|
29
|
-
"pubinfo": "2.0.
|
|
29
|
+
"pubinfo": "2.0.14"
|
|
30
30
|
},
|
|
31
31
|
"scripts": {
|
|
32
32
|
"dev": "pubinfo build --watch",
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { defineComponent, h } from 'vue';
|
|
2
|
-
import
|
|
2
|
+
import FourAPNG from '@/assets/images/4A.png';
|
|
3
3
|
import { RedirectLogin } from '../RedirectLogin';
|
|
4
4
|
|
|
5
5
|
export const LoginWithFourA = defineComponent({
|
|
@@ -11,6 +11,6 @@ export const LoginWithFourA = defineComponent({
|
|
|
11
11
|
},
|
|
12
12
|
},
|
|
13
13
|
setup(props) {
|
|
14
|
-
return () => h(RedirectLogin, { id: '4A', src:
|
|
14
|
+
return () => h(RedirectLogin, { id: '4A', src: FourAPNG, color: props.color });
|
|
15
15
|
},
|
|
16
16
|
});
|
package/src/core.ts
CHANGED
|
@@ -1,35 +1,6 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { Recordable, ThirdParty } from './interface';
|
|
2
2
|
import { ctx } from './context';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* 获取指定的 `Provider`
|
|
6
|
-
* @param id
|
|
7
|
-
*/
|
|
8
|
-
export function getProvider(id?: ThirdParty) {
|
|
9
|
-
const { providers } = ctx.use();
|
|
10
|
-
const provider = id ? providers?.find(provider => provider.id === id) : providers?.[0];
|
|
11
|
-
if (!provider) {
|
|
12
|
-
throw new Error(`Provider '${id}' is not found.`);
|
|
13
|
-
}
|
|
14
|
-
return provider;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* 构建第三方授权登录地址
|
|
19
|
-
* @param provider
|
|
20
|
-
*/
|
|
21
|
-
function createUrl(provider: ProviderUserConfig) {
|
|
22
|
-
const { authorization } = provider;
|
|
23
|
-
|
|
24
|
-
if (typeof authorization === 'function') {
|
|
25
|
-
return '';
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
const url = new URL(authorization?.url ?? '');
|
|
29
|
-
const params = new URLSearchParams(authorization?.params ?? {});
|
|
30
|
-
|
|
31
|
-
return `${url.toString()}?${params.toString()}`;
|
|
32
|
-
}
|
|
3
|
+
import { createUrl, createUrlByProvider, getProvider } from './helper';
|
|
33
4
|
|
|
34
5
|
/**
|
|
35
6
|
* 前往登录
|
|
@@ -38,14 +9,13 @@ function createUrl(provider: ProviderUserConfig) {
|
|
|
38
9
|
*/
|
|
39
10
|
export async function signIn(id: ThirdParty, options?: Recordable) {
|
|
40
11
|
const provider = getProvider(id);
|
|
41
|
-
const { type, authorization } = provider;
|
|
42
12
|
|
|
43
|
-
if (typeof
|
|
44
|
-
return await
|
|
13
|
+
if (typeof provider.signIn === 'function') {
|
|
14
|
+
return await provider.signIn(options);
|
|
45
15
|
}
|
|
46
16
|
|
|
47
|
-
if (
|
|
48
|
-
const url =
|
|
17
|
+
if (['oauth', 'custom'].includes(provider.type)) {
|
|
18
|
+
const url = createUrlByProvider(provider);
|
|
49
19
|
window.location.replace(url);
|
|
50
20
|
}
|
|
51
21
|
}
|
|
@@ -58,11 +28,10 @@ export async function signIn(id: ThirdParty, options?: Recordable) {
|
|
|
58
28
|
*/
|
|
59
29
|
export function renderQRCode(id: ThirdParty, options: { id: string } & Recordable) {
|
|
60
30
|
const provider = getProvider(id);
|
|
61
|
-
const { type, initQRCode } = provider;
|
|
62
31
|
|
|
63
|
-
if (
|
|
64
|
-
const url =
|
|
65
|
-
initQRCode?.(url, options);
|
|
32
|
+
if (['oauth', 'custom'].includes(provider.type)) {
|
|
33
|
+
const url = createUrlByProvider(provider);
|
|
34
|
+
provider.initQRCode?.(url, options);
|
|
66
35
|
}
|
|
67
36
|
}
|
|
68
37
|
|
|
@@ -70,22 +39,23 @@ export function renderQRCode(id: ThirdParty, options: { id: string } & Recordabl
|
|
|
70
39
|
* 认证
|
|
71
40
|
* @param id 第三方的唯一值
|
|
72
41
|
*/
|
|
73
|
-
export async function
|
|
42
|
+
export async function authenticate(id: ThirdParty) {
|
|
74
43
|
const provider = getProvider(id);
|
|
75
44
|
const { baseURL } = ctx.use();
|
|
76
|
-
const { type, callbackUrl } = provider;
|
|
77
45
|
|
|
78
46
|
// TODO 处理hash路由中的#
|
|
79
47
|
// 获取URL上的参数
|
|
80
48
|
const qs = window.location.href.split('?')?.[1] ?? '';
|
|
81
49
|
const params = new URLSearchParams(qs);
|
|
50
|
+
const paramsObject = Object.fromEntries(params.entries());
|
|
82
51
|
|
|
83
|
-
if (typeof
|
|
84
|
-
return await
|
|
52
|
+
if (typeof provider.authenticate === 'function') {
|
|
53
|
+
return await provider.authenticate(paramsObject, baseURL);
|
|
85
54
|
}
|
|
86
55
|
|
|
87
|
-
if (
|
|
88
|
-
const
|
|
56
|
+
if (['oauth', 'cas', 'custom'].includes(provider.type)) {
|
|
57
|
+
const url = createUrl(`${baseURL}${provider.authenticate}`, paramsObject);
|
|
58
|
+
const response = await fetch(url);
|
|
89
59
|
return await response.json();
|
|
90
60
|
}
|
|
91
61
|
}
|
|
@@ -100,6 +70,6 @@ export function redirect() {
|
|
|
100
70
|
return;
|
|
101
71
|
}
|
|
102
72
|
|
|
103
|
-
const url =
|
|
73
|
+
const url = createUrlByProvider(provider);
|
|
104
74
|
window.location.replace(url);
|
|
105
75
|
}
|
package/src/helper.ts
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import type { ProviderUserOptions, Recordable, ThirdParty } from './interface';
|
|
2
|
+
import { ctx } from './context';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* 获取指定的 `Provider`
|
|
6
|
+
* @param id
|
|
7
|
+
*/
|
|
8
|
+
export function getProvider(id?: ThirdParty) {
|
|
9
|
+
const { providers } = ctx.use();
|
|
10
|
+
const provider = id ? providers?.find(provider => provider.id === id) : providers?.[0];
|
|
11
|
+
if (!provider) {
|
|
12
|
+
throw new Error(`Provider '${id}' is not found.`);
|
|
13
|
+
}
|
|
14
|
+
return provider;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* 构建第三方授权登录地址
|
|
19
|
+
* @param provider
|
|
20
|
+
*/
|
|
21
|
+
export function createUrlByProvider(provider: ProviderUserOptions) {
|
|
22
|
+
const { signIn } = provider;
|
|
23
|
+
|
|
24
|
+
if (typeof signIn === 'function') {
|
|
25
|
+
return '';
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
return createUrl(signIn?.url, signIn?.params);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* 构建携带 `params` 的 URL
|
|
33
|
+
* @param url
|
|
34
|
+
* @param params
|
|
35
|
+
*/
|
|
36
|
+
export function createUrl(url: string = '', params: Recordable = {}) {
|
|
37
|
+
const _url = new URL(url);
|
|
38
|
+
const _params = new URLSearchParams(_url.search);
|
|
39
|
+
|
|
40
|
+
// 合并参数
|
|
41
|
+
for (const [key, value] of Object.entries(params)) {
|
|
42
|
+
_params.set(key, value);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
_url.search = _params.toString();
|
|
46
|
+
|
|
47
|
+
return _url.toString();
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* 读取 `URL` 上的 `params` 参数
|
|
52
|
+
* @param url
|
|
53
|
+
*/
|
|
54
|
+
export function readUrlParams(url?: string): URLSearchParams {
|
|
55
|
+
const { href, search, hash } = url ? new URL(url) : window.location;
|
|
56
|
+
|
|
57
|
+
// 1.优先从 search(history 模式)拿
|
|
58
|
+
if (search) {
|
|
59
|
+
return new URLSearchParams(search);
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
// 2.再尝试从 hash(hash 模式)里拿
|
|
63
|
+
// 可能是 /#/callback?code=xxx
|
|
64
|
+
const hashIndex = hash.indexOf('?');
|
|
65
|
+
if (hashIndex !== -1) {
|
|
66
|
+
return new URLSearchParams(hash.slice(hashIndex));
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// 3.fallback:尝试整个 URL
|
|
70
|
+
const qsIndex = href.indexOf('?');
|
|
71
|
+
if (qsIndex !== -1) {
|
|
72
|
+
return new URLSearchParams(href.slice(qsIndex));
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// 4.否则返回空
|
|
76
|
+
return new URLSearchParams();
|
|
77
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -3,7 +3,7 @@ import type { RouteRecordRaw } from 'vue-router';
|
|
|
3
3
|
import type { AuthOptions } from './interface';
|
|
4
4
|
import { cleanup } from 'pubinfo';
|
|
5
5
|
import { ctx } from './context';
|
|
6
|
-
import {
|
|
6
|
+
import { authenticate, redirect } from './core';
|
|
7
7
|
import { PageAuth } from './pages/auth';
|
|
8
8
|
|
|
9
9
|
export function auth(options: AuthOptions): ModuleOptions {
|
|
@@ -33,7 +33,7 @@ export function auth(options: AuthOptions): ModuleOptions {
|
|
|
33
33
|
},
|
|
34
34
|
props: route => ({
|
|
35
35
|
type: route.params.type,
|
|
36
|
-
|
|
36
|
+
authenticate,
|
|
37
37
|
redirectTo() {
|
|
38
38
|
if (typeof redirectTo === 'function') {
|
|
39
39
|
redirectTo();
|
|
@@ -69,7 +69,7 @@ export function auth(options: AuthOptions): ModuleOptions {
|
|
|
69
69
|
export { LoginWithFourA } from './components/LoginWithFourA';
|
|
70
70
|
|
|
71
71
|
export {
|
|
72
|
-
|
|
72
|
+
authenticate,
|
|
73
73
|
redirect,
|
|
74
74
|
renderQRCode,
|
|
75
75
|
signIn,
|
package/src/interface.ts
CHANGED
|
@@ -5,7 +5,7 @@ export type Fn<T = any, K = any> = (params?: Recordable & T) => Promise<K> | K;
|
|
|
5
5
|
export type FnApi<T = any> = (params: Recordable & T, baseURL: string) => Promise<any>;
|
|
6
6
|
|
|
7
7
|
export interface AuthOptions {
|
|
8
|
-
/**
|
|
8
|
+
/** 登录后默认重定向至 */
|
|
9
9
|
redirectTo?: RouteLocationRaw | Fn
|
|
10
10
|
|
|
11
11
|
/** 页面配置 */
|
|
@@ -17,21 +17,21 @@ export interface AuthOptions {
|
|
|
17
17
|
/** 接口的baseURL */
|
|
18
18
|
baseURL: string
|
|
19
19
|
|
|
20
|
-
providers?:
|
|
20
|
+
providers?: ProviderOptions[]
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
export interface InternalContext {
|
|
24
24
|
/** 接口的baseURL */
|
|
25
25
|
baseURL: string
|
|
26
26
|
|
|
27
|
-
providers?:
|
|
27
|
+
providers?: ProviderOptions[]
|
|
28
28
|
}
|
|
29
29
|
|
|
30
30
|
/** 第三方类型 */
|
|
31
31
|
export type ThirdParty = string;
|
|
32
|
-
export type
|
|
32
|
+
export type ProviderUserOptions = Partial<ProviderOptions>;
|
|
33
33
|
|
|
34
|
-
export interface
|
|
34
|
+
export interface ProviderOptions {
|
|
35
35
|
/** 唯一值 */
|
|
36
36
|
id: string
|
|
37
37
|
|
|
@@ -47,16 +47,10 @@ export interface ProviderConfig {
|
|
|
47
47
|
type: 'oauth' | 'cas' | 'custom'
|
|
48
48
|
|
|
49
49
|
/** 授权登录地址 */
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
/** `client_id` */
|
|
53
|
-
clientId?: string
|
|
54
|
-
|
|
55
|
-
/** `redirect_uri` */
|
|
56
|
-
redirectUri?: string
|
|
50
|
+
signIn?: Authorization | Fn
|
|
57
51
|
|
|
58
52
|
/** 授权登录接口 */
|
|
59
|
-
|
|
53
|
+
authenticate?: string | FnApi
|
|
60
54
|
|
|
61
55
|
/** 初始化二维码 */
|
|
62
56
|
initQRCode?: (url: string, params: { id: string } & Recordable) => Promise<void> | void
|
package/src/pages/auth.ts
CHANGED
|
@@ -5,17 +5,28 @@ export const PageAuth = defineComponent({
|
|
|
5
5
|
props: {
|
|
6
6
|
type: String,
|
|
7
7
|
redirectTo: Function,
|
|
8
|
-
|
|
8
|
+
authenticate: Function,
|
|
9
9
|
},
|
|
10
10
|
setup(props) {
|
|
11
11
|
const userStore = useUserStore();
|
|
12
|
+
const route = useRoute();
|
|
13
|
+
const router = useRouter();
|
|
12
14
|
|
|
13
15
|
const message = ref('授权登录中...');
|
|
14
16
|
|
|
15
17
|
onMounted(async () => {
|
|
16
|
-
const res = await props.
|
|
18
|
+
const res = await props.authenticate?.(props.type);
|
|
17
19
|
if (res?.success) {
|
|
18
20
|
userStore.setToken(res?.data?.accessToken, res?.data?.refreshToken);
|
|
21
|
+
|
|
22
|
+
// 读取路由上的 redirect 参数
|
|
23
|
+
const redirect = route.query.redirect?.toString();
|
|
24
|
+
if (redirect) {
|
|
25
|
+
router.push(redirect);
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// 默认的重定向地址
|
|
19
30
|
props?.redirectTo?.();
|
|
20
31
|
}
|
|
21
32
|
else {
|
package/src/providers/4A.ts
CHANGED
|
@@ -1,16 +1,28 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { ProviderOptions, ProviderUserOptions } from '../interface';
|
|
2
|
+
|
|
3
|
+
export interface FourAOptions extends ProviderUserOptions {
|
|
4
|
+
/** `client_id` */
|
|
5
|
+
clientId?: string
|
|
6
|
+
|
|
7
|
+
/** `redirect_uri` */
|
|
8
|
+
redirectUri?: string
|
|
9
|
+
}
|
|
2
10
|
|
|
3
11
|
/**
|
|
4
|
-
* 4A
|
|
12
|
+
* `4A 统一认证`
|
|
13
|
+
*
|
|
14
|
+
* - 携带 `client_id` 和 `redirect_uri`,前往 [4A认证中心](http://134.108.76.137:7001/index) 进行登录;
|
|
15
|
+
* - 成功登录后,4A认证中心会回调 `redirect_uri` 并携带参数;
|
|
16
|
+
* - 当前 `provider` 将获取参数值并调用 `/bs/loginBy4a` 完成登录认证。
|
|
5
17
|
*/
|
|
6
|
-
export default function FourA(options:
|
|
18
|
+
export default function FourA(options: FourAOptions): ProviderOptions {
|
|
7
19
|
const { clientId, redirectUri } = options;
|
|
8
20
|
|
|
9
21
|
return {
|
|
10
22
|
id: '4A',
|
|
11
23
|
name: '4A登录',
|
|
12
24
|
type: 'oauth',
|
|
13
|
-
|
|
25
|
+
signIn: {
|
|
14
26
|
url: 'http://134.108.76.137:7001/index',
|
|
15
27
|
params: {
|
|
16
28
|
response_type: 'code',
|
|
@@ -18,7 +30,7 @@ export default function FourA(options: ProviderUserConfig): ProviderConfig {
|
|
|
18
30
|
redirect_uri: redirectUri,
|
|
19
31
|
},
|
|
20
32
|
},
|
|
21
|
-
|
|
33
|
+
authenticate: '/bs/loginBy4a',
|
|
22
34
|
...options,
|
|
23
35
|
};
|
|
24
36
|
}
|
|
@@ -1,19 +1,15 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { ProviderOptions, ProviderUserOptions } from '../interface';
|
|
2
2
|
|
|
3
|
-
interface
|
|
4
|
-
authorize: Fn<any>
|
|
5
|
-
}
|
|
3
|
+
export interface CredentialsOptions extends ProviderUserOptions {}
|
|
6
4
|
|
|
7
5
|
/**
|
|
8
6
|
* 凭证登录
|
|
9
7
|
*/
|
|
10
|
-
export default function Credentials(options
|
|
11
|
-
const { authorize } = options;
|
|
12
|
-
|
|
8
|
+
export default function Credentials(options?: CredentialsOptions): ProviderOptions {
|
|
13
9
|
return {
|
|
14
10
|
id: 'credentials',
|
|
15
11
|
name: '凭证登录',
|
|
16
12
|
type: 'custom',
|
|
17
|
-
|
|
13
|
+
...options,
|
|
18
14
|
};
|
|
19
15
|
}
|