版權聲明:本文爲CSDN博主「滔濤江水」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/taotaojs/article/details/84955218
網上有一些關於這個問題的答案,但都不是基於SpringBoot的,一想到SpringBoot還要配置XML文件就頭大呀有木有。
以下就是解決方法:
在SecurityConfig中添加如下代碼
@Bean
public UserDetailsService myUserService(){
return new MyUserDetailsService();
}
並且在configure(AuthenticationManagerBuilder auth)方法中將new MyUserService()改爲以上的方法名
@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(myUserService());
}
至此,自定義DetailsService中的Service就可以注入成功了。
另外,自定義DetailsService的@Service標註不需要也沒關係,因爲已經有@Bean標註了
說一下線索:
Spring Security在Spring加載完Bean之前就加載了(Spring框架中的Web.xml配置相關)
MyUserDetailsService繼承AbstractJUnit4SpringContextTests之後輸出applicationContext,發現applicationContext爲空,說明Spring沒有加載完成
Spring沒有掃描到MyUserDetailsService,否則@Service肯定能達到與@Bean同樣的效果
這個問題是相當冷門的,所以肯定有一個約定俗成的辦法,於是搜一下Spring Security詳細搭建就可以找到問題所在了
完整代碼,就是SpringSecurity配置類
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter{
protected void configure(HttpSecurity http) throws Exception {
http
// 過濾請求
.authorizeRequests()
// 配置permitAll的不進行訪問控制!這裏的話是直接配置的是訪問首頁和訪問用戶信息,用戶分類,首頁輪播圖進行跳過
.antMatchers("/image/**", "/index/**", "/goods-info/**", "/goods-category/**", "/carousel/**").permitAll()
.antMatchers("/admin/**").hasAnyRole("ADMIN") // 訪問用戶的角色必須要有ROLE_ADMIN角色才能進行訪問
.antMatchers("/article/**").hasRole("USER")
.anyRequest().authenticated()
.and()
.csrf().disable()
.formLogin().disable()
.sessionManagement().disable()
.cors()
.and()
.headers().addHeaderWriter(new StaticHeadersWriter(Arrays.asList(
new Header("Access-control-Allow-Origin","*"),
new Header("Access-Control-Expose-Headers","Authorization"))))
.and()
// 過濾Options請求
.addFilterAfter(new OptionsRequestFilter(), CorsFilter.class)
.apply(new JsonLoginConfigurer<>()).loginSuccessHandler(jsonLoginSuccessHandler())
.and()
.apply(new JwtLoginConfigurer<>()).tokenValidSuccessHandler(jwtRefreshSuccessHandler()).permissiveRequestUrls("/logout")
.and()
.logout()
// .logoutUrl("/logout") //默認就是"/logout"
.addLogoutHandler(tokenClearLogoutHandler())
.logoutSuccessHandler(new HttpStatusReturningLogoutSuccessHandler())
.and()
.sessionManagement().disable();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService());
auth.authenticationProvider(daoAuthenticationProvider()).authenticationProvider(jwtAuthenticationProvider());
}
@Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Bean("jwtUserService")
protected JwtUserService jwtUserService() {
return new JwtUserService();
}
@Bean("jwtAuthenticationProvider")
protected AuthenticationProvider jwtAuthenticationProvider() {
return new JwtAuthenticationProvider(jwtUserService());
}
@Bean("daoAuthenticationProvider")
protected AuthenticationProvider daoAuthenticationProvider() throws Exception{
//這裏會默認使用BCryptPasswordEncoder比對加密後的密碼,注意要跟createUser時保持一致
DaoAuthenticationProvider daoProvider = new DaoAuthenticationProvider();
daoProvider.setUserDetailsService(userDetailsService());
return daoProvider;
}
@Override
@Bean
protected UserDetailsService userDetailsService() {
return new JwtUserService();
}
@Bean
protected JsonLoginSuccessHandler jsonLoginSuccessHandler() {
return new JsonLoginSuccessHandler(jwtUserService());
}
@Bean
protected JwtRefreshSuccessHandler jwtRefreshSuccessHandler() {
return new JwtRefreshSuccessHandler(jwtUserService());
}
@Bean
protected TokenClearLogoutHandler tokenClearLogoutHandler() {
return new TokenClearLogoutHandler(jwtUserService());
}
@Bean
protected CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOrigins(Arrays.asList("*"));
configuration.setAllowedMethods(Arrays.asList("GET","POST","HEAD", "OPTION"));
configuration.setAllowedHeaders(Arrays.asList("*"));
configuration.addExposedHeader("Authorization");
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
}