当前位置: 首页 > 知识库问答 >
问题:

Spring Boot2无法自动连接。有多个“UserDemailsService”bean

贾飞章
2023-03-14

大家好,我是Spring安保和jwt的新人。我正在我的spring boot项目中实现Jwt以确保用户登录安全,我使用的是spring boot 2.1.5,我不太了解spring boot 2中的新bean限制

@自动安装用户详细信息服务jwtUserDemailsService

谚语。。。无法自动连线。用户详细信息服务类型的 bean 不止一个。

谁能解释一下这里发生了什么问题,为什么我不能自动加载,为什么以及Spring启动2中的自动加载限制是什么?

先谢谢你了

@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);
    }
}

我的客户服务是

@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类,它公开restend点以生成jwt令牌


@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);
    }

}

其他事情也很正常,比如实体、存储库和一些安全的restend点

共有3个答案

祁柏
2023-03-14

您可以将此代码放在 application.properties 中:

spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.security.servlet.UserDetailsServiceAutoConfiguration
陈志
2023-03-14

我在另一个上下文中也犯了同样的错误。原因是这个想法不知道使用“UserDetailsService”类型的哪个bean。我的解决方案是通过注释限定符:

@Qualifier("beanNameWhichYouWantUse")
@Autowired
private UserDetailsService jwtUserDetailsService;

如果使用 Idea:将鼠标指向错误,请从上下文菜单中选择:

"More actions" -> "Add qualifier"

最后选择豆子

卢开济
2023-03-14

UserDetailsService由spring提供。要自动连线,您需要使用进行配置。

@Bean
public UserDetailsService getUserDetails(){
   return new JwtUserDetailService(); // Implementation class
}

如果您对 Bean 配置不感兴趣。您可以直接自动连接 JwtUserDetailService。

@Autowired
private JwtUserDetailService jwtUserDetailsService;
 类似资料:
  • 我的问题是:我有一个基本接口和两个实现类。 服务类依赖于基本接口,代码如下: 而配置是这样的: 服务类依赖于基础接口,将决定通过某些业务逻辑自动连接哪个实现。代码是这样的: 这个想法引发了一个例外:无法自动连线。有多个bean属于类型。 虽然可以使用@Qualifier来解决这个问题,但在这种情况下,我不能选择dependencies类。 我试图阅读spring文档,它提供了一个基于,但我仍然对这

  • 我正在学习将activiti与spring boot结合使用,但我遇到了一些错误,并且搜索了太多关于使用spring boot和java的acitiviti稳定版本的信息 我正在使用java 8和tomcat 8.0.3 我更改了这么多版本的spring和jdk,检查了这么多样本,没有发现任何问题,我只有一个控制器类和spring主类,当我运行项目时,得到了以下错误: 这是我的RestContro

  • 我的类使用@service,而bean已经自动连线,所以我不明白为什么会出现这个错误。

  • 这是我的FileStorageProperties类: 这让我想到:未通过@enableconfigurationproperties注册或标记为spring组件。 这是我的文件存储服务: 这给了我一个错误:无法自动关联未找到类型的bean。 这是我的项目结构: 当我试图运行它时,它给了我: 申请无法启动 描述: com中构造函数的参数0。穆阿。cse616.服务。FileStorageServi

  • 我正在使用java配置而不是XML迁移到spring Security4.0.1。当我自动操作时,它会给出以下错误: HTTP状态500-org.springframework.beans.factory.beanCreationException:创建名为“ScopedTarget.UsersComponent”的bean时出错:注入autowired依赖项失败;嵌套异常为org.springf

  • 当我在spring boot中添加安全配置时,遇到了这个令人讨厌的错误: 这是SpringBootApplication: 最后,这是我的项目树: