问题描述
近期升级了springsecurity版本到5.7,WebSecurityConfig的配置方法由集成优化成了声明Bean的方式,直接上代码
@EnableWebSecurity
@EnableConfigurationProperties(AuthProperties.class)
public class WebSecurityConfig {
@Autowired
private SysUserService sysUserService;
@Autowired
private AuthProperties authProperties;
@Autowired
private AuthenticationManager authenticationManager;
@Autowired
private JWTService jwtService;
@Autowired
private CacheManager cacheManager;
@Bean
SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
return http
// 基于 token,不需要 csrf
.csrf().disable()
// 基于 token,不需要 session
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
// 下面开始设置权限
.authorizeRequests(authorize -> authorize
.antMatchers(authProperties.getPermitStatic().toArray(new String[0])).permitAll()
.antMatchers(authProperties.getPermitMethod().toArray(new String[0])).permitAll()
// 其他地址的访问均需验证权限
.anyRequest().authenticated())
.addFilter(new JWTAuthenticationFilter(authenticationManager, sysUserService, jwtService, userCache()))
.exceptionHandling().authenticationEntryPoint(new UserAuthenticationEntryPoint()).and()
// 认证用户时用户信息加载配置,注入springAuthUserService
.userDetailsService(sysUserService).build();
}
/**
* 获取AuthenticationManager(认证管理器),登录时认证使用
* @param authenticationConfiguration
* @return
* @throws Exception
*/
@Bean
public AuthenticationManager authenticationManager(AuthenticationConfiguration authenticationConfiguration) throws Exception {
return authenticationConfiguration.getAuthenticationManager();
}
/**
* 密码明文加密方式配置(使用国密SM4)
* @return
*/
@Bean
public static PasswordEncoder passwordEncoder() {
return new SM4PasswordEncoder();
}
@Bean
UserCache userCache(){
Cache ca = cacheManager.getCache("userCache");
return new SpringCacheBasedUserCache(ca);
}
}
由于配置SecurityFilterChain过滤器链中,使用了JWTAuthenticationFilter,而JWTAuthenticationFilter继承自BasicAuthenticationFilter,需要定义一个AuthenticationManager,代码如下,SecurityFilterChain中需要注入AuthenticationManager,而且需要声明一个AuthenticationManager Bean配置
Slf4j
public class JWTAuthenticationFilter extends BasicAuthenticationFilter {
private final UserDetailsService userService;
private final JWTService jwtService;
private final UserCache userCache;
public JWTAuthenticationFilter(AuthenticationManager authenticationManager, SysUserService userService, JWTService jwtService, UserCache userCache) {
super(authenticationManager);
this.userService = userService;
this.jwtService = jwtService;
this.userCache = userCache;
}
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
chain.doFilter(request, response);
}
}
启动时循环依赖
***************************
APPLICATION FAILED TO START
***************************
Description:
The dependencies of some of the beans in the application context form a cycle:
┌──->──┐
| webSecurityConfig (field private org.springframework.security.authentication.AuthenticationManager com.langchen.minfang.user.config.WebSecurityConfig.authenticationManager)
└──<-──┘
Action:
Relying upon circular references is discouraged and they are prohibited by default. Update your application to remove the dependency cycle between beans. As a last resort, it may be possible to break the cycle automatically by setting spring.main.allow-circular-references to true.
Process finished with exit code 1
解决方法:
在注入AuthenticationManager时使用@Lazy注解,一定要在注入的时候。。。。。。。
@Lazy
@Autowired
private AuthenticationManager authenticationManager;