spring boot:用spring security加强spring boot admin的安全(spring boot admin 2.3.0 / spring boot 2.3.3)
一,spring boot admin的安全环节:
1,修改context-path,默认时首页就是admin,
我们修改这个地址可以更安全
2,配置ip地址白名单,有ip限制才安全,
我们使用了spring security,
可以在防火墙中也配置上ip限制
3,登录用户有相应的role授权才能访问
4,actuator端也要配置ip/路径/权限
说明:刘宏缔的架构森林是一个专注架构的博客,
网站:https://blog.imgtouch.com
本文: https://blog.imgtouch.com/index.php/2023/05/25/springboot-yong-springsecurity-jia-qiang-springbootadmin-de-an-quan-springbootadmin230springboot233/
对应的源码可以访问这里获取: https://github.com/liuhongdi/
说明:作者:刘宏缔 邮箱: 371125307@qq.com
二,演示项目的相关信息
1,项目地址:
https://github.com/liuhongdi/bootadmin
2,项目功能说明:
演示了spring boot admin 服务端和actuator客户端的安全配置
3,项目结构;如图:
三,配置文件说明
1,admin模块的pom.xml
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!--admin sever--> <dependency> <groupId>de.codecentric</groupId> <artifactId>spring-boot-admin-starter-server</artifactId> <version>2.3.0</version> </dependency> <!-- spring security --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency>
2,actuator模块的pom.xml
<!--admin client--> <dependency> <groupId>de.codecentric</groupId> <artifactId>spring-boot-admin-starter-client</artifactId> <version>2.3.0</version> </dependency> <!--actuator begin--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <!-- spring security --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency>
3,admin模块的application.properties
#admin context-path spring.boot.admin.context-path=/lhdadmin #admin white ip list spring.boot.admin.access.iplist=192.168.3.1,127.0.0.1 #admin status intertal spring.boot.admin.monitor.status-interval=60000ms spring.boot.admin.monitor.status-lifetime=60000ms #error server.error.include-stacktrace=always #error logging.level.org.springframework.web=trace
4,actuator模块的application.properties
#admin url spring.boot.admin.client.url=http://localhost:8080/lhdadmin spring.boot.admin.client.username=lhdadmin spring.boot.admin.client.password=123456 spring.boot.admin.client.connect-timeout=5000ms spring.boot.admin.client.period=60000ms spring.boot.admin.client.instance.metadata.user.name=lhdadmin spring.boot.admin.client.instance.metadata.user.password=123456 #port server.port=8081 #exposure management.endpoints.web.exposure.include=* #路径映射 management.endpoints.web.base-path=/lhdmon #health显示 management.endpoint.health.show-details=always #允许访问的ip列表 management.access.iplist = 127.0.0.1,192.168.1.100,192.168.2.3/24,192.168.1.6,localhost #error server.error.include-stacktrace=always #error logging.level.org.springframework.web=trace
说明:
spring.boot.admin.client.username=lhdadmin
spring.boot.admin.client.password=123456
这两项是用来访问server的账号
spring.boot.admin.client.instance.metadata.user.name=lhdadmin
spring.boot.admin.client.instance.metadata.user.password=123456
这两项是供server访问actuator时使用
spring.boot.admin.client.url=http://localhost:8080/lhdadmin
此处注意使用服务端设置的context-path
四,java代码说明
1,admin模块的application:DemoApplication.java
@SpringBootApplication @EnableAdminServer public class DemoApplication { public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); } }
注意添加了@EnableAdminServer注解,用来启动admin sever
2,admin模块的SecurityConfig.java
@Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Value("${spring.boot.admin.access.iplist}") private String iplist; @Override protected void configure(HttpSecurity http) throws Exception { //得到iplist列表 String iprule = ""; //hasIpAddress('10.0.0.0/16') or hasIpAddress('127.0.0.1/32') String[] splitAddress=iplist.split(","); for(String ip : splitAddress){ if (iprule.equals("")) { iprule = "hasIpAddress('"+ip+"')"; } else { iprule += " or hasIpAddress('"+ip+"')"; } } String adminRule = "hasAnyRole('ADMIN','DEV') and ("+iprule+")"; //login和logout http.formLogin() .loginPage("/lhdadmin/login") .defaultSuccessUrl("/lhdadmin/wallboard") .failureUrl("/login-error.html") .permitAll() .and() .logout().logoutUrl("/lhdadmin/logout").permitAll() .and() .httpBasic(); http.csrf() .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()) .ignoringAntMatchers( "/lhdadmin/**", "/actuator/**" ); //匹配的页面,符合限制才可访问 http.authorizeRequests() .antMatchers("/lhdadmin/login/**","/lhdadmin/assets/**").access(iprule) .antMatchers("/lhdadmin/**").access(adminRule); //剩下的页面,允许访问 http.authorizeRequests().anyRequest().permitAll(); } @Autowired public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { //添加两个账号用来做测试 auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder()) .withUser("lhdadmin") .password(new BCryptPasswordEncoder().encode("123456")) .roles("ADMIN","USER") .and() .withUser("lhduser") .password(new BCryptPasswordEncoder().encode("123456")) .roles("USER"); } }
3,actuator模块的SecurityConfig.java
@Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Value("${management.access.iplist}") private String iplist; @Override protected void configure(HttpSecurity http) throws Exception { //得到iplist列表 String iprule = ""; String[] splitAddress=iplist.split(","); for(String ip : splitAddress){ if (iprule.equals("")) { iprule = "hasIpAddress('"+ip+"')"; } else { iprule += " or hasIpAddress('"+ip+"')"; } } String actuatorRule = "hasAnyRole('ADMIN','DEV') and ("+iprule+")"; //login和logout http.formLogin() .defaultSuccessUrl("/lhdmon") .failureUrl("/login-error.html") .permitAll() .and() .logout() .and() .httpBasic(); //匹配的页面,符合限制才可访问 http.authorizeRequests() .antMatchers("/lhdmon/**").access(actuatorRule); //剩下的页面,允许访问 http.authorizeRequests().anyRequest().permitAll(); } @Autowired public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { //添加两个账号用来做测试 auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder()) .withUser("lhdadmin") .password(new BCryptPasswordEncoder().encode("123456")) .roles("ADMIN","USER") .and() .withUser("lhduser") .password(new BCryptPasswordEncoder().encode("123456")) .roles("USER"); } }
五,测试效果
1,spring boot admin 非授权ip地址访问
http://192.168.3.182:8080/lhdadmin/wallboard
登录后返回:
2,spring boot admin 非授权账号访问
http://127.0.0.1:8080/lhdadmin/login
页面:用lhduser登录
lhduser这个账号无权访问
3,spring boot admin从授权ip用有授权账号登录:
http://127.0.0.1:8080/lhdadmin/login
用lhdadmin这个账号登录:
跳转到了wallboard
点击进入:
六,查看spring boot的版本
. ____ _ __ _ _ /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \\/ ___)| |_)| | | | | || (_| | ) ) ) ) ' |____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot :: (v2.3.3.RELEASE)