配置
ruoyi
springboot 3.1.5
jdk17
升级前代码
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.authentication.logout.LogoutFilter;
import org.springframework.web.filter.CorsFilter;
import com.ruoyi.framework.config.properties.PermitAllUrlProperties;
import com.ruoyi.framework.security.filter.JwtAuthenticationTokenFilter;
import com.ruoyi.framework.security.handle.AuthenticationEntryPointImpl;
import com.ruoyi.framework.security.handle.LogoutSuccessHandlerImpl;
/**
* spring security配置
*
* @author ruoyi
*/
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter
{
/**
* 自定义用户认证逻辑
*/
@Autowired
private UserDetailsService userDetailsService;
/**
* 认证失败处理类
*/
@Autowired
private AuthenticationEntryPointImpl unauthorizedHandler;
/**
* 退出处理类
*/
@Autowired
private LogoutSuccessHandlerImpl logoutSuccessHandler;
/**
* token认证过滤器
*/
@Autowired
private JwtAuthenticationTokenFilter authenticationTokenFilter;
/**
* 跨域过滤器
*/
@Autowired
private CorsFilter corsFilter;
/**
* 允许匿名访问的地址
*/
@Autowired
private PermitAllUrlProperties permitAllUrl;
/**
* 解决 无法直接注入 AuthenticationManager
*
* @return
* @throws Exception
*/
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception
{
return super.authenticationManagerBean();
}
@Override
protected void configure(HttpSecurity httpSecurity) throws Exception
{
// 注解标记允许匿名访问的url
ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry registry = httpSecurity.authorizeRequests();
permitAllUrl.getUrls().forEach(url -> registry.antMatchers(url).permitAll());
httpSecurity
// CSRF禁用,因为不使用session
.csrf().disable()
// 禁用HTTP响应标头
.headers().cacheControl().disable().and()
// 认证失败处理类
.exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and()
// 基于token,所以不需要session
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
// 过滤请求
.authorizeRequests()
// 对于登录login 注册register 验证码captchaImage 允许匿名访问
.antMatchers("/login", "/register", "/captchaImage").permitAll()
// 静态资源,可匿名访问
.antMatchers(HttpMethod.GET, "/", "/*.html", "/**/*.html", "/**/*.css", "/**/*.js", "/profile/**").permitAll()
.antMatchers("/swagger-ui.html", "/swagger-resources/**", "/webjars/**", "/*/api-docs", "/druid/**").permitAll()
// 除上面外的所有请求全部需要鉴权认证
.anyRequest().authenticated()
.and()
.headers().frameOptions().disable();
// 添加Logout filter
httpSecurity.logout().logoutUrl("/logout").logoutSuccessHandler(logoutSuccessHandler);
// 添加JWT filter
httpSecurity.addFilterBefore(authenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);
// 添加CORS filter
httpSecurity.addFilterBefore(corsFilter, JwtAuthenticationTokenFilter.class);
httpSecurity.addFilterBefore(corsFilter, LogoutFilter.class);
}
/**
* 强散列哈希加密实现
*/
@Bean
public BCryptPasswordEncoder bCryptPasswordEncoder()
{
return new BCryptPasswordEncoder();
}
/**
* 身份认证接口
*/
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception
{
auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder());
}
}
升级后代码
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.ProviderManager;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.config.annotation.web.configurers.HeadersConfigurer.CacheControlConfig;
import org.springframework.security.config.annotation.web.configurers.HeadersConfigurer.FrameOptionsConfig;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.authentication.logout.LogoutFilter;
import org.springframework.security.web.servlet.util.matcher.MvcRequestMatcher;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.web.filter.CorsFilter;
import org.springframework.web.servlet.handler.HandlerMappingIntrospector;
import com.ruoyi.framework.config.properties.PermitAllUrlProperties;
import com.ruoyi.framework.security.filter.JwtAuthenticationTokenFilter;
import com.ruoyi.framework.security.handle.AuthenticationEntryPointImpl;
import com.ruoyi.framework.security.handle.LogoutSuccessHandlerImpl;
import jakarta.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
/**
* spring security配置
*
* @author zhaorui
*/
@Configuration
@EnableWebSecurity
public class SecurityConfig {
/**
* 自定义用户认证逻辑
*/
@Resource
private UserDetailsService userDetailsService;
/**
* 认证失败处理类
*/
@Resource
private AuthenticationEntryPointImpl unauthorizedHandler;
/**
* 退出处理类
*/
@Resource
private LogoutSuccessHandlerImpl logoutSuccessHandler;
/**
* token认证过滤器
*/
@Resource
private JwtAuthenticationTokenFilter authenticationTokenFilter;
/**
* 跨域过滤器
*/
@Resource
private CorsFilter corsFilter;
/**
* 允许匿名访问的地址
*/
@Resource
private PermitAllUrlProperties permitAllUrl;
@Resource
private HandlerMappingIntrospector introspector;
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
// CSRF禁用,因为不使用session
.csrf(AbstractHttpConfigurer::disable)
// 禁用HTTP响应标头
.headers(
// 控制响应头禁用缓存
(headers) -> headers.cacheControl(CacheControlConfig::disable)
// 处理X-Frame-Options响应头
.frameOptions(FrameOptionsConfig::disable))
// 认证失败处理类
.exceptionHandling(
exceptionHandler -> exceptionHandler.authenticationEntryPoint(unauthorizedHandler))
// 基于token,所以不需要session
.sessionManagement(sessionManagement -> sessionManagement.sessionCreationPolicy(
SessionCreationPolicy.STATELESS))
.authorizeHttpRequests(authorizeReq -> authorizeReq
.requestMatchers(createMvcReqMatcher()).permitAll()
.requestMatchers(createAntPathReqMatcher()).permitAll()
// 除上面外的所有请求全部需要鉴权认证
.anyRequest().authenticated())
// 添加Logout filter
.logout(logoutHandler -> logoutHandler.logoutUrl("/logout")
.logoutSuccessHandler(logoutSuccessHandler));
// 添加JWT filter
http.addFilterBefore(authenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);
// 添加CORS filter
http.addFilterBefore(corsFilter, JwtAuthenticationTokenFilter.class);
http.addFilterBefore(corsFilter, LogoutFilter.class);
return http.build();
}
/**
* mvc请求,即controller中的请求
*
* @return mvc请求(发送到controller的请求)
*/
private MvcRequestMatcher[] createMvcReqMatcher() {
List<MvcRequestMatcher> mvcRequestMatchers = new ArrayList<>();
// 对于登录login 注册register 验证码captchaImage 允许匿名访问
mvcRequestMatchers.add(new MvcRequestMatcher(introspector, "/login"));
mvcRequestMatchers.add(new MvcRequestMatcher(introspector, "/register"));
mvcRequestMatchers.add(new MvcRequestMatcher(introspector, "/captchaImage"));
// 注解标记允许匿名访问的url
for (String url : permitAllUrl.getUrls()) {
mvcRequestMatchers.add(new MvcRequestMatcher(introspector, url));
}
return mvcRequestMatchers.toArray(MvcRequestMatcher[]::new);
}
/**
* 可匿名访问的静态资源 非Spring MVC端点请求, 需要特别指明,否则springboot无法启动
*
* @return 非Spring MVC端点请求集合
*/
private AntPathRequestMatcher[] createAntPathReqMatcher() {
return new AntPathRequestMatcher[]{
AntPathRequestMatcher.antMatcher(HttpMethod.GET, "/"),
AntPathRequestMatcher.antMatcher(HttpMethod.GET, "/*.html"),
AntPathRequestMatcher.antMatcher(HttpMethod.GET, "/**/*.html"),
AntPathRequestMatcher.antMatcher(HttpMethod.GET, "/**/*.css"),
AntPathRequestMatcher.antMatcher(HttpMethod.GET, "/**/*.js"),
AntPathRequestMatcher.antMatcher(HttpMethod.GET, "/profile/**"),
AntPathRequestMatcher.antMatcher("/swagger-ui.html"),
AntPathRequestMatcher.antMatcher("/swagger-resources/**"),
AntPathRequestMatcher.antMatcher("/webjars/**"),
AntPathRequestMatcher.antMatcher("/*/api-docs"),
AntPathRequestMatcher.antMatcher("/druid/**")
};
}
/**
* 强散列哈希加密实现
*/
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
/**
* 获取AuthenticationManager(认证管理器),登录时认证使用
*
* @return 认证结果
*/
@Bean
public AuthenticationManager authenticationManager() {
// 身份认证接口
DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider();
authenticationProvider.setUserDetailsService(userDetailsService);
authenticationProvider.setPasswordEncoder(passwordEncoder());
ProviderManager providerManager = new ProviderManager(authenticationProvider);
providerManager.setEraseCredentialsAfterAuthentication(false);
return providerManager;
}
}
重点更改
- Javax --> jakarta
- 一些方法的弃用,参考api来写[1]
- 当用tomcat来启动时,springboot启动失败[2][3]
参考链接:
[1]: https://docs.spring.io/spring-security/site/docs/current/api/
[2]: https://www.qinglite.cn/doc/540264c47d6bbacc6
[3]:https://blog.csdn.net/wangshuai6707/article/details/132898994