作者 RuoYi

升级spring-security到安全版本,防止漏洞风险

@@ -19,6 +19,7 @@ @@ -19,6 +19,7 @@
19 <java.version>1.8</java.version> 19 <java.version>1.8</java.version>
20 <maven-jar-plugin.version>3.1.1</maven-jar-plugin.version> 20 <maven-jar-plugin.version>3.1.1</maven-jar-plugin.version>
21 <spring-framework.version>5.3.33</spring-framework.version> 21 <spring-framework.version>5.3.33</spring-framework.version>
  22 + <spring-security.version>5.7.12</spring-security.version>
22 <druid.version>1.2.23</druid.version> 23 <druid.version>1.2.23</druid.version>
23 <bitwalker.version>1.21</bitwalker.version> 24 <bitwalker.version>1.21</bitwalker.version>
24 <swagger.version>3.0.0</swagger.version> 25 <swagger.version>3.0.0</swagger.version>
@@ -45,6 +46,15 @@ @@ -45,6 +46,15 @@
45 <scope>import</scope> 46 <scope>import</scope>
46 </dependency> 47 </dependency>
47 48
  49 + <!-- SpringSecurity的依赖配置-->
  50 + <dependency>
  51 + <groupId>org.springframework.security</groupId>
  52 + <artifactId>spring-security-bom</artifactId>
  53 + <version>${spring-security.version}</version>
  54 + <type>pom</type>
  55 + <scope>import</scope>
  56 + </dependency>
  57 +
48 <!-- SpringBoot的依赖配置--> 58 <!-- SpringBoot的依赖配置-->
49 <dependency> 59 <dependency>
50 <groupId>org.springframework.boot</groupId> 60 <groupId>org.springframework.boot</groupId>
@@ -2,16 +2,17 @@ package com.ruoyi.framework.config; @@ -2,16 +2,17 @@ package com.ruoyi.framework.config;
2 2
3 import org.springframework.beans.factory.annotation.Autowired; 3 import org.springframework.beans.factory.annotation.Autowired;
4 import org.springframework.context.annotation.Bean; 4 import org.springframework.context.annotation.Bean;
  5 +import org.springframework.context.annotation.Configuration;
5 import org.springframework.http.HttpMethod; 6 import org.springframework.http.HttpMethod;
6 import org.springframework.security.authentication.AuthenticationManager; 7 import org.springframework.security.authentication.AuthenticationManager;
7 -import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;  
8 -import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; 8 +import org.springframework.security.authentication.ProviderManager;
  9 +import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
  10 +import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
9 import org.springframework.security.config.annotation.web.builders.HttpSecurity; 11 import org.springframework.security.config.annotation.web.builders.HttpSecurity;
10 -import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;  
11 -import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer;  
12 import org.springframework.security.config.http.SessionCreationPolicy; 12 import org.springframework.security.config.http.SessionCreationPolicy;
13 import org.springframework.security.core.userdetails.UserDetailsService; 13 import org.springframework.security.core.userdetails.UserDetailsService;
14 import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; 14 import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
  15 +import org.springframework.security.web.SecurityFilterChain;
15 import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; 16 import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
16 import org.springframework.security.web.authentication.logout.LogoutFilter; 17 import org.springframework.security.web.authentication.logout.LogoutFilter;
17 import org.springframework.web.filter.CorsFilter; 18 import org.springframework.web.filter.CorsFilter;
@@ -25,8 +26,9 @@ import com.ruoyi.framework.security.handle.LogoutSuccessHandlerImpl; @@ -25,8 +26,9 @@ import com.ruoyi.framework.security.handle.LogoutSuccessHandlerImpl;
25 * 26 *
26 * @author ruoyi 27 * @author ruoyi
27 */ 28 */
28 -@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)  
29 -public class SecurityConfig extends WebSecurityConfigurerAdapter 29 +@EnableMethodSecurity(prePostEnabled = true, securedEnabled = true)
  30 +@Configuration
  31 +public class SecurityConfig
30 { 32 {
31 /** 33 /**
32 * 自定义用户认证逻辑 34 * 自定义用户认证逻辑
@@ -65,16 +67,15 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter @@ -65,16 +67,15 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter
65 private PermitAllUrlProperties permitAllUrl; 67 private PermitAllUrlProperties permitAllUrl;
66 68
67 /** 69 /**
68 - * 解决 无法直接注入 AuthenticationManager  
69 - *  
70 - * @return  
71 - * @throws Exception 70 + * 身份验证实现
72 */ 71 */
73 @Bean 72 @Bean
74 - @Override  
75 - public AuthenticationManager authenticationManagerBean() throws Exception 73 + public AuthenticationManager authenticationManager()
76 { 74 {
77 - return super.authenticationManagerBean(); 75 + DaoAuthenticationProvider daoAuthenticationProvider = new DaoAuthenticationProvider();
  76 + daoAuthenticationProvider.setUserDetailsService(userDetailsService);
  77 + daoAuthenticationProvider.setPasswordEncoder(bCryptPasswordEncoder());
  78 + return new ProviderManager(daoAuthenticationProvider);
78 } 79 }
79 80
80 /** 81 /**
@@ -92,40 +93,39 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter @@ -92,40 +93,39 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter
92 * rememberMe | 允许通过remember-me登录的用户访问 93 * rememberMe | 允许通过remember-me登录的用户访问
93 * authenticated | 用户登录后可访问 94 * authenticated | 用户登录后可访问
94 */ 95 */
95 - @Override  
96 - protected void configure(HttpSecurity httpSecurity) throws Exception 96 + @Bean
  97 + protected SecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Exception
97 { 98 {
98 - // 注解标记允许匿名访问的url  
99 - ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry registry = httpSecurity.authorizeRequests();  
100 - permitAllUrl.getUrls().forEach(url -> registry.antMatchers(url).permitAll());  
101 -  
102 - httpSecurity 99 + return httpSecurity
103 // CSRF禁用,因为不使用session 100 // CSRF禁用,因为不使用session
104 - .csrf().disable() 101 + .csrf(csrf -> csrf.disable())
105 // 禁用HTTP响应标头 102 // 禁用HTTP响应标头
106 - .headers().cacheControl().disable().and() 103 + .headers((headersCustomizer) -> {
  104 + headersCustomizer.cacheControl(cache -> cache.disable()).frameOptions(options -> options.sameOrigin());
  105 + })
107 // 认证失败处理类 106 // 认证失败处理类
108 - .exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and() 107 + .exceptionHandling(exception -> exception.authenticationEntryPoint(unauthorizedHandler))
109 // 基于token,所以不需要session 108 // 基于token,所以不需要session
110 - .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()  
111 - // 过滤请求  
112 - .authorizeRequests() 109 + .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
  110 + // 注解标记允许匿名访问的url
  111 + .authorizeHttpRequests((requests) -> {
  112 + permitAllUrl.getUrls().forEach(url -> requests.antMatchers(url).permitAll());
113 // 对于登录login 注册register 验证码captchaImage 允许匿名访问 113 // 对于登录login 注册register 验证码captchaImage 允许匿名访问
114 - .antMatchers("/login", "/register", "/captchaImage").permitAll() 114 + requests.antMatchers("/login", "/register", "/captchaImage").permitAll()
115 // 静态资源,可匿名访问 115 // 静态资源,可匿名访问
116 .antMatchers(HttpMethod.GET, "/", "/*.html", "/**/*.html", "/**/*.css", "/**/*.js", "/profile/**").permitAll() 116 .antMatchers(HttpMethod.GET, "/", "/*.html", "/**/*.html", "/**/*.css", "/**/*.js", "/profile/**").permitAll()
117 .antMatchers("/swagger-ui.html", "/swagger-resources/**", "/webjars/**", "/*/api-docs", "/druid/**").permitAll() 117 .antMatchers("/swagger-ui.html", "/swagger-resources/**", "/webjars/**", "/*/api-docs", "/druid/**").permitAll()
118 // 除上面外的所有请求全部需要鉴权认证 118 // 除上面外的所有请求全部需要鉴权认证
119 - .anyRequest().authenticated()  
120 - .and()  
121 - .headers().frameOptions().disable(); 119 + .anyRequest().authenticated();
  120 + })
122 // 添加Logout filter 121 // 添加Logout filter
123 - httpSecurity.logout().logoutUrl("/logout").logoutSuccessHandler(logoutSuccessHandler); 122 + .logout(logout -> logout.logoutUrl("/logout").logoutSuccessHandler(logoutSuccessHandler))
124 // 添加JWT filter 123 // 添加JWT filter
125 - httpSecurity.addFilterBefore(authenticationTokenFilter, UsernamePasswordAuthenticationFilter.class); 124 + .addFilterBefore(authenticationTokenFilter, UsernamePasswordAuthenticationFilter.class)
126 // 添加CORS filter 125 // 添加CORS filter
127 - httpSecurity.addFilterBefore(corsFilter, JwtAuthenticationTokenFilter.class);  
128 - httpSecurity.addFilterBefore(corsFilter, LogoutFilter.class); 126 + .addFilterBefore(corsFilter, JwtAuthenticationTokenFilter.class)
  127 + .addFilterBefore(corsFilter, LogoutFilter.class)
  128 + .build();
129 } 129 }
130 130
131 /** 131 /**
@@ -136,13 +136,4 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter @@ -136,13 +136,4 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter
136 { 136 {
137 return new BCryptPasswordEncoder(); 137 return new BCryptPasswordEncoder();
138 } 138 }
139 -  
140 - /**  
141 - * 身份认证接口  
142 - */  
143 - @Override  
144 - protected void configure(AuthenticationManagerBuilder auth) throws Exception  
145 - {  
146 - auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder());  
147 - }  
148 } 139 }