作者 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  
103 - // CSRF禁用,因为不使用session  
104 - .csrf().disable()  
105 - // 禁用HTTP响应标头  
106 - .headers().cacheControl().disable().and()  
107 - // 认证失败处理类  
108 - .exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and()  
109 - // 基于token,所以不需要session  
110 - .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()  
111 - // 过滤请求  
112 - .authorizeRequests() 99 + return httpSecurity
  100 + // CSRF禁用,因为不使用session
  101 + .csrf(csrf -> csrf.disable())
  102 + // 禁用HTTP响应标头
  103 + .headers((headersCustomizer) -> {
  104 + headersCustomizer.cacheControl(cache -> cache.disable()).frameOptions(options -> options.sameOrigin());
  105 + })
  106 + // 认证失败处理类
  107 + .exceptionHandling(exception -> exception.authenticationEntryPoint(unauthorizedHandler))
  108 + // 基于token,所以不需要session
  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()  
115 - // 静态资源,可匿名访问  
116 - .antMatchers(HttpMethod.GET, "/", "/*.html", "/**/*.html", "/**/*.css", "/**/*.js", "/profile/**").permitAll()  
117 - .antMatchers("/swagger-ui.html", "/swagger-resources/**", "/webjars/**", "/*/api-docs", "/druid/**").permitAll()  
118 - // 除上面外的所有请求全部需要鉴权认证  
119 - .anyRequest().authenticated()  
120 - .and()  
121 - .headers().frameOptions().disable();  
122 - // 添加Logout filter  
123 - httpSecurity.logout().logoutUrl("/logout").logoutSuccessHandler(logoutSuccessHandler);  
124 - // 添加JWT filter  
125 - httpSecurity.addFilterBefore(authenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);  
126 - // 添加CORS filter  
127 - httpSecurity.addFilterBefore(corsFilter, JwtAuthenticationTokenFilter.class);  
128 - httpSecurity.addFilterBefore(corsFilter, LogoutFilter.class); 114 + requests.antMatchers("/login", "/register", "/captchaImage").permitAll()
  115 + // 静态资源,可匿名访问
  116 + .antMatchers(HttpMethod.GET, "/", "/*.html", "/**/*.html", "/**/*.css", "/**/*.js", "/profile/**").permitAll()
  117 + .antMatchers("/swagger-ui.html", "/swagger-resources/**", "/webjars/**", "/*/api-docs", "/druid/**").permitAll()
  118 + // 除上面外的所有请求全部需要鉴权认证
  119 + .anyRequest().authenticated();
  120 + })
  121 + // 添加Logout filter
  122 + .logout(logout -> logout.logoutUrl("/logout").logoutSuccessHandler(logoutSuccessHandler))
  123 + // 添加JWT filter
  124 + .addFilterBefore(authenticationTokenFilter, UsernamePasswordAuthenticationFilter.class)
  125 + // 添加CORS filter
  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 }