如何解决FindBugs DP_DO_INSIDE_DO_PRIVILEGED

问题描述 投票:0回答:3

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

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 块内进行。

我的问题为什么这么糟糕?那我该怎么解决呢?

java findbugs
3个回答
9
投票

来自

field#setAccessible(boolean)
的 Javadocs:

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

无需安装

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

为了保证

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

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

4
投票

添加到上面接受的答案中,使用 Java 1.7+ lambda 表达式,可以通过以下方式实现相同的效果:

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

0
投票

由于

SecurityManager
AccessController
在 Java 17 中已被弃用并且没有替代品,因此禁用此错误检测应该被认为是安全的。更多详情请参阅官方文档

已弃用,删除:此 API 元素可能会在 未来版本。该类仅与 安全管理器,已弃用并可能会在 未来的版本。因此,这个类也被弃用了 可能会被移除。安全管理器无可替代 或这门课。

© www.soinside.com 2019 - 2024. All rights reserved.