解决看板模板内的图表存在越权引用的问题

This commit is contained in:
datagear 2020-01-29 23:13:18 +08:00
parent daae61efc7
commit 80a6ac5801
9 changed files with 178 additions and 25 deletions

View File

@ -19,6 +19,7 @@ public interface ChartWidgetSource
*
* @param id
* @return
* @throws Throwable
*/
<T extends RenderContext> ChartWidget<T> getChartWidget(String id);
<T extends RenderContext> ChartWidget<T> getChartWidget(String id) throws Throwable;
}

View File

@ -90,6 +90,8 @@ public abstract class HtmlTplDashboardWidgetRenderer<T extends HtmlRenderContext
public static final String DEFAULT_DASHBOARD_VAR = "dashboard";
public static final String PROPERTY_VALUE_FOR_WIDGET_GET_EXCEPTION = "targetHtmlChartWidgetGetExceptionMessage";
public static final String PROPERTY_VALUE_FOR_WIDGET_NOT_FOUND = "targetHtmlChartWidgetNotFoundMessage";
public static final String PROPERTY_VALUE_FOR_PLUGIN_NULL = "targetHtmlChartWidgePluginNullMessage";
@ -106,6 +108,10 @@ public abstract class HtmlTplDashboardWidgetRenderer<T extends HtmlRenderContext
private HtmlDashboardScriptObjectWriter htmlDashboardScriptObjectWriter = new HtmlDashboardScriptObjectWriter();
private HtmlChartPlugin<HtmlRenderContext> htmlChartPluginForWidgetGetException = new ValueHtmlChartPlugin<HtmlRenderContext>(
StringUtil.firstLowerCase(Global.PRODUCT_NAME_EN) + "HtmlChartPluginForWidgetGetException",
PROPERTY_VALUE_FOR_WIDGET_GET_EXCEPTION);
private HtmlChartPlugin<HtmlRenderContext> htmlChartPluginForWidgetNotFound = new ValueHtmlChartPlugin<HtmlRenderContext>(
StringUtil.firstLowerCase(Global.PRODUCT_NAME_EN) + "HtmlChartPluginForWidgetNotFound",
PROPERTY_VALUE_FOR_WIDGET_NOT_FOUND);
@ -223,6 +229,17 @@ public abstract class HtmlTplDashboardWidgetRenderer<T extends HtmlRenderContext
this.htmlDashboardScriptObjectWriter = htmlDashboardScriptObjectWriter;
}
public HtmlChartPlugin<HtmlRenderContext> getHtmlChartPluginForWidgetGetException()
{
return htmlChartPluginForWidgetGetException;
}
public void setHtmlChartPluginForWidgetGetException(
HtmlChartPlugin<HtmlRenderContext> htmlChartPluginForWidgetGetException)
{
this.htmlChartPluginForWidgetGetException = htmlChartPluginForWidgetGetException;
}
public HtmlChartPlugin<HtmlRenderContext> getHtmlChartPluginForWidgetNotFound()
{
return htmlChartPluginForWidgetNotFound;
@ -612,7 +629,16 @@ public abstract class HtmlTplDashboardWidgetRenderer<T extends HtmlRenderContext
/**
* 获取用于渲染指定ID图表的{@linkplain ChartWidget}
* <p>
* 此方法不会返回{@code null}如果找不到指定ID的{@linkplain ChartWidget}它将返回{@linkplain #htmlChartWidgetForNotFound}
* 此方法不会返回{@code null}
* </p>
* <p>
* 如果没有找到则返回{@linkplain #createHtmlChartWidgetForNotFound(String)}
* </p>
* <p>
* 如果出现异常则返回{@linkplain #createHtmlChartWidgetForGetException(String, Throwable)}
* </p>
* <p>
* 如果{@linkplain HtmlChartWidget#getChartPlugin()}{@code null}则返回{@linkplain #createHtmlChartWidgetForPluginNull(ChartWidget)}
* </p>
*
* @param renderContext
@ -622,7 +648,19 @@ public abstract class HtmlTplDashboardWidgetRenderer<T extends HtmlRenderContext
@SuppressWarnings({ "unchecked", "rawtypes" })
protected HtmlChartWidget<HtmlRenderContext> getHtmlChartWidgetForRender(HtmlRenderContext renderContext, String id)
{
ChartWidget chartWidget = (StringUtil.isEmpty(id) ? null : this.chartWidgetSource.getChartWidget(id));
ChartWidget chartWidget = null;
if (!StringUtil.isEmpty(id))
{
try
{
chartWidget = this.chartWidgetSource.getChartWidget(id);
}
catch(Throwable t)
{
chartWidget = createHtmlChartWidgetForGetException(id, t);
}
}
if (chartWidget == null)
chartWidget = createHtmlChartWidgetForNotFound(id);
@ -633,6 +671,18 @@ public abstract class HtmlTplDashboardWidgetRenderer<T extends HtmlRenderContext
return (HtmlChartWidget<HtmlRenderContext>) chartWidget;
}
protected HtmlChartWidget<HtmlRenderContext> createHtmlChartWidgetForGetException(String exceptionWidgetId,
Throwable t)
{
HtmlChartWidget<HtmlRenderContext> widget = new HtmlChartWidget<HtmlRenderContext>(IDUtil.uuid(),
"HtmlChartWidgetForWidgetGetException", this.htmlChartPluginForWidgetGetException);
widget.addChartPropertyValue(PROPERTY_VALUE_FOR_WIDGET_GET_EXCEPTION,
"Chart '" + (exceptionWidgetId == null ? "" : exceptionWidgetId) + "' exception : " + t.getMessage());
return widget;
}
protected HtmlChartWidget<HtmlRenderContext> createHtmlChartWidgetForNotFound(String notFoundWidgetId)
{
HtmlChartWidget<HtmlRenderContext> widget = new HtmlChartWidget<HtmlRenderContext>(IDUtil.uuid(),

View File

@ -9,6 +9,7 @@ package org.datagear.management.service;
import org.datagear.analysis.support.ChartWidgetSource;
import org.datagear.management.domain.HtmlChartWidgetEntity;
import org.datagear.management.domain.User;
/**
* {@linkplain HtmlChartWidgetEntity}业务服务接口
@ -19,5 +20,76 @@ import org.datagear.management.domain.HtmlChartWidgetEntity;
public interface HtmlChartWidgetEntityService
extends DataPermissionEntityService<String, HtmlChartWidgetEntity>, ChartWidgetSource
{
/**
* {@linkplain ChartWidgetSource}上下文
* <p>
* {@linkplain ChartWidgetSource#getChartWidget(String)}实现方法可以使用此类处理权限
* </p>
*
* @author datagear@163.com
*
*/
class ChartWidgetSourceContext
{
protected static final String NAME_FOR_SERVICE_CONTEXT = ChartWidgetSourceContext.class.getName();
private User user;
public ChartWidgetSourceContext()
{
super();
}
public ChartWidgetSourceContext(User user)
{
super();
this.user = user;
}
public boolean hasUser()
{
return (this.user != null);
}
public User getUser()
{
return user;
}
public void setUser(User user)
{
this.user = user;
}
/**
* 获取当前{@linkplain ChartWidgetSourceContext}线程变量不会返回{@code null}
*
* @return
*/
public static ChartWidgetSourceContext get()
{
ChartWidgetSourceContext context = ServiceContext.get().getValue(NAME_FOR_SERVICE_CONTEXT);
if (context == null)
context = new ChartWidgetSourceContext();
return context;
}
/**
* 设置当前{@linkplain ChartWidgetSourceContext}至线程变量
*
* @param context
*/
public static void set(ChartWidgetSourceContext context)
{
ServiceContext.get().setValue(NAME_FOR_SERVICE_CONTEXT, context);
}
/**
* 移除当前{@linkplain ChartWidgetSourceContext}线程变量
*/
public static void remove()
{
ServiceContext.get().removeValue(NAME_FOR_SERVICE_CONTEXT);
}
}
}

View File

@ -36,5 +36,5 @@ public interface HtmlTplDashboardWidgetEntityService
* @param id
* @return
*/
HtmlTplDashboardWidget<HtmlRenderContext> getHtmlTplDashboardWidget(User user, String id);
HtmlTplDashboardWidgetEntity getHtmlTplDashboardWidget(User user, String id);
}

View File

@ -2,7 +2,7 @@
* Copyright (c) 2018 datagear.tech. All Rights Reserved.
*/
package org.datagear.management.service.impl;
package org.datagear.management.service;
import java.util.HashMap;
import java.util.Map;
@ -58,6 +58,18 @@ public class ServiceContext
return (T) this.values.get(name);
}
/**
* 移除上下文名字值
*
* @param name
* @return
*/
@SuppressWarnings("unchecked")
public <T> T removeValue(String name)
{
return (T) this.values.remove(name);
}
/**
* 获取全部上下文名字值
*

View File

@ -7,6 +7,7 @@ package org.datagear.management.service.impl;
import java.io.Serializable;
import org.datagear.management.domain.Authorization;
import org.datagear.management.service.ServiceContext;
/**
* {@linkplain Authorization}查询上下文

View File

@ -111,9 +111,16 @@ public class HtmlChartWidgetEntityServiceImpl
@SuppressWarnings("unchecked")
@Override
public <T extends RenderContext> ChartWidget<T> getChartWidget(String id)
public <T extends RenderContext> ChartWidget<T> getChartWidget(String id) throws Throwable
{
HtmlChartWidgetEntity entity = getById(id);
ChartWidgetSourceContext context = ChartWidgetSourceContext.get();
HtmlChartWidgetEntity entity = null;
if (context.hasUser())
entity = getById(context.getUser(), id);
else
entity = getById(id);
if (entity == null)
return null;

View File

@ -12,7 +12,6 @@ import java.util.Map;
import org.apache.ibatis.session.SqlSessionFactory;
import org.datagear.analysis.support.html.HtmlRenderContext;
import org.datagear.analysis.support.html.HtmlTplDashboardWidget;
import org.datagear.analysis.support.html.HtmlTplDashboardWidgetFmkRenderer;
import org.datagear.analysis.support.html.HtmlTplDashboardWidgetRenderer;
import org.datagear.management.domain.HtmlChartWidgetEntity;
@ -87,9 +86,9 @@ public class HtmlTplDashboardWidgetEntityServiceImpl
}
@Override
public HtmlTplDashboardWidget<HtmlRenderContext> getHtmlTplDashboardWidget(User user, String id)
public HtmlTplDashboardWidgetEntity getHtmlTplDashboardWidget(User user, String id)
{
HtmlTplDashboardWidget<HtmlRenderContext> dashboard = getById(user, id);
HtmlTplDashboardWidgetEntity dashboard = getById(user, id);
if (dashboard != null)
dashboard.setRenderer(this.htmlTplDashboardWidgetRenderer);

View File

@ -30,6 +30,7 @@ import org.datagear.analysis.support.html.HtmlTplDashboardWidgetRenderer;
import org.datagear.analysis.support.html.HtmlTplDashboardWidgetRenderer.AddPrefixHtmlTitleHandler;
import org.datagear.management.domain.HtmlTplDashboardWidgetEntity;
import org.datagear.management.domain.User;
import org.datagear.management.service.HtmlChartWidgetEntityService.ChartWidgetSourceContext;
import org.datagear.management.service.HtmlTplDashboardWidgetEntityService;
import org.datagear.persistence.PagingData;
import org.datagear.persistence.PagingQuery;
@ -494,33 +495,43 @@ public class DashboardController extends AbstractDataAnalysisController
{
User user = WebUtils.getUser(request, response);
HtmlTplDashboardWidget<HtmlRenderContext> dashboardWidget = this.htmlTplDashboardWidgetEntityService
HtmlTplDashboardWidgetEntity dashboardWidget = this.htmlTplDashboardWidgetEntityService
.getHtmlTplDashboardWidget(user, id);
if (dashboardWidget == null)
throw new RecordNotFoundException();
TemplateDashboardWidgetResManager dashboardWidgetResManager = this.htmlTplDashboardWidgetEntityService
.getHtmlTplDashboardWidgetRenderer().getTemplateDashboardWidgetResManager();
// 上面已确保当前用户对此看板有读权限这里则确保看板创建用户对看板模板内定义的图表有权限
ChartWidgetSourceContext.set(new ChartWidgetSourceContext(dashboardWidget.getCreateUser()));
String responseEncoding = dashboardWidget.getTemplateEncoding();
try
{
TemplateDashboardWidgetResManager dashboardWidgetResManager = this.htmlTplDashboardWidgetEntityService
.getHtmlTplDashboardWidgetRenderer().getTemplateDashboardWidgetResManager();
if (StringUtil.isEmpty(responseEncoding))
responseEncoding = dashboardWidgetResManager.getDefaultEncoding();
String responseEncoding = dashboardWidget.getTemplateEncoding();
response.setCharacterEncoding(responseEncoding);
if (StringUtil.isEmpty(responseEncoding))
responseEncoding = dashboardWidgetResManager.getDefaultEncoding();
Writer out = response.getWriter();
response.setCharacterEncoding(responseEncoding);
HtmlRenderContext renderContext = createHtmlRenderContext(request, createWebContext(request), out);
AddPrefixHtmlTitleHandler htmlTitleHandler = new AddPrefixHtmlTitleHandler(
getMessage(request, "dashboard.show.htmlTitlePrefix", getMessage(request, "app.name")));
HtmlRenderAttributes.setHtmlTitleHandler(renderContext, htmlTitleHandler);
Writer out = response.getWriter();
HtmlDashboard dashboard = dashboardWidget.render(renderContext);
HtmlRenderContext renderContext = createHtmlRenderContext(request, createWebContext(request), out);
AddPrefixHtmlTitleHandler htmlTitleHandler = new AddPrefixHtmlTitleHandler(
getMessage(request, "dashboard.show.htmlTitlePrefix", getMessage(request, "app.name")));
HtmlRenderAttributes.setHtmlTitleHandler(renderContext, htmlTitleHandler);
SessionHtmlDashboardManager dashboardManager = getSessionHtmlDashboardManagerNotNull(request);
dashboardManager.put(dashboard);
HtmlDashboard dashboard = dashboardWidget.render(renderContext);
SessionHtmlDashboardManager dashboardManager = getSessionHtmlDashboardManagerNotNull(request);
dashboardManager.put(dashboard);
}
finally
{
ChartWidgetSourceContext.remove();
}
}
/**