提交 76cffded 编写于 作者: Cano1997's avatar Cano1997

update: 添加重定向白名单校验

上级 a840c2a4
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
<script lang="ts"> <script lang="ts">
import { Vue, Component,Prop } from 'vue-property-decorator'; import { Vue, Component,Prop } from 'vue-property-decorator';
import { Subject } from 'rxjs'; import { Subject } from 'rxjs';
import { safeRedirect } from '@/utils';
/** /**
* 表格列链接 * 表格列链接
*/ */
...@@ -192,7 +193,7 @@ export default class AppColumnLink extends Vue { ...@@ -192,7 +193,7 @@ export default class AppColumnLink extends Vue {
* @memberof AppColumnLink * @memberof AppColumnLink
*/ */
private openPopupApp(url: string): void { private openPopupApp(url: string): void {
window.open(url, '_blank'); safeRedirect(url, { type: '_blank'});
} }
/** /**
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
import { Vue, Component, Prop, Model, Emit } from "vue-property-decorator"; import { Vue, Component, Prop, Model, Emit } from "vue-property-decorator";
import { Subject } from "rxjs"; import { Subject } from "rxjs";
import { Environment } from '@/environments/environment'; import { Environment } from '@/environments/environment';
import { safeRedirect } from "@/utils";
@Component({ @Component({
}) })
...@@ -66,7 +67,7 @@ export default class AppHeaderMenus extends Vue { ...@@ -66,7 +67,7 @@ export default class AppHeaderMenus extends Vue {
* @memberof AppHeaderMenus * @memberof AppHeaderMenus
*/ */
public openWindow(menu:any){ public openWindow(menu:any){
window.open(menu.url, '_blank'); safeRedirect(menu.url, { type: '_blank'});
} }
......
...@@ -33,6 +33,7 @@ ...@@ -33,6 +33,7 @@
import { Vue, Component, Prop, Watch, Provide } from 'vue-property-decorator'; import { Vue, Component, Prop, Watch, Provide } from 'vue-property-decorator';
import { Environment } from '@/environments/environment'; import { Environment } from '@/environments/environment';
import { Subject, Unsubscribable } from 'rxjs'; import { Subject, Unsubscribable } from 'rxjs';
import { safeRedirect } from '@/utils';
@Component({}) @Component({})
export default class AppImagePreview extends Vue { export default class AppImagePreview extends Vue {
...@@ -167,7 +168,7 @@ export default class AppImagePreview extends Vue { ...@@ -167,7 +168,7 @@ export default class AppImagePreview extends Vue {
* @memberof AppImagePreview * @memberof AppImagePreview
*/ */
public onDownload(file: any) { public onDownload(file: any) {
window.open(file.url); safeRedirect(file.url, { type: '_blank'});
} }
/** /**
......
...@@ -65,6 +65,7 @@ ...@@ -65,6 +65,7 @@
import { Vue, Component, Prop, Watch, Provide } from 'vue-property-decorator'; import { Vue, Component, Prop, Watch, Provide } from 'vue-property-decorator';
import { Environment } from '@/environments/environment'; import { Environment } from '@/environments/environment';
import { Subject, Unsubscribable } from 'rxjs'; import { Subject, Unsubscribable } from 'rxjs';
import { safeRedirect } from '@/utils';
@Component({}) @Component({})
export default class AppImageUpload extends Vue { export default class AppImageUpload extends Vue {
...@@ -455,7 +456,7 @@ export default class AppImageUpload extends Vue { ...@@ -455,7 +456,7 @@ export default class AppImageUpload extends Vue {
* @memberof AppImageUpload * @memberof AppImageUpload
*/ */
public onDownload(file: any) { public onDownload(file: any) {
window.open(file.url); safeRedirect(file.url, { type: '_blank'});
} }
/** /**
......
...@@ -87,6 +87,7 @@ ...@@ -87,6 +87,7 @@
import {Vue, Component, Prop, Model, Emit} from "vue-property-decorator"; import {Vue, Component, Prop, Model, Emit} from "vue-property-decorator";
import {Environment} from '@/environments/environment'; import {Environment} from '@/environments/environment';
import moment from 'moment'; import moment from 'moment';
import { safeRedirect } from '@/utils';
@Component({}) @Component({})
export default class AppMessagePopover extends Vue { export default class AppMessagePopover extends Vue {
...@@ -176,7 +177,7 @@ export default class AppMessagePopover extends Vue { ...@@ -176,7 +177,7 @@ export default class AppMessagePopover extends Vue {
const baseUrl:any = Environment.BaseUrl; const baseUrl:any = Environment.BaseUrl;
const openUrl:any = baseUrl + `/wfcore/mytasks/${data.processDefinitionKey}/web/${data.processInstanceBusinessKey}/usertasks/${data.taskDefinitionKey}`; const openUrl:any = baseUrl + `/wfcore/mytasks/${data.processDefinitionKey}/web/${data.processInstanceBusinessKey}/usertasks/${data.taskDefinitionKey}`;
// 打开新窗口 // 打开新窗口
window.open(openUrl,'_blank'); safeRedirect(openUrl, { type: '_blank'});
} }
/** /**
......
...@@ -58,7 +58,7 @@ ...@@ -58,7 +58,7 @@
<script lang = 'ts'> <script lang = 'ts'>
import { Component, Vue, Prop, Model, Watch } from 'vue-property-decorator'; import { Component, Vue, Prop, Model, Watch } from 'vue-property-decorator';
import { Subject } from 'rxjs'; import { Subject } from 'rxjs';
import { AppModal } from '@/utils'; import { AppModal, safeRedirect } from '@/utils';
@Component({ @Component({
}) })
...@@ -585,7 +585,7 @@ export default class AppPicker extends Vue { ...@@ -585,7 +585,7 @@ export default class AppPicker extends Vue {
* @memberof AppPicker * @memberof AppPicker
*/ */
private openPopupApp(url: string): void { private openPopupApp(url: string): void {
window.open(url, '_blank'); safeRedirect(url, { type: '_blank'});
} }
/** /**
......
...@@ -10,6 +10,7 @@ import { Environment } from '@/environments/environment'; ...@@ -10,6 +10,7 @@ import { Environment } from '@/environments/environment';
import { CreateElement } from 'vue'; import { CreateElement } from 'vue';
import { Subject, Unsubscribable } from 'rxjs'; import { Subject, Unsubscribable } from 'rxjs';
import EntityService from '@/service/entity-service'; import EntityService from '@/service/entity-service';
import { safeRedirect } from '@/utils';
@Component({ @Component({
}) })
...@@ -131,7 +132,7 @@ export default class AppUploadFileInfo extends Vue { ...@@ -131,7 +132,7 @@ export default class AppUploadFileInfo extends Vue {
* @memberof AppUploadFileInfo * @memberof AppUploadFileInfo
*/ */
public onDownload(file: any) { public onDownload(file: any) {
window.open(file.url); safeRedirect(file.url, { type: '_blank'});
} }
} }
......
...@@ -64,6 +64,7 @@ ...@@ -64,6 +64,7 @@
import draggable from "vuedraggable"; import draggable from "vuedraggable";
import EntityService from '@/service/entity-service'; import EntityService from '@/service/entity-service';
import { Vue,Component,Provide,Watch,Prop,Model } from "vue-property-decorator"; import { Vue,Component,Provide,Watch,Prop,Model } from "vue-property-decorator";
import { safeRedirect } from '@/utils';
// tslint:disable-next-line:max-classes-per-file // tslint:disable-next-line:max-classes-per-file
@Component({ @Component({
...@@ -219,7 +220,7 @@ export default class ContextMenuDrag extends Vue { ...@@ -219,7 +220,7 @@ export default class ContextMenuDrag extends Vue {
let params: any = {}; let params: any = {};
params.model = this.selectlist; params.model = this.selectlist;
const put: Promise<any> = this.entityService.updateChooseApp(null,params); const put: Promise<any> = this.entityService.updateChooseApp(null,params);
window.location.href = item.addr; safeRedirect(item.addr, { type: 'href' });
}else{ }else{
this.$message.info((this.$t('components.contextMenuDrag.noFind') as string)); this.$message.info((this.$t('components.contextMenuDrag.noFind') as string));
} }
......
...@@ -72,6 +72,7 @@ import { Unsubscribable } from 'rxjs'; ...@@ -72,6 +72,7 @@ import { Unsubscribable } from 'rxjs';
import { Environment } from '@/environments/environment'; import { Environment } from '@/environments/environment';
import { encode } from "js-base64"; import { encode } from "js-base64";
import EntityService from '@/service/entity-service'; import EntityService from '@/service/entity-service';
import { safeRedirect } from '@/utils';
@Component({}) @Component({})
export default class DiskFileUpload extends Vue { export default class DiskFileUpload extends Vue {
...@@ -623,7 +624,7 @@ export default class DiskFileUpload extends Vue { ...@@ -623,7 +624,7 @@ export default class DiskFileUpload extends Vue {
const name = typeof item.name == "string" ? item.name : JSON.stringify(item.name); const name = typeof item.name == "string" ? item.name : JSON.stringify(item.name);
const editUrl = '/net-disk/editview/' + this.getFolder() + '/' + id + '/' + name + '?authcode=' + item.authcode; const editUrl = '/net-disk/editview/' + this.getFolder() + '/' + id + '/' + name + '?authcode=' + item.authcode;
// TODO:暂时用window.open // TODO:暂时用window.open
window.open(editUrl); safeRedirect(editUrl, { type: '_blank'});
} }
/** /**
......
...@@ -12,3 +12,4 @@ export { UIActionTool } from './uiaction-tool/uiaction-tool'; ...@@ -12,3 +12,4 @@ export { UIActionTool } from './uiaction-tool/uiaction-tool';
export { LoadAppData } from './load-app-data/load-app-data'; export { LoadAppData } from './load-app-data/load-app-data';
export { Interceptors } from './interceptor/interceptor'; export { Interceptors } from './interceptor/interceptor';
export { StudioActionUtil } from './studio-action/StudioActionUtil'; export { StudioActionUtil } from './studio-action/StudioActionUtil';
export { safeRedirect } from './redirect-util/redirect-util';
...@@ -5,6 +5,7 @@ import i18n from '@/locale'; ...@@ -5,6 +5,7 @@ import i18n from '@/locale';
import { Environment } from '@/environments/environment'; import { Environment } from '@/environments/environment';
import { Http } from '../http/http'; import { Http } from '../http/http';
import { Util } from '../util/util'; import { Util } from '../util/util';
import { safeRedirect } from '..';
/** /**
* 拦截器 * 拦截器
...@@ -171,7 +172,7 @@ export class Interceptors { ...@@ -171,7 +172,7 @@ export class Interceptors {
} }
loginurl = `${loginurl}${_url}`; loginurl = `${loginurl}${_url}`;
window.location.href = loginurl; safeRedirect(loginurl, { type: 'href' });
} else { } else {
if (Object.is(this.router.currentRoute.name, 'login')) { if (Object.is(this.router.currentRoute.name, 'login')) {
return; return;
......
import { Environment } from '@/environments/environment';
/**
* @description 计算跳转路径是否在白名单中
* @param {string} url
* @returns {*} {boolean}
*/
const isAllowed = (url: string): boolean => {
if (!url) return false;
const { protocol, hostname, origin } = new URL(url, window.location.origin);
// 非http、https、blob:协议直接拦截
if (!['blob:', 'https:', 'http:'].includes(protocol)) return false;
// 相对路径直接放过
if (window.location.origin === origin) {
return true;
}
const allowList: string[] = Environment.redirectWhiteList.split(',');
return allowList.some(rule => {
if (typeof rule === 'string') {
if (rule.includes('*')) {
const reg = new RegExp(`^${rule.replace(/\*/g, '[^/]+')}$`);
return reg.test(hostname);
}
return rule === `${protocol}//${hostname}`;
}
return (rule as RegExp).test(url);
});
};
/**
* 唯一重定向出口
* @param url 目标地址
* @param fallback 不合法时回退地址,默认当前页
*/
export function safeRedirect(
url: string,
options: any = {},
): Window | null | undefined {
try {
if (isAllowed(url)) {
const { type = '_blank' } = options;
if (type === 'href') {
window.location.href = url;
} else {
return window.open(url, type);
}
} else {
console.error(`重定向路径${url}不在白名单中,请确认是否正确!`);
}
} catch {
console.error(`重定向路径${url}不在白名单中,请确认是否正确!`);
}
}
import Vue from 'vue'; import Vue from 'vue';
import { Http } from '@/utils'; import { Http, safeRedirect } from '@/utils';
import { Environment } from '@/environments/environment'; import { Environment } from '@/environments/environment';
import { on } from '@/utils/dom/dom'; import { on } from '@/utils/dom/dom';
...@@ -92,7 +92,7 @@ export class StudioActionUtil { ...@@ -92,7 +92,7 @@ export class StudioActionUtil {
const config: any = await this.getConfig(viewName); const config: any = await this.getConfig(viewName);
if (config) { if (config) {
const context: string = `视图模块:${config.viewmodule}\n视图标识:${config.viewname}\n视图类型:${config.viewtype}\n`; const context: string = `视图模块:${config.viewmodule}\n视图标识:${config.viewname}\n视图类型:${config.viewtype}\n`;
window.open(`${Environment.ProjectUrl}/issues/new?issue[title]=${encodeURIComponent('问题')}&issue[description]=${encodeURIComponent(context)}`, '_blank'); safeRedirect(`${Environment.ProjectUrl}/issues/new?issue[title]=${encodeURIComponent('问题')}&issue[description]=${encodeURIComponent(context)}`, { type: '_blank'});
} }
} }
...@@ -123,7 +123,10 @@ export class StudioActionUtil { ...@@ -123,7 +123,10 @@ export class StudioActionUtil {
console.log("打开sln未支持"); console.log("打开sln未支持");
// this.studioWin = window.open(`${Environment.StudioUrl}?ov=${encodeURIComponent(JSON.stringify(params))}#/common_slnindex/srfkeys=${Environment.SlnId}/sysdesign_psdevslnsysmodeltreeexpview/srfkey=${Environment.SysId}`, '_blank'); // this.studioWin = window.open(`${Environment.StudioUrl}?ov=${encodeURIComponent(JSON.stringify(params))}#/common_slnindex/srfkeys=${Environment.SlnId}/sysdesign_psdevslnsysmodeltreeexpview/srfkey=${Environment.SysId}`, '_blank');
}else{ }else{
this.studioWin = window.open(`${Environment.StudioUrl}?ov=${encodeURIComponent(JSON.stringify(params))}#/common_mosindex/srfkeys=${Environment.SysId}`, '_blank'); const win = safeRedirect(`${Environment.StudioUrl}?ov=${encodeURIComponent(JSON.stringify(params))}#/common_mosindex/srfkeys=${Environment.SysId}`, { type: '_blank'});
if (win) {
this.studioWin = win;
}
} }
} }
} }
......
import qs from 'qs'; import qs from 'qs';
import { Route } from 'vue-router'; import { Route } from 'vue-router';
import Schema from "async-validator"; import Schema from "async-validator";
import { safeRedirect } from '..';
/** /**
* 平台工具类 * 平台工具类
...@@ -59,7 +60,7 @@ export class Util { ...@@ -59,7 +60,7 @@ export class Util {
*/ */
public static processResult(o: any = {}): void { public static processResult(o: any = {}): void {
if (o.url != null && o.url !== '') { if (o.url != null && o.url !== '') {
window.location.href = o.url; safeRedirect(o.url, { type: 'href' });
} }
if (o.code != null && o.code !== '') { if (o.code != null && o.code !== '') {
// tslint:disable-next-line:no-eval // tslint:disable-next-line:no-eval
...@@ -80,7 +81,7 @@ export class Util { ...@@ -80,7 +81,7 @@ export class Util {
* @memberof Util * @memberof Util
*/ */
public static download(url: string): void { public static download(url: string): void {
window.open(url, '_blank'); safeRedirect(url, { type: '_blank'});
} }
/** /**
......
Markdown 格式
0% or
您添加了 0 到此讨论。请谨慎行事。
先完成此消息的编辑!
想要评论请 注册