当前位置: 首页 > 面试题库 >

无法自动连线栏位:私人org.springframework.security.core.userdetails.UserDetailsS​​ervice

江志业
2023-03-14
问题内容

我是Spring的新手,所以我一直在考虑安全方面。每当我运行我的应用程序时,我都会得到:

org.springframework.beans.factory.BeanCreationException:创建名称为’securityConfig’的bean时出错:自动连接依赖项的注入失败;嵌套的异常是org.springframework.beans.factory.BeanCreationException:无法自动连线字段:私有org.springframework.security.core.userdetails.UserDetailsS​​ervice
com.entirety.app.config.SecurityConfig.userDetailsS​​erviceImplementation;
嵌套的异常是org.springframework.beans.factory.NoSuchBeanDefinitionException:没有找到类型为[org.springframework.security.core.userdetails.UserDetailsS​​ervice]的合格Bean作为依赖项:至少应有1个有资格作为该依赖项的自动装配候选的bean。依赖项注释:{@
org.springframework.beans.factory.annotation.Autowired(required = true)}

我已经很好地梳理了我的代码,无法查明问题所在。

Spring Framework版本:3.2.5.RELEASE Spring安全版本:3.2.0.M2

SecurityConfig.java

package com.entirety.app.config;

import com.entirety.app.service.implement.UserDetailsServiceImplementation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

import javax.sql.DataSource;

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled=true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    private DataSource dataSource;

    @Autowired
    private UserDetailsService userDetailsServiceImplementation;

    @Override
    protected void registerAuthentication(AuthenticationManagerBuilder auth) throws Exception {
        auth.jdbcAuthentication().dataSource(dataSource);
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.userDetailsService(userDetailsServiceImplementation)
                .authorizeUrls()
                    .antMatchers("/admin/**").hasRole("ADMIN")
                    .antMatchers("/sec/**").hasRole("MODERATOR")
                    .antMatchers("/*").permitAll()
                    .anyRequest().anonymous().and().exceptionHandling().accessDeniedPage("/denied").and()
                .formLogin()
                    .loginProcessingUrl("/j_spring_security_check")
                    .loginPage("/login")
                    .failureUrl("/error-login")
                .and()
                .logout()
                    .logoutUrl("/j_spring_security_logout")
                    .logoutSuccessUrl("/");
    }

    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }
}

CrmUserService.java

@Service("userService")
@Transactional
public class CrmUserService implements UserDetailsService {
    @Autowired
    private UserDAO userDAO;

    @Override
    public UserDetails loadUserByUsername(String login) throws UsernameNotFoundException {

        com.entirety.app.domain.User domainUser = userDAO.getUser(login);

        boolean enabled = true;
        boolean accountNonExpired = true;
        boolean credentialsNonExpired = true;
        boolean accountNonLocked = true;

        return new User(
                domainUser.getLogin(),
                domainUser.getPassword(),
                enabled,
                accountNonExpired,
                credentialsNonExpired,
                accountNonLocked,
                getAuthorities(domainUser.getAuthority().getId())
        );
    }

    public Collection<? extends GrantedAuthority> getAuthorities(Integer role) {
        List<GrantedAuthority> authList = getGrantedAuthorities(getRoles(role));
        return authList;
    }

    public List<String> getRoles(Integer role) {

        List<String> roles = new ArrayList<String>();

        if (role.intValue() == 1) {
            roles.add("ROLE_MODERATOR");
            roles.add("ROLE_ADMIN");
        } else if (role.intValue() == 2) {
            roles.add("ROLE_MODERATOR");
        }
        return roles;
    }

    public static List<GrantedAuthority> getGrantedAuthorities(List<String> roles) {
        List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();

        for (String role : roles) {
            authorities.add(new SimpleGrantedAuthority(role));
        }
        return authorities;
    }
}

没有逻辑上的原因导致它应该失败,但是它确实会失败。

注意:

我的IDE可以链接自动装配线(也就是说,它知道从何处进行自动装配线以及所有内容),但是编译失败。

编辑2:我从SecurityConfig.java文件中删除了以下代码

@Autowired
private UserDataService userDataService;

并将其添加到我所知道的POJO和控制器之一中,它会被定期调用并包含其他服务。在这种情况下,将该代码粘贴到我的baseController.java文件中,该文件定向到呈现主页。该服务已正确编译,我什至可以在控制器中调用它。

因此,问题仅被隔离到配置文件(例如SecurityConfig.java),这是唯一无法解决的问题。

编辑3:添加了额外的文件

SecurityInitializer.java

@Order(2)
public class SecurityInitializer extends AbstractSecurityWebApplicationInitializer  {
}

WebInitializer.java

@Order(1)
public class WebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
    @Override
    protected Class<?>[] getRootConfigClasses() {
        return new Class<?>[] { PersistanceConfig.class, SecurityConfig.class };  //To change body of implemented methods use File | Settings | File Templates.
    }

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

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

//    @Override
//    protected Filter[] getServletFilters() {
//        CharacterEncodingFilter characterEncodingFilter = new CharacterEncodingFilter();
//        characterEncodingFilter.setEncoding("UTF-8");
//        return new Filter[] { characterEncodingFilter};
//    }
}

mvc-dispatcher-servlet.xml

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

    <context:component-scan base-package="com.entirety.app"/>

    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/pages/"/>
        <property name="suffix" value=".jsp"/>
    </bean>

</beans>

web.xml

<web-app version="2.4"
    xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee 
    http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">

    <display-name>Spring MVC Application</display-name>

    <servlet>
        <servlet-name>mvc-dispatcher</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>mvc-dispatcher</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
</web-app>

问题答案:

看来您有多个问题。

web.xml与AbstractAnnotationConfigDispatcherServletInitializer

您创建的应用程序有一个web.xml,用于配置名为的DispatcherServlet mvc-dispatcher。的mvc- dispatcher配置已将mvc-dispatcher- servlet.xml软件包中的所有bean装入com.springapp.sectest。这意味着mvc- dispatcher可以找到您的UserDetailsService

该应用程序还具有一个AbstractAnnotationConfigDispatcherServletInitializer,它创建了一个DispatcherServlet加载WebConfigJava配置的文件。这DispatcherServlet无法看到创建的豆类mvc- dispatcher

简而言之,您应该DispatcherServlet使用web.xml
进行配置,或者AbstractAnnotationConfigDispatcherServletInitializer不要同时使用两者。

getRootConfigClasses与getServletConfigClasses

getRootConfigClasses中的任何配置通常称为根配置或父配置,并且无法查看在getServletConfigClasses中定义的bean。Spring
Security使用由@EnableWebSecurity注释创建的名为springSecurityFilterChain的过滤器保护在getRootConfigClasses中定义的应用程序。这意味着通常最好将Spring
Security的配置放在getRootConfigClasses中。对此有一些例外,例如,如果您想在Spring MVC控制器上进行方法安全性。

getServletConfigClasses中的任何配置通常都称为子配置,并且可以查看在getRootConfigClasses中定义的bean。getServletConfigClasses配置,DispatcherServlet并且必须包含Spring
MVC的bean(即Controllers,ViewResovlers等)。getRootConfigClasses中定义的任何Spring MVC
bean都是可见的,但未使用。

这种设置虽然有点令人困惑,但允许您DispatcherServlet使用隔离配置来拥有多个实例。实际上,很少有多个DispatcherServlet实例。

根据上述信息,您应该将UserDetailsService声明及其所有依赖的bean移到getRootConfigClasses。这将确保SecurityConfig.java可以找到UserDetailsService

拉请求修复

我已经提交了一份PR来获取您的应用程序,以便它以没有错误的开头https://github.com/worldcombined/AnnotateFailed/pull/1。一些注意事项

  • 该测试未使用父级和子级上下文,因此未反映运行该应用程序
  • 我不得不移动资源文件夹,以便正确拾取
  • 我没有这样做,所以您实际上可以进行身份​​验证。没有login.jsp,并且您提供的UserDetailsS​​ervice始终返回null。相反,我尝试证明这里的错误已得到解决。

原始答案

基于此评论:

@ComponentScan在我的mvc-dispatcher-servlet.xml中作为 进行

看来您是在Dispatcher配置中而不是在根上下文中配置服务。

Spring
Security的配置通常在根上下文中配置。例如,可以如下所示扩展AbstractSecurityWebApplicationInitializer:

import org.springframework.security.web.context.*;

public class SecurityWebApplicationInitializer
      extends AbstractSecurityWebApplicationInitializer {
}

您如何导入安全配置?如果Spring Security配置在根上下文中,则它将看不到在Dispatcher Servlet上下文中定义的bean。

解决方案是在根上下文中移动服务的配置,或将Spring
Security配置移动到调度程序的ApplicationContext。例如,如果您的调度程序servlet被命名为mvc,那么将Spring
Security配置移动到调度程序上下文中将如下所示。

public class SecurityWebApplicationInitializer
      extends AbstractSecurityWebApplicationInitializer {
    protected String getDispatcherWebApplicationContextSuffix() {
        return "mvc";
    }
}


 类似资料:
  • 我们正在使用Spring框架5和Spring Boot 2.0.0。M6,我们也在使用WebClient进行反应式编程。我们为我们的反应式Restendpoint创建了测试方法,所以我查找了一些关于如何做到这一点的例子。我发现这个或这个以及许多其他的都一样。他们只是自动绑定一个WebTestClient。所以我尝试了同样的方法: 我无法运行此操作,因为我收到错误信息: 因此,似乎不存在自动配置。我

  • 在试图通过浏览器访问我的应用程序时,我遇到了不少错误。错误包括: 无法自动连线方法:public void com。ProjectOne。Util。自定义HibernatedAOSupport。anyMethodName(org.hibernate.SessionFactory);嵌套的异常是org。springframework。豆。工厂NoSuchBeanDefinitionException

  • 问题内容: 如果Service类使用Validated注释进行注释,则同一类无法自动装配自身。 这是在Spring Context尝试加载时引发的异常: 同样,当您有很多依赖于类的自身时,就会发生这种情况(当某个服务使用使用第一个服务的其他服务时)。我想知道@Validated注解,但是我总是在bean上遇到同样的错误。 有人知道我该怎么解决吗? 问题答案: 在这种情况下,注释与错误的自动装配无关

  • 问题内容: 我在Spring定义了这样的地图: 然后,我将该bean自动装配为定义为的属性: 这样做时,会抛出一个异常,说: `Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘DutyCreator’: Injection of autowired

  • 问题内容: 需要一些帮助,我刚刚开始学习Spring,似乎无法弄清楚我们的错: Application.java-没有包 User.java-包com.mapping UserDAO.java-包com.accesors Root.java-包com.controllers 当我运行项目时,我似乎得到了以下启示 堆栈跟踪: 据我了解,这意味着@ComponentScan没有检测到软件包 问题答案:

  • 代码完成了这项工作,创建了repo HashMap对象({})。然而,我试图让repo映射对象由Spring生成。所以我把DataRepoImpl改成: 然而,当我重构帐户ID和地图键到字符串类型,我能够产生HashMap包含一个'假人'变量,这是奇怪的: 回到Integer,我无法修复错误,然后我尝试将自动连线移到DataRepoImpl类的空构造函数: 然而,我从repo得到空值,因为(我的假