`
QING____
  • 浏览: 2251313 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

springboot中endpoint安全控制

    博客分类:
  • JAVA
 
阅读更多

     springboot中endpoint的安全访问,需要谨慎设计,endpoint可以暴露很多有用的信息,这对外部数据采集器来说非常便捷,但是潜在也引入了安全问题,稍有不慎可能被非法访问。本文基于springboot2,基于spring-security来认证endpoint的访问授权。

 

    在springboot2之后,health和info接口将是公开的,其他endpoint将默认在security的控制之下,不允许被访问,如果需要访问,则必须接入security。本文描述,如果将health和info接口继续保持公开(当然也可以安全控制)、其他endpoint需要授权才能访问,此外web项目的其他接口则可以正常访问。

 

    1)将spring-security(或者其starter)加入classpath。

    2)基于security实现httpBasic授权认证,保护其他endpoint。

    

    springboot2默认实现,有些不妥之处,一旦引入security,不仅endpoint被防护,web项目的其他接口也被拦截,这一点需要重新设计。我们通过实现自定义的security配置,并覆盖原有安全配置。

 

一、pom.xml

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-autoconfigure-processor</artifactId>
    <optional>true</optional>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>

 

二、Environment设置

import org.apache.commons.lang3.RandomStringUtils;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.actuate.autoconfigure.security.servlet.ManagementWebSecurityAutoConfiguration;
import org.springframework.boot.env.EnvironmentPostProcessor;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.MapPropertySource;
import org.springframework.core.env.MutablePropertySources;

import java.util.Map;
import java.util.TreeMap;

/**
 * @author liuguanqing
 * created 2018/11/2 3:32 PM
 * 调整优化环境变量,对于框架会默认覆盖一些环境变量,此时我们需要在processor中执行
 * 我们不再需要使用单独的yml文件来解决此问题。原则:
 * 1)所有设置为系统属性的,初衷为"对系统管理员可见"、"对外部接入组件可见"(比如starter或者日志组件等)
 * 2)对设置为lastSource,表示"当用户没有通过yml"配置选项时的默认值--担保策略。
 **/
public class MeteorEnvironmentPostProcessor implements EnvironmentPostProcessor {

    //可以被application覆盖的配置,此处作为默认担保
    private static final Map<String, Object> lastSource = new TreeMap<>();

    //框架限定,不能被覆盖或者外部指定无效的配置
    private static final Map<String,Object> firstSource = new TreeMap<>();

    private static final String NAME_FIRST = "CUSTOMIZE_FIRST";

    private static final String NAME_LAST = "CUSTOMIZE_LAST";


    @Override
    public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
        MutablePropertySources propertySources = environment.getPropertySources();
        //已装载,则中断
        if (propertySources.contains(NAME_FIRST) || propertySources.contains(NAME_LAST)) {
            return;
        }

        resolveSecurity(environment);
        resolveManagement(environment);

        MapPropertySource lastPropertySource = new MapPropertySource(CONTEXT_NAME_LAST, lastSource);
        propertySources.addLast(lastPropertySource);

        MapPropertySource firstPropertySource = new MapPropertySource(CONTEXT_NAME_FIRST, firstSource);
        propertySources.addFirst(firstPropertySource);
    }


    private void resolveSecurity(final ConfigurableEnvironment environment) {
        String password = environment.getProperty(PASSWORD);
        if (password == null) {
            password = environment.getProperty("spring.security.user.password");
        }

        if (password == null) {
            password = RandomStringUtils.random(16,true,true);
        }
        firstSource.put("spring.security.user.password",password);
        //可被系统管理员查看
        System.setProperty(WEB_SECURITY_PASSWORD_SP_KEY,password);

        //覆盖
        firstSource.put("spring.security.user.name","application");
        lastSource.put("spring.security.user.roles","application");
    }

    private void resolveManagement(final ConfigurableEnvironment environment) {
        //有关Endpoints安全问题
        String excludes = environment.getProperty("spring.autoconfigure.exclude");
        StringBuilder sb = new StringBuilder();
        if(excludes != null) {
            sb.append(",");
        }
        //关闭spring-boot默认的security配置
        sb.append(ManagementWebSecurityAutoConfiguration.class.getName());
        firstSource.put("spring.autoconfigure.exclude",sb.toString());

        //默认全部关闭
        firstSource.put("management.endpoints.enabled-by-default",false);
        firstSource.put("management.endpoints.jmx.domain",ContextConstants.JMX_DOMAIN);
        firstSource.put("management.endpoints.jmx.exposure.include","*");

        firstSource.put("management.endpoints.web.exposure.include","*");
        firstSource.put("management.endpoints.web.exposure.exclude","shutdown,threaddump,heapdump");
        firstSource.put("management.endpoints.web.base-path","/actuator");

        firstSource.put("management.endpoint.health.enabled",true);
        lastSource.put("management.endpoint.health.show-details","never");

        firstSource.put("management.endpoint.info.enabled",true);
        firstSource.put("management.endpoint.mappings.enabled",true);
        firstSource.put("management.endpoint.metrics.enabled",true);
        firstSource.put("management.endpoint.env.enabled",true);
        firstSource.put("management.endpoint.configprops.enabled",true);
        firstSource.put("management.endpoint.beans.enabled",true);
        firstSource.put("management.endpoint.httptrace.enabled",true);
    }
}

 

    有时候,我们不希望用户干扰有关security和endpoint的参数配置,比如用户好奇的打开或者关闭了一些“不安全的”endpoint,将可能导致一些严重的事故,我们需要在项目框架中集成有关Environment的处理器,强制覆盖有关配置。

    比如本文,有关endpoint的开关配置是用户无法配置的(不生效),我们也强制为项目设定security的用户名和密码。

    需要注意,这个EnvironmentPostProcessor会被执行两次,分别为spring环境和servlet环境,此时Environment类型不同,所以如果你在Porcessor中处理有关“字符串拼接”、“累加”等操作时需要慎重。

 

三、自定义Security配置

/**
 * created 2018/11/5 2:34 PM
 * 用于保护endpoint不被非法访问
 **/
@Order(99)
public class MeteorWebSecurityConfigurer extends WebSecurityConfigurerAdapter {
    @Override
    public void configure(WebSecurity web) throws Exception {
        //普通web资源
    }

    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .requestMatchers(
                        EndpointRequest.to(MetricsEndpoint.class,
                                EnvironmentEndpoint.class,
                                HttpTraceEndpoint.class,
                                ConfigurationPropertiesReportEndpoint.class,
                                BeansEndpoint.class,
                                MappingsEndpoint.class)).hasRole("application").anyRequest()
                .permitAll().and()
                .httpBasic();

    }
}

 

    安全控制策略需要特别注意,如果上下文中有多个WebSecurityConfigurerAdapter,必须为每个实现声明@Order和指定顺序且order不能重复,此外@Order只能声明在类上,不能声明在@Bean。

    对于springboot2而言,默认已经提供了一个有关endpoint的安全控制类:ManagementWebSecurityAutoConfiguration,这个类的加载条件也“如果上下文中没有提供“WebSecurityConfigurerAdapter”实现,ManagementWebSecurityAutoConfiguration主要是为了将“health和info”可被公开访问、其他接口需要认证授权,为了避免不必要的设计问题,我们强制关闭此类的自动装配(或者开发自定义的WebSecurityConfigurerAdapter,且优先级高于100)。

    1)通过@SpringBootApplication(exclude = {ManagementWebSecurityAutoConfiguration.class})。

    2)在yml中显式声明:

spring.autoconfigure.exclude=org.springframework.boot.actuate.autoconfigure.security.servlet.ManagementWebSecurityAutoConfiguration

 

    3)你可以像本文描述,通过上述EnvironmentPostProcessor,强制覆盖“spring.autofigure.exclude”的参数,并追加ManagementWebSecurityAutoConfiguration。

 

    如果你的上下文中,有多个自定义的WebSecurityConfigurerAdapter实现,那么他们的Order必须唯一,否则将会抛出:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration': Injection of autowired dependencies failed; nested exception is java.lang.IllegalStateException: @Order on WebSecurityConfigurers must be unique. Order of 100 was already used on com.example.demo.Application$TestSecurity@54c60202, so it cannot be used on org.springframework.boot.actuate.autoconfigure.security.servlet.ManagementWebSecurityConfigurerAdapter$$EnhancerBySpringCGLIB$$1d8564e5@7889b4b9 too.

 

三、初始化WebSecurityConfigurerAdapter

   @Bean
    public WebSecurityConfigurer meteorWebSecurityConfigurer() {
        return new MeteorWebSecurityConfigurer();
    }

    此代码,可以放在任何被@Configuration修饰的类中,当然也可以为你自定义的AutoConfiguration类中。

 

四、配置Environment处理器(META-INF/spring.factories)

org.springframework.boot.env.EnvironmentPostProcessor=\
com.test.springboot.environment.MeteorEnvironmentPostProcessor

 

五、yml配置

spring:
  security:
    user:
      name: application
      password: ${password:test123}

 

    你可以通过启动时使用“-Dpassword=”来传入密码,这样必要安全,如果未传入,则使用“test123”。

 

六、访问与验证

    此后,我们也已通过postman、浏览器、curl等方式验证安全是否生效:

> curl http://127.0.0.1:8080/actuator/metrics -u application:test123
或者
> curl http://application:test123@127.0.0.1:8080/actuator/metrics
#可以访问
> curl http://127.0.0.1:8080/actuator/health
##无认证可以访问
> curl http://127.0.0.1:8080/index
##无认证可以访问
> curl http://127.0.0.1:8080/actuator/metrics
##401错误

  

分享到:
评论

相关推荐

    springboot整合oss实现文件的上传,查看,删除,下载

    在本文中,我们将深入探讨如何使用SpringBoot与OSS(Object Storage Service)集成,实现...在实际开发中,可以根据业务需求进行定制化改造,如增加权限控制、文件版本管理等功能,进一步提升系统的实用性和安全性。

    详解SpringBoot应用服务启动与安全终止

    @Controller注解表明该类是一个控制器,而@EnableAutoConfiguration注解则表明SpringBoot将根据添加的jar依赖来猜测如何配置Spring。 SpringBoot应用安全终止 SpringBoot应用安全终止是指在SpringBoot应用运行时...

    SpringBoot2.0-Actuator监控参数说明

    - **Endpoint Security**:默认情况下,Actuator端点是开放的,但在生产环境中,为了安全考虑,通常需要进行权限控制,可以通过`management.security.enabled`属性来启用或禁用端点的安全性。 - **自定义Endpoint*...

    springboot2.1.5集成CXF3.2.5,webservice服务端

    在IT行业中,Spring Boot和Apache CXF是两个非常重要的组件,它们在开发高效、轻量级的Web服务中发挥着...在实际开发中,还可以根据需求进一步定制CXF的行为,例如添加安全控制、错误处理等,以满足更复杂的应用场景。

    springboot集成minio完成自己的分布式文件系统

    在实际项目中,你可能还需要考虑其他因素,如文件权限管理、文件版本控制、对象生命周期策略、监控与日志记录等。此外,还可以利用SpringBoot的缓存管理、事务支持等功能,进一步优化系统的性能和稳定性。对于安全...

    springboot mysql jdbc示例

    以下是这个"springboot mysql jdbc示例"中的关键知识点: 1. **Spring Boot**: Spring Boot是Spring框架的一个扩展,它提供了快速开发新Spring应用的方式,通过预设默认配置,减少了常规的Spring应用所需的初始设置...

    全套springboot从零到有

    总之,"全套SpringBoot从零到有"的学习资源可能包括了Spring Boot的安装与配置、核心概念解析、实战案例、异常处理、安全控制、日志管理、单元测试等多个方面的内容。通过系统学习,你将能够熟练地运用Spring Boot来...

    基于SpringBoot 开发理财产品系统.zip

    6. **Actuator**:SpringBoot Actuator提供了一组端点(Endpoint),用于监控和管理应用程序,包括健康检查、指标收集、日志查看等。这对于理解和优化理财系统的运行状态非常有帮助。 7. **Docker化部署**:...

    SpringBoot开发WebService之CXF示例

    在本文中,我们将深入探讨如何使用SpringBoot集成Apache CXF来开发Web服务。SpringBoot以其简洁的配置和快速的应用启动而受到广大开发者的欢迎,而CXF是一个强大的开源框架,用于构建和消费Web服务。结合这两者,...

    springboot-oos.zip

    3. **OSS服务配置**:在SpringBoot应用中,我们需要配置OSS的相关参数,包括访问密钥(AccessKey ID和AccessKey Secret)、Endpoint(OSS服务的访问域名)以及Bucket(存储空间)名称。这些通常在项目的配置文件(如...

    SpringBoot-Learning:springboot 学习

    3. **使用Spring Security扩展**: Spring Security提供了OAuth2的集成,可以轻松添加安全控制。 ## 自定义Endpoint SpringBoot允许你自定义Actuator的Endpoint,以便监控和管理应用的健康状况、指标和其他信息。这...

    SpringBoot整合minio

    本文将详细介绍如何在SpringBoot项目中整合MinIO,帮助开发者实现高效、安全的文件存储功能。 **一、MinIO简介** MinIO是一款高性能、开源的对象存储系统,设计目标是提供简单、快速、安全的数据访问接口。它的...

    springboot-websocket例子

    在Spring Boot中,我们需要配置WebSocket的Endpoint。这通常通过实现`WebSocketHandler`接口或者扩展`TextWebSocketHandler`或`BinaryWebSocketHandler`来完成。此外,还需要在`WebMvcConfigurer`或`...

    SpringBoot 实战 之 优雅终止服务的方法

    在 SpringBoot 官方文档的第 4 部分中介绍了为应用发布生产准备的各种特性,其中,通过 Actuator 的 HTTP Endpoint,开发人员可以方便地对应用的监控与管理。引入指定的 starter 包,并在 application.yml 中打开...

    SpringBoot集成MinIO快速入门Demo

    **SpringBoot集成MinIO快速入门** 在现代的Web开发中,数据存储是一个不可或缺的部分,而文件存储服务在很多场景下都是必要的。...记得在生产环境中,安全总是首要的,确保对敏感信息(如访问密钥)进行妥善管理。

    SpringBoot跨域Jsonp和Cors的方法

    在现代Web开发中,由于浏览器的安全策略,前后端分离的应用常常会遇到跨域问题。同源策略限制了JavaScript从一个源获取另一个源的数据,导致不同域名、端口或协议之间的通信受到阻碍。本文将深入探讨如何在...

    springboot5-webservice

    - Spring Security为SpringBoot应用提供了安全控制,包括身份验证和授权。 - 可以通过`spring-boot-starter-security`启动器添加安全功能,配置基本的用户名/密码登录,或使用OAuth2、JWT等高级认证机制。 7. **...

    springboot配置文件参数列表

    - `management.endpoint.health.show-details`: 控制健康检查详情是否显示。 以上仅列举了部分常用配置项,实际上Spring Boot支持的配置参数远不止这些。通过合理配置这些参数,开发者可以轻松地调整Spring Boot...

    SpringBoot面试专题及答案.pdf

    2. 创建 REST 控制器:创建一个带有 `@RestController` 注解的 Java 类,它表示该类中的方法将返回 JSON 或其他响应格式的数据。例如: ```java import org.springframework.web.bind.annotation.GetMapping; ...

    springboot-API:具有Spring Boot和Java的基本API

    6. **安全控制** - **Spring Security**:Spring Boot 提供对安全的默认配置,可以轻松实现身份验证和授权,如使用 `@Secured` 或 `@PreAuthorize` 注解进行权限控制。 7. **测试** - **Spring Boot 测试支持**:...

Global site tag (gtag.js) - Google Analytics