收口移动壳H5入口来源
移动壳启动URL仅允许生产主站和本机开发入口 补充移动壳URL和deep link测试,防止外域H5获得HostBridge 更新原生壳方案和共享决策记录
This commit is contained in:
@@ -74,11 +74,11 @@ describe('buildMobileShellUrlFromDeepLink', () => {
|
||||
expect(url.pathname).toBe('/');
|
||||
});
|
||||
|
||||
test('基准 H5 URL 配置非法时回退到默认启动地址', () => {
|
||||
test('基准 H5 URL 配置非法或外域时回退到默认启动地址', () => {
|
||||
const url = new URL(
|
||||
buildMobileShellUrlFromDeepLink(
|
||||
'genarrative://open/works/detail?work=PZ-1',
|
||||
'file:///tmp/index.html',
|
||||
'https://example.com/app',
|
||||
options,
|
||||
),
|
||||
);
|
||||
|
||||
@@ -13,7 +13,7 @@ describe('buildMobileShellUrl', () => {
|
||||
|
||||
test('为 H5 附加原生移动壳上下文', () => {
|
||||
const url = new URL(
|
||||
buildMobileShellUrl('https://app.test/works/detail?work=PZ-1', {
|
||||
buildMobileShellUrl('https://app.genarrative.world/works/detail?work=PZ-1', {
|
||||
platform: 'ios',
|
||||
hostVersion: '0.1.0',
|
||||
capabilities: ['host.getRuntime', 'share.open'],
|
||||
@@ -34,14 +34,14 @@ describe('buildMobileShellUrl', () => {
|
||||
|
||||
test('支持按平台注入不同能力清单', () => {
|
||||
const iosUrl = new URL(
|
||||
buildMobileShellUrl('https://app.test/', {
|
||||
buildMobileShellUrl('https://app.genarrative.world/', {
|
||||
platform: 'ios',
|
||||
hostVersion: '0.1.0',
|
||||
capabilities: ['host.getRuntime', 'app.setBadgeCount'],
|
||||
}),
|
||||
);
|
||||
const androidUrl = new URL(
|
||||
buildMobileShellUrl('https://app.test/', {
|
||||
buildMobileShellUrl('https://app.genarrative.world/', {
|
||||
platform: 'android',
|
||||
hostVersion: '0.1.0',
|
||||
capabilities: ['host.getRuntime'],
|
||||
@@ -56,13 +56,24 @@ describe('buildMobileShellUrl', () => {
|
||||
);
|
||||
});
|
||||
|
||||
test('移动壳基准 URL 只接受 http 和 https', () => {
|
||||
expect(resolveMobileShellBaseWebUrl('https://app.test/path')).toBe(
|
||||
'https://app.test/path',
|
||||
test('移动壳基准 URL 只接受生产主站和本机开发入口', () => {
|
||||
expect(
|
||||
resolveMobileShellBaseWebUrl('https://app.genarrative.world/path'),
|
||||
).toBe(
|
||||
'https://app.genarrative.world/path',
|
||||
);
|
||||
expect(resolveMobileShellBaseWebUrl(' http://127.0.0.1:3000/ ')).toBe(
|
||||
'http://127.0.0.1:3000/',
|
||||
);
|
||||
expect(resolveMobileShellBaseWebUrl('http://localhost:3000/')).toBe(
|
||||
'http://localhost:3000/',
|
||||
);
|
||||
expect(resolveMobileShellBaseWebUrl('https://example.com/path')).toBe(
|
||||
DEFAULT_MOBILE_SHELL_WEB_URL,
|
||||
);
|
||||
expect(resolveMobileShellBaseWebUrl('http://192.168.1.2:3000/')).toBe(
|
||||
DEFAULT_MOBILE_SHELL_WEB_URL,
|
||||
);
|
||||
expect(resolveMobileShellBaseWebUrl('javascript:alert(1)')).toBe(
|
||||
DEFAULT_MOBILE_SHELL_WEB_URL,
|
||||
);
|
||||
|
||||
@@ -10,6 +10,21 @@ export type MobileShellUrlOptions = {
|
||||
};
|
||||
|
||||
export const DEFAULT_MOBILE_SHELL_WEB_URL = 'https://app.genarrative.world/';
|
||||
const ALLOWED_PRODUCTION_WEB_ORIGIN = 'https://app.genarrative.world';
|
||||
const LOCAL_DEVELOPMENT_WEB_HOSTS = new Set([
|
||||
'127.0.0.1',
|
||||
'localhost',
|
||||
'[::1]',
|
||||
]);
|
||||
|
||||
function isAllowedMobileShellBaseUrl(url: URL) {
|
||||
if (url.origin === ALLOWED_PRODUCTION_WEB_ORIGIN) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return url.protocol === 'http:' &&
|
||||
LOCAL_DEVELOPMENT_WEB_HOSTS.has(url.hostname);
|
||||
}
|
||||
|
||||
export function resolveMobileShellBaseWebUrl(rawUrl: unknown) {
|
||||
if (typeof rawUrl !== 'string') {
|
||||
@@ -23,7 +38,7 @@ export function resolveMobileShellBaseWebUrl(rawUrl: unknown) {
|
||||
|
||||
try {
|
||||
const url = new URL(value);
|
||||
if (url.protocol !== 'http:' && url.protocol !== 'https:') {
|
||||
if (!isAllowedMobileShellBaseUrl(url)) {
|
||||
return DEFAULT_MOBILE_SHELL_WEB_URL;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user