一,druid的安全保障有哪些環節要注意?
1,druid ui的訪問要有ip地址限制
2,用戶必須要有相應的權限才能訪問druid
3,關閉重置功能
說明:stat-view-servlet.url-pattern的配置應用時會報錯,
如果bug修改了,使用這個功能會更安全
說明:劉宏締的架構森林是一個專注架構的博客,地址:https://www.cnblogs.com/architectforest
對應的源碼可以訪問這里獲取: https://github.com/liuhongdi/
說明:作者:劉宏締 郵箱: 371125307@qq.com
二,演示項目的相關信息
1,項目地址:
https://github.com/liuhongdi/druidsecurity
2,項目功能說明:
演示了druid的安全配置
3,項目結構:如圖:
三,配置文件說明
1,pom.xml
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <exclusions> <exclusion> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-logging</artifactId> </exclusion> </exclusions> </dependency> <!--druid begin--> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid-spring-boot-starter</artifactId> <version>1.1.22</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-log4j2</artifactId> </dependency> <dependency> <groupId>com.lmax</groupId> <artifactId>disruptor</artifactId> <version>3.4.2</version> </dependency> <!--mybatis begin--> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>2.1.3</version> </dependency> <!--mysql begin--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency> <!-- spring security --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency>
2,application.properties
#error server.error.include-stacktrace=always #error logging.level.org.springframework.web=trace # 數據源基本配置 spring.datasource.username = root spring.datasource.password = lhddemo spring.datasource.driver-class-name = com.mysql.cj.jdbc.Driver spring.datasource.url = jdbc:mysql://127.0.0.1:3306/store?serverTimezone=UTC spring.datasource.type = com.alibaba.druid.pool.DruidDataSource # Druid數據源配置 spring.datasource.druid.initialSize = 5 spring.datasource.druid.minIdle = 5 spring.datasource.druid.maxActive = 20 spring.datasource.druid.maxWait = 60000 spring.datasource.druid.timeBetweenEvictionRunsMillis = 60000 spring.datasource.druid.minEvictableIdleTimeMillis = 300000 spring.datasource.druid.validationQuery = SELECT 1 FROM DUAL spring.datasource.druid.testWhileIdle = true spring.datasource.druid.testOnBorrow = false spring.datasource.druid.testOnReturn = false spring.datasource.druid.poolPreparedStatements = true # 配置監控統計攔截的filters,去掉后監控界面sql無法統計,'wall'用於防火牆 spring.datasource.druid.filters = stat,wall,log4j2 spring.datasource.druid.maxPoolPreparedStatementPerConnectionSize = 20 spring.datasource.druid.useGlobalDataSourceStat = true spring.datasource.druid.connectionProperties = druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500 #druid sql firewall monitor spring.datasource.druid.filter.wall.enabled=true #druid sql monitor spring.datasource.druid.filter.stat.enabled=true spring.datasource.druid.filter.stat.log-slow-sql=true spring.datasource.druid.filter.stat.slow-sql-millis=10000 spring.datasource.druid.filter.stat.merge-sql=true #druid uri monitor spring.datasource.druid.web-stat-filter.enabled=true spring.datasource.druid.web-stat-filter.url-pattern=/* spring.datasource.druid.web-stat-filter.exclusions=*.js,*.gif,*.jpg,*.bmp,*.png,*.css,*.ico,/druid/* #druid session monitor spring.datasource.druid.web-stat-filter.session-stat-enable=true spring.datasource.druid.web-stat-filter.profile-enable=true #druid spring monitor spring.datasource.druid.aop-patterns=com.druid.* #monintor #druid login user config spring.datasource.druid.stat-view-servlet.enabled=true #使重置功能不起作用 spring.datasource.druid.stat-view-servlet.reset-enable=false #spring.datasource.druid.stat-view-servlet.url-pattern=/abcd/* spring.datasource.druid.stat-view-servlet.login-username=root spring.datasource.druid.stat-view-servlet.login-password=root # IP白名單 (沒有配置或者為空,則允許所有訪問) spring.datasource.druid.stat-view-servlet.allow = 127.0.0.1,192.168.1.1 # IP黑名單 (存在共同時,deny優先於allow) spring.datasource.druid.stat-view-servlet.deny = 192.168.10.1 #mybatis mybatis.mapper-locations=classpath:/mapper/*Mapper.xml mybatis.type-aliases-package=com.example.demo.mapper mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl logging.config = classpath:log4j2.xml
說明:以下是安全配置的重點
#使重置功能不起作用
spring.datasource.druid.stat-view-servlet.reset-enable=false
#配置訪問監控view的用戶名密碼
spring.datasource.druid.stat-view-servlet.login-username=root
spring.datasource.druid.stat-view-servlet.login-password=root
# IP白名單 (沒有配置或者為空,則允許所有訪問)
spring.datasource.druid.stat-view-servlet.allow = 127.0.0.1,192.168.1.1
# IP黑名單 (存在共同時,deny優先於allow)
spring.datasource.druid.stat-view-servlet.deny = 192.168.10.1
四,java代碼說明:
1,SecurityConfig.java
@Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { //針對druid的ui,關閉csrf,否則會無法登錄 http.csrf().ignoringAntMatchers("/druid/**"); //login和logout http.formLogin() .defaultSuccessUrl("/goods/session") .failureUrl("/login-error.html") .permitAll() .and() .logout(); //指定訪問druid的role String druidRule = "hasAnyRole('ADMIN','DEV')"; //匹配的頁面,符合限制才可訪問 http.authorizeRequests() .antMatchers("/druid/**").access(druidRule) .antMatchers("/goods/**").hasAnyRole("ADMIN","DEV","USER"); //剩下的頁面,允許訪問 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"); } }
說明:
http.csrf().ignoringAntMatchers("/druid/**");
針對druid關閉csrf,否則會導致無法登錄,其他頁面不受影響
antMatchers("/druid/**").access(druidRule)
指定了訪問druid監控view的規則
2,GoodsController.java
@Controller @RequestMapping("/goods") public class GoodsController { @Resource private GoodsMapper goodsMapper; //商品詳情 參數:商品id @GetMapping("/goodsinfo") @ResponseBody public Goods goodsInfo(@RequestParam(value="goodsid",required = true,defaultValue = "0") Long goodsId) { Goods goods = goodsMapper.selectOneGoods(goodsId); return goods; } //打印當前登錄用戶的session @GetMapping("/session") @ResponseBody public String session() { HttpSession session = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest().getSession(); Enumeration e = session.getAttributeNames(); String s = ""; while( e.hasMoreElements()) { String sessionName=(String)e.nextElement(); s += "name="+sessionName+";<br/>"; s += "value="+session.getAttribute(sessionName)+";"; } return s; } }
3,GoodsMapper.java,GoodsMapper.xml,Goods.java等用來演示通過druid訪問數據源,不再貼出,
大家可訪問github.com查看
五,效果測試
1,使用無權限的用戶登錄后訪問
用lhduser登錄
session信息中可以看到授權的角色是:ROLE_USER
訪問druid:
因為沒有權限,我們看到了報錯信息
2,使用有權限的用戶登錄后訪問
用lhdadmin登錄,查看session:
查看druid,先用配置的賬號root登錄
可以正常訪問:
3,從未授權的ip訪問:注意替換成自己應用所在的ip
http://192.168.3.182:8080/druid
用有權限的賬號lhdadmin登錄,
返回:
可見既使有權限訪問,但如果ip未加入白名單也會報錯
六,查看spring boot的版本
. ____ _ __ _ _ /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \\/ ___)| |_)| | | | | || (_| | ) ) ) ) ' |____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot :: (v2.3.3.RELEASE)