当前位置: 首页 > 知识库问答 >
问题:

如何保护@ConfigurationProperties类免受更改?

越姚石
2023-03-14

要使用@ConfigurationProperties注释,必须创建一个包含getters和setters的类:

@ConfigurationProperties(prefix = "some")
public class PropertiesConfig {
    private boolean debug;

    public boolean isDebug() {
        return debug;
    }

    public void setDebug(boolean debug) {
        this.debug = debug;
    }
}

但这会导致有人试图通过调用以下命令来修改此值:

@Autowire
private PropertiesConfig config;        
//....

config.setDebug(true);

有没有一种方法可以创建@ConfigurationProperties注释类,而不使用setter和外部解析器/读取器类?

共有3个答案

马坚
2023-03-14

从Spring Boot 2.2中,终于可以定义用@ConfigurationProperties装饰的不可变类。
留档显示了一个例子。
你只需要声明一个构造函数与字段绑定(而不是setter方式):

@ConstructorBinding
@ConfigurationProperties(prefix = "some")
public class PropertiesConfig {
    private boolean debug;

    public AcmeProperties(boolean enabled) {
        this.enabled = enabled;   
    }

    public boolean isDebug() {
        return debug;
    }

}

注意1:您必须定义一个且仅有一个带有绑定参数的构造函数:

在此设置中,必须使用要绑定的属性列表定义一个构造函数,并且只能定义一个构造函数,并且不能绑定构造函数中的属性以外的其他属性。

注2:引入了@DefaultValue来定义不可变属性绑定的默认值。

可以使用@DefaultValue指定默认值,并且将应用相同的转换服务来强制将String值转换为缺失属性的目标类型。

以下是从官方文档中获得的更详细示例:

import java.net.InetAddress;
import java.util.List;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.DefaultValue;
import org.springframework.boot.context.properties.ConstructorBinding;

@ConstructorBinding
@ConfigurationProperties("acme")
public class AcmeProperties {

    private final boolean enabled;

    private final InetAddress remoteAddress;

    private final Security security;

    public AcmeProperties(boolean enabled, InetAddress remoteAddress, Security security) {
        this.enabled = enabled;
        this.remoteAddress = remoteAddress;
        this.security = security;
    }

    public boolean isEnabled() { ... }

    public InetAddress getRemoteAddress() { ... }

    public Security getSecurity() { ... }

    public static class Security {

        private final String username;

        private final String password;

        private final List<String> roles;

        public Security(String username, String password,
                @DefaultValue("USER") List<String> roles) {
            this.username = username;
            this.password = password;
            this.roles = roles;
        }

        public String getUsername() { ... }

        public String getPassword() { ... }

        public List<String> getRoles() { ... }

    }

}
韦安顺
2023-03-14

像这样的东西工作正常

@Configuration
class MyAppPropertiesConfiguration {

    @Bean
    @ConfigurationProperties(prefix = "some")
    public PropertiesConfig propertiesConfig () {
        return new PropertiesConfigImpl();
    }

    public interface PropertiesConfig {
            public boolean isDebug();
    }

    private static class PropertiesConfigImpl implements PropertiesConfig {
        private boolean debug;

        @Override
        public boolean isDebug() {
            return debug;
        }

        public void setDebug(boolean debug) {
            this.debug = debug;
        }
    }
}

然后呢

@Autowired PropertiesConfig properties;
楚灿
2023-03-14

一种尽可能少使用样板代码的方法是只使用带有getter的接口

public interface AppProps {
    String getNeededProperty();
}

在Lombok的@Getter@Setter注释的帮助下,在实现中摆脱样板文件的Getter和Setter:

@ConfigurationProperties(prefix = "props")
@Getter
@Setter
public class AppPropsImpl implements AppProps {
    private String neededProperty;
}

然后,对于Bean BO只能通过接口访问其他bean,可以将其标记为<代码> @组件< /代码>,或者在主应用程序类上使用<代码> @ EnablCon图形属性(AppPrimSpl.class)< /Cl>,将其放入一个将通过接口公开的配置:

@Configuration
@EnableConfigurationProperties
public class PropsConfiguration  {
    @Bean
    public AppProps appProps(){
        return new AppPropsImpl();
    }
}

现在这个bean只能通过使用接口注入,这使得setters对其他bean不可用:

public class ApplicationLogicBean {
    @Autowired
    AppProps props;

    public void method(){
        log.info("Got " + props.getNeededProperty());
    }
}

使用Spring靴1.5.3和Lombok 1.16.16进行测试。

 类似资料:
  • 问题内容: 关键字授予对相同包和子类(http://java.sun.com/docs/books/tutorial/java/javaOO/accesscontrol.html)中的类的访问权限。 现在,每个类都有一个超类(http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Object.html)。 因此,我得出结论,即使每个类都可以访问的方法。

  • 为了防止我们的网络在预连接攻击和获取访问部分中解释的先前攻击破解方法,我们需要访问路由器的设置页面。每个路由器都有一个web页面,我们可以在页面中修改路由器的设置,它通常位于路由器的IP上。首先,获得我们自己的计算机的IP,为此运行命令。如下面的屏幕截图所示,突出显示的部分是计算机的IP: 现在打开浏览器并访问:。对于此示例,计算机的IP为。通常,路由器的IP是子网的第一个IP。目前,它是,我们只

  • 问题内容: 我正在研究使用SQL LocalDB作为客户端数据库,它将替代.net 4中开发的内部应用程序中的当前SQL CE 3.5数据库。 我遇到了一个不确定的问题,那就是LocalDB实例的安全设置。 如果我在.net中设置了一个脚本来创建一个私有LocalDB实例,例如(localdb)\ T1,然后在该实例中创建了一个新数据库,并添加了一个SQL用户帐户+密码(非域帐户),如何停止本地使

  • 问题内容: 我刚刚读了有关zip炸弹的信息,即包含大量高度可压缩数据的zip文件(00000000000000000 …)。 打开后,它们将填充服务器的磁盘。 如何解压缩一个zip炸弹, 然后再将其 解压缩? 更新 你能告诉我这是如何用Python或Java完成的吗? 问题答案: 在Python中尝试一下:

  • 最近,我一直在使用AWS API gateway,在那里我创建了一个API,并用API key和Cognito(OAuth)保护它。 有一天,我发现我的API被访问了10K次,但失败了,因为攻击者没有访问它的权限。 任何帮助都很感激...

  • 问题内容: 我想保护某些行以免被删除,我更喜欢使用触发器而不是应用程序的逻辑来做到这一点。我正在使用MySQL数据库。 我想到的是: 但是当我使用delete时给了我一个错误: 还有另一种方法可以做这样的事情吗? 问题答案: 一种解决方案是创建一个具有权限表外键的子表,并添加引用行以引用要阻止其删除的各个行。 现在,您无法从ID为1234的权限中删除该行,因为它会违反外键依赖性。 如果您确实想使用