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

使用注释的Spring security登录数据库:NosuchBeanDefinitionException

熊博远
2023-03-14
 @Configuration
 @EnableWebSecurity
 public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    DataSource dataSource;

    @Autowired
public void configAuthentication(AuthenticationManagerBuilder auth) throws Exception {

  auth.jdbcAuthentication().dataSource(dataSource)
              .passwordEncoder(passwordEncoder())
    .usersByUsernameQuery(
                        "SELECT email as username,password,active_yn FROM users where email=?")
    .authoritiesByUsernameQuery(
        "SELECT users.email as username,user_role.role_code as user_role FROM users inner join user_role on users.user_id=user_role.user_id where users.email=?");
}   


@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
    auth.inMemoryAuthentication().withUser("uname@gmail.com").password("pass").roles("USER");
    auth.inMemoryAuthentication().withUser("admin@gmail.com").password("pass").roles("ADMIN");
    auth.inMemoryAuthentication().withUser("expert@gmail.com").password("pass").roles("EXPERT");
}

//.csrf() is optional, enabled by default, if using WebSecurityConfigurerAdapter constructor
@Override
protected void configure(HttpSecurity http) throws Exception {

    http.authorizeRequests()
        .antMatchers("/client/**").access("hasRole('ROLE_USER')")
        .antMatchers("/admin/**").access("hasRole('ROLE_ADMIN')")
        .antMatchers("/expert/**").access("hasRole('ROLE_EXPERT')")
        .and()
            .formLogin().loginPage("/login").failureUrl("/login?error")
                .usernameParameter("username").passwordParameter("password")

        .and()
            .logout().logoutSuccessUrl("/login?logout")
        .and()
            .csrf(); 

}
    @Bean
public PasswordEncoder passwordEncoder(){
    PasswordEncoder encoder = new BCryptPasswordEncoder();
    return encoder;
}
 @Configuration
 @ComponentScan("com.package.project")
 @EnableWebMvc
 @EnableTransactionManagement
 @PropertySource("classpath:pro-${env.name}.properties")
 @Import({SecurityConfig.class})
 public class MainConfig extends WebMvcConfigurerAdapter {
  @Value("${jdbc.classname}")
  private String jdbcClassname;
  @Value("${jdbc.url}")
  private String jdbcUrl;
  @Value("${jdbc.username}")
  private String jdbcUsername;
  @Value("${jdbc.password}")
  private String jdbcPassword;
  //code

@Bean(name = "dataSource")
public BasicDataSource dataSource() {
    BasicDataSource dataSource = new BasicDataSource();
    dataSource.setDriverClassName(jdbcClassname);
    dataSource.setUrl(jdbcUrl);
    dataSource.setUsername(jdbcUsername);
    dataSource.setPassword(jdbcPassword);
    return dataSource;
}

}

我的消息属性:

jdbc.classname=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://10.0.1.28:3306/test
jdbc.username=root
jdbc.password=pass

我还添加了扩展到AbstractanNotationConfigDispatcherServletInitializer的类。

     2015-03-31 13:35:32 WARN  AnnotationConfigWebApplicationContext:487 - Exception encountered during context initialization - cancelling refresh attempt

     org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'securityConfig': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: javax.sql.DataSource com.project.pro.config.SecurityConfig.dataSource; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [javax.sql.DataSource] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}

   Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: javax.sql.DataSource com.project.pro.config.SecurityConfig.dataSource; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [javax.sql.DataSource] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}

   Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [javax.sql.DataSource] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}

     2015-03-31 13:35:32 ERROR ContextLoader:331 - Context initialization failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'securityConfig': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: javax.sql.DataSource com.project.pro.config.SecurityConfig.dataSource; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [javax.sql.DataSource] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
@Override
protected Class<?>[] getRootConfigClasses() {
    return new Class[] {SecurityConfig.class};
}

@Override
protected Class<?>[] getServletConfigClasses() {
    return new Class[] { MainConfig.class };
}

@Override
protected String[] getServletMappings() {
    return new String[] { "/" };
}

}

共有1个答案

缪嘉志
2023-03-14

问题是Spring Security注册在根ApplicationContext中,而根ApplicationContext看不到子ApplicationContext(即ServletConfigClasss)中定义的bean。

将BasicDataSource移动到父ApplicationContext中,它应该可以正常工作。注意,必须在ServletConfigClasss中声明任何与Spring MVC相关的配置(即EnableWebMvc、Controllers等),以确保它们被获取。

因此,在您的实例中,BasicDataSource是在MainConfig中定义的,而MainConfig通过GetServletConfigClasss公开。这意味着BasicDataSource仅可用于通过GetServletConfigClasss公开的配置。

SecurityConfig通过GetRootConfigClasss公开,这意味着它看不到GetServletConfigClasss中的任何内容。这意味着它无法看到BasicDataSource。

通过GetRootConfigClasss公开的任何配置都可以通过GetServletConfigClasss看到。

因此您可以按照以下方式更新配置:

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    DataSource dataSource;

    @Autowired
    public void configAuthentication(AuthenticationManagerBuilder auth) throws Exception {

        auth
            .jdbcAuthentication()
                .dataSource(dataSource)
                .passwordEncoder(passwordEncoder())
                .usersByUsernameQuery(
                        "SELECT email as username,password,active_yn FROM users where email=?")
                .authoritiesByUsernameQuery(
        "SELECT users.email as username,user_role.role_code as user_role FROM users inner join user_role on users.user_id=user_role.user_id where users.email=?")
                .and()
            .inMemoryAuthentication()
                .withUser("uname@gmail.com").password("pass").roles("USER").and()
                .withUser("admin@gmail.com").password("pass").roles("ADMIN").and()
                .withUser("expert@gmail.com").password("pass").roles("EXPERT");
    }   

    @Override
    protected void configure(HttpSecurity http) throws Exception {

        http
            .authorizeRequests()
                .antMatchers("/client/**").access("hasRole('ROLE_USER')")
                .antMatchers("/admin/**").access("hasRole('ROLE_ADMIN')")
                .antMatchers("/expert/**").access("hasRole('ROLE_EXPERT')")
                .and()
            .formLogin()
                .loginPage("/login");
}

@Bean
public PasswordEncoder passwordEncoder(){
    return new BCryptPasswordEncoder();
}


@Configuration
@ComponentScan("com.package.project")
@EnableTransactionManagement
@PropertySource("classpath:pro-${env.name}.properties")
public class MainConfig {
    @Value("${jdbc.classname}")
    private String jdbcClassname;
    @Value("${jdbc.url}")
    private String jdbcUrl;
    @Value("${jdbc.username}")
    private String jdbcUsername;
    @Value("${jdbc.password}")
    private String jdbcPassword;
    //code

    @Bean(name = "dataSource")
    public BasicDataSource dataSource() {
        BasicDataSource dataSource = new BasicDataSource();
        dataSource.setDriverClassName(jdbcClassname);
        dataSource.setUrl(jdbcUrl);
        dataSource.setUsername(jdbcUsername);
        dataSource.setPassword(jdbcPassword);
        return dataSource;
    }
}

@Configuration
@ComponentScan("com.package.project")
@EnableWebMvc
public class WebMvcConfig extends WebMvcConfigurerAdapter {
     // ... if you don't override any methods you don't need to extend WebMvcConfigurerAdapter
}

public class ProWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
    @Override
    protected Class<?>[] getRootConfigClasses() {
        return new Class[] {SecurityConfig.class, MainConfig.class};
    }

    @Override
    protected Class<?>[] getServletConfigClasses() {
        return new Class[] { WebMvcConfig.class };
    }

    @Override
    protected String[] getServletMappings() {
        return new String[] { "/" };
    }
}
 类似资料:
  • 我使用spring和security with创建了一个REST服务。当前,当我点击url时,我获得了访问令牌,然后使用它发送基本登录凭据,该凭据在文件中是静态的。如何使用数据库提供用户身份验证?

  • 主要内容:通过命令行客户端软件登录当MySQL 服务开启后,就可以通过客户端来登录 MySQL 数据库了。在 Windows 操作系统下可以使用 DOS 命令登录数据库,本节将介绍使用命令方式登录 MySQL 数据库的方法。 登录 MySQL 数据库的具体操作步骤如下: 步骤 1):单击“开始”→“Windows 系统”→“命令提示符”,如图所示。 步骤 2):打开命令行提示符界面,输入命令 ,按回车键,如图所示。 步骤 3):在

  • 我有一个moodle数据库(其中有完整的用户)。所以,我想创建一个登录表单(只是为了好玩),并且用户可以用他们的moodle帐户credidentials登录。Moodle为每个单独的用户使用密码盐,我如何在我的代码中盐密码来与db记录进行比较?

  • 我是mysql和php的新手。 一直致力于为用户创建一个带有表的数据库。 我已经成功地将用户添加到数据库中,他们的密码是md5(是的,我知道它不安全),它不会在线启动。 我的问题是,如何根据用户正确的用户名和密码登录。 这是我的密码 我的逻辑是taht查询运行后,它将返回true或false。 如果为真,则显示成功登录,否则不成功。 然而,即使我输入了正确的用户名和密码,我仍然会收到一条不成功的登

  • 主要内容:1.引入jar包,2.配置文件编写,3.编写数据库,4.编写实体类,5.编写Mapper接口,6.在业务层中引入用户的用户名和密码,7.测试1.引入jar包 2.配置文件编写 appilication.properties 需要注意后面需要加上时区,因为当前引入的是SpringBoot2以上的版本 3.编写数据库 4.编写实体类 5.编写Mapper接口 这里是继承了BaseMapper接口 6.在业务层中引入用户的用户名和密码 第一个是导入UserMapper接口 第二个是根据接口去

  • 我必须将所有日志数据(即调试、信息、错误)放入mysql数据库,而不是文件/控制台。我阅读了Spring Boot文档,但没有看到任何与日志记录数据库相关的配置。 https://docs.spring.io/spring-boot/docs/current/reference/html/howto-logging.html 也尝试了以下链接,但它也不工作。https://www.tutorial