大家好,我是 Spring 安全和 jwt 的新手。我正在我的 spring boot 项目中实现 Jwt 以保护用户登录,我正在使用 spring boot 2.1.5
而且我对 spring boot 2+ 中的新 bean 限制知之甚少。
我需要一些帮助..在这里我正在尝试@Autowired UserDetailsService并且代码运行良好..结果也很好..但intellij在
@Autowired UserDetailsService jwtUserDetailsService
说......无法 Autowiring 。有不止一个 UserDetailsService 类型的 bean。
谁能解释一下这里发生了什么问题,为什么我不能 Autowiring 以及为什么 Spring Boot 2+ 中的 Autowiring 限制是什么?
并提前致谢
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurity extends WebSecurityConfigurerAdapter {
@Autowired
private JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint;
@Autowired
private PasswordEncoder passwordEncoder;
@Autowired
private JwtFilter jwtFilter;
@Autowired
private UserDetailsService jwtUserDetailsService; // here i got error only
@Autowired
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(jwtUserDetailsService).passwordEncoder(passwordEncoder);
}
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable();
http.authorizeRequests().antMatchers("/api/user/add", "/generate").permitAll().anyRequest().authenticated().and() .exceptionHandling().authenticationEntryPoint(jwtAuthenticationEntryPoint)
.and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
http.addFilterBefore(jwtFilter, UsernamePasswordAuthenticationFilter.class);
}
}
我的 customUserDetailService 是
@Service
public class JwtUserDetailService implements UserDetailsService {
@Autowired
private UserRepository userRepository;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = userRepository.findByUsername(username);
if (user != null) {
return new org.springframework.security.core.userdetails.User(user.getUsername(), user.getPassword(), new ArrayList<>());
} else {
throw new UsernameNotFoundException("Username does't exists");
}
}
}
我的 JwtController 类公开了重新端点以生成 jwt token
@CrossOrigin
@RestController
public class JwtController {
@Autowired
private JwtUtils jwtUtils;
@Autowired
private AuthenticationManager authenticationManager;
@Autowired
private JwtUserDetailService jwtUserDetailService;
@PostMapping(value = "/generate")
public ResponseEntity<?> generateToken(@RequestBody JwtRequest jwtRequest) throws Exception {
try {
authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(jwtRequest.getUsername(),
jwtRequest.getPassword()));
} catch (DisabledException e) {
throw new Exception("USER_DISABLED", e);
} catch (BadCredentialsException e) {
throw new Exception("INVAILD_CREDENTIALS", e);
}
final UserDetails userDetails = jwtUserDetailService.loadUserByUsername(jwtRequest.getUsername());
final String token = jwtUtils.generateToken(userDetails);
return ResponseEntity.ok(new JwtResponse(token));
}
}
我的 JwtFilter 类
@Component
public class JwtFilter extends OncePerRequestFilter {
@Autowired
private JwtUserDetailService jwtUserDetailService;
@Autowired
private JwtUtils jwtUtils;
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
throws ServletException, IOException {
final String requestTokenHeader = request.getHeader("Authorization");
String username = null;
String jwtToken = null;
if (requestTokenHeader != null && requestTokenHeader.startsWith("Bearer ")) {
jwtToken = requestTokenHeader.substring(7);
try {
username = jwtUtils.getUsernameFromToken(jwtToken);
} catch (IllegalArgumentException e) {
System.out.println("Unable to get JWT Token");
} catch (ExpiredJwtException e) {
System.out.println("JWT Token has expired");
}
} else {
logger.warn("JWT Token does not begin with Bearer String");
}
if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
UserDetails userDetails = this.jwtUserDetailService.loadUserByUsername(username);
if (jwtUtils.validate(jwtToken, userDetails)) {
UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(
userDetails, null, userDetails.getAuthorities());
usernamePasswordAuthenticationToken
.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
}
}
chain.doFilter(request, response);
}
}
其他正常的东西,如实体、存储库和一些安全的重新端点
最佳答案
UserDetailsService 由 spring 提供。
要 Autowiring ,您需要对其进行配置。
@Bean
public UserDetailsService getUserDetails(){
return new JwtUserDetailService(); // Implementation class
}
如果您对 Bean 配置不感兴趣。
您可以直接 Autowiring JwtUserDetailService。
@Autowired
private JwtUserDetailService jwtUserDetailsService;
关于spring-boot - Spring Boot 2+ 无法 Autowiring 。 'UserDetailsService'的bean不止一个,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56702369/