【问题标题】:How to solve FindBugs DP_DO_INSIDE_DO_PRIVILEGED如何解决 FindBugs DP_DO_INSIDE_DO_PRIVILEGED
【发布时间】:2012-12-26 01:50:45
【问题描述】:

在阅读和扫描旧代码时,我看到了这些代码行:

public static void replaceNull(Object obj)
{
    if (obj == null)
    {
        return;
    }

    Field[] fields = obj.getClass().getDeclaredFields();
    if (fields != null)
    {
        for (Field field : fields)
        {
            field.setAccessible(true);
            Class<?> fieldType = field.getType();
            try
            {
                if (field.get(obj) == null)
                {
                    setDefaultValue(obj, field, fieldType);
                }
            } catch (IllegalArgumentException e)
            {
                logger. error("failed replacing null :"+ e.getMessage(),e);
            } catch (IllegalAccessException e)
            {
                logger. error("failed replacing null :"+ e.getMessage(),e);
            }

        }
    }
}

   private static void setDefaultValue(Object obj, Field field, Class<?> fieldType) throws IllegalAccessException
{
    if (fieldType == String.class)
    {
        field.set(obj, CommonConstants.BLANK);

    } else if (fieldType == Date.class)
    {
        field.set(obj, new Date());
    } else if (fieldType == Long.class)
    {
        field.setLong(obj, 0L);
    } else if (fieldType == Integer.class)
    {
        field.setInt(obj, 0);
    } else if (fieldType == BigDecimal.class)
    {
        field.set(obj, new BigDecimal("0.0"));
    }
}

从程序的流程来看,作者似乎想为对象的所有数据成员创建一个默认值,如果值为空。

在使用 FindBugs 扫描时,findbugs 报告“DP_DO_INSIDE_DO_PRIVILEGED”,并在 setAccessible(true) 上有此描述:

不好的做法 - 调用的方法只能在 doPrivileged 块内调用 插件:findbugs 键:DP_DO_INSIDE_DO_PRIVILEGED 此代码调用需要安全权限检查的方法。如果此代码将被授予安全权限,但可能被没有安全权限的代码调用,则调用需要在 doPrivileged 块内进行。

我的问题为什么这么糟糕?又该如何解决呢?

【问题讨论】:

  • field.setAccessible(true); 需要suppressAccessChecks 权限。您可以通过 AccessController.doPrivileged(...) 将整个代码包装在 PrivilegedAction 中来“解决”该案例。或者忽略来自 FindBugs 的这个警告。并非所有错误/警告在任何情况下都有效。此外,整个函数可能已经被包装,但通常 FindBugs 无法检测到。

标签: java findbugs


【解决方案1】:

来自field#setAccessible(boolean)的Javadocs:

首先,如果有安全管理器,则调用其 checkPermission 方法,并带有 ReflectPermission("suppressAccessChecks") 权限。

如果没有安装SecurityManager,程序将运行良好。但是,假设您的代码是作为共享库编写的,并且恰好被某个设置了安全管理器的模块使用。在这种情况下,field.setAccessible(true) 可能会被拒绝权限,即使您的代码中的此操作和其他操作被视为受信任代码。这就是 FindBugs 发出此警告的原因。

为了保证无论调用者代码的权限如何,field.setAccessible(true) 将始终被授予权限,您可以将语句包装在 AccessController.doPrivileged 中(您必须将 field 设为 final):

AccessController.doPrivileged(new PrivilegedAction() {
    @Override
    public Object run() {
        field.setAccessible(true);
        return null;
    }
});

【讨论】:

    【解决方案2】:

    除了上面接受的答案之外,使用 Java 1.7+ lambda 表达式,同样可以通过以下方式实现:

    AccessController.doPrivileged((PrivilegedAction) () -> {
        field.setAccessible(true);
        return null;
    });
    

    【讨论】:

      猜你喜欢
      • 2011-02-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-05-26
      • 2018-06-01
      相关资源
      最近更新 更多