我想为项目配置Spring Security。
然而,它失败并出现下一个错误:
***************************
APPLICATION FAILED TO START
***************************
Description:
The dependencies of some of the beans in the application context form a cycle:
┌─────┐
| securityConfiguration defined in file [C:\Users\Nazar\Projects\IdeaProjects\Lohika_Projects\blog\target\classes\net\lelyak\edu\configuration\SecurityConfiguration.class]
↑ ↓
| blogDTS defined in file [C:\Users\Nazar\Projects\IdeaProjects\Lohika_Projects\blog\target\classes\net\lelyak\edu\rest\service\impl\UserDetailsServiceImpl.class]
↑ ↓
| userServiceImpl defined in file [C:\Users\Nazar\Projects\IdeaProjects\Lohika_Projects\blog\target\classes\net\lelyak\edu\rest\service\impl\UserServiceImpl.class]
└─────┘
接下来,您可以看到我的弹簧安全配置:
@Configuration
@AllArgsConstructor
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
private DataSource dataSource;
@Qualifier("blogDTS")
private UserDetailsService userDetailsService;
private AccessDeniedHandler accessDeniedHandler;
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests()
.antMatchers("/", "/registration", "/403", "/500").permitAll()
.antMatchers("/posts/**").hasAnyRole("USER")
.antMatchers("/post/**").hasAnyRole("USER")
.anyRequest().authenticated()
.and()
.formLogin().loginPage("/login").permitAll()
.usernameParameter("username")
.passwordParameter("password")
.defaultSuccessUrl("/posts")
.and()
.rememberMe().tokenValiditySeconds(10_000).tokenRepository(persistentTokenRepository())
.and()
.logout().permitAll()
.and()
.exceptionHandling().accessDeniedHandler(accessDeniedHandler).accessDeniedPage("/403");
}
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Override
protected UserDetailsService userDetailsService() {
return userDetailsService;
}
@Bean
public PersistentTokenRepository persistentTokenRepository() {
JdbcTokenRepositoryImpl db = new JdbcTokenRepositoryImpl();
db.setDataSource(dataSource);
return db;
}
@Bean
public SavedRequestAwareAuthenticationSuccessHandler
savedRequestAwareAuthenticationSuccessHandler() {
SavedRequestAwareAuthenticationSuccessHandler auth
= new SavedRequestAwareAuthenticationSuccessHandler();
auth.setTargetUrlParameter("targetUrl");
return auth;
}
}
UserDetailsServiceImpl
代码段:
@Service("blogDTS")
@AllArgsConstructor
public class UserDetailsServiceImpl implements UserDetailsService {
private UserServiceImpl userService;
@Override
public UserDetails loadUserByUsername(final String username) throws UsernameNotFoundException {
BlogUser user = userService.getUser(username);
List<GrantedAuthority> authorities = buildUserAuthority(user.getRole());
return buildUserForAuthentication(user, authorities);
}
private org.springframework.security.core.userdetails.User buildUserForAuthentication(BlogUser user,
List<GrantedAuthority> authorities) {
return new org.springframework.security.core.userdetails.User(
user.getUserName(),
user.getPassword(),
user.isEnabled(),
true,
true,
true,
authorities);
}
private List<GrantedAuthority> buildUserAuthority(Role userRole) {
Set<GrantedAuthority> setAuths = Stream.of(new SimpleGrantedAuthority(userRole.name()))
.collect(Collectors.toSet());
return Lists.newArrayList(setAuths);
}
}
UserServiceImpl
是管理存储库操作的常用服务层:
@Service
@AllArgsConstructor
public class UserServiceImpl implements UserService {
private final UserRepository userRepository;
private final PasswordEncoder passwordEncoder;
@Override
public List<BlogUser> getAllUsers() {
List<BlogUser> result = new ArrayList<>();
result.addAll(userRepository.findAll());
return result;
}
@Override
public BlogUser getUser(String userName) {
Assert.hasText(userName, "User name is empty");
return userRepository.findByUserName(userName)
.orElseThrow(() -> new NotPresentedInDbException(userName));
}
我无法理解如何使用Spring Security解决这个循环问题。
如何解决此问题?
答案 0 :(得分:0)
最后,我找到了解决方案,重新设计了我的代码:
@Configuration
@AllArgsConstructor
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
private UserDetailsServiceImpl userDetailsService;
private AccessDeniedHandler accessDeniedHandler;
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests()
.antMatchers("/", "/registration").permitAll()
.antMatchers("/posts/**", "/post/*").authenticated()
.anyRequest().authenticated()
.and()
.formLogin().loginPage("/login").permitAll()
.usernameParameter("username")
.passwordParameter("password")
.defaultSuccessUrl("/posts")
.and()
.logout().permitAll()
.and()
.exceptionHandling().accessDeniedHandler(accessDeniedHandler).accessDeniedPage("/403");
}
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(authenticationProvider());
}
@Bean
public DaoAuthenticationProvider authenticationProvider() {
DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider();
authProvider.setUserDetailsService(userDetailsService);
authProvider.setPasswordEncoder(passwordEncoder());
return authProvider;
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Override
protected UserDetailsService userDetailsService() {
return userDetailsService;
}
}
简化一点UserDetailsServiceImpl
。此外,使用存储库类从DB获取用户:
@Service
@AllArgsConstructor
public class UserDetailsServiceImpl implements UserDetailsService {
private UserRepository userRepository;
@Override
public UserDetails loadUserByUsername(final String username) throws UsernameNotFoundException {
BlogUser user = userRepository.findByUserName(username)
.orElseThrow(NotPresentedInDbException::new);
return buildUserForAuthentication(user);
}
private org.springframework.security.core.userdetails.User buildUserForAuthentication(BlogUser user) {
SimpleGrantedAuthority grantedAuthority = new SimpleGrantedAuthority(user.getRole().name());
List<GrantedAuthority> authorities = Lists.newArrayList(grantedAuthority);
return new org.springframework.security.core.userdetails.User(
user.getUserName(),
user.getPassword(),
user.isEnabled(),
true,
true,
true,
authorities);
}
}
现在它的工作正常。