从xml配置到java配置的Spring安全性

时间:2017-08-30 08:27:19

标签: java spring spring-security

这是我的安全xml配置。

    <?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/security"
             xmlns:beans="http://www.springframework.org/schema/beans"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
        http://www.springframework.org/schema/security
        http://www.springframework.org/schema/security/spring-security.xsd">

    <http auto-config="true">
        <csrf disabled="true"/>
        <intercept-url pattern="/" access="hasRole('ROLE_USER')"/>
        <intercept-url pattern="/welcome" access="hasRole('ROLE_USER')"/>
        <form-login login-page="/login" default-target-url="/welcome" authentication-failure-url="/login?error"
                    username-parameter="username" password-parameter="password"/>
        <logout logout-success-url="/login?logout"/>
    </http>

    <authentication-manager alias="authenticationManager">
        <authentication-provider user-service-ref="userDetailsServiceImpl">
            <password-encoder ref="encoder"/>
        </authentication-provider>
    </authentication-manager>

    <beans:bean id="userDetailsServiceImpl" class="com.egs.account.service.user.UserDetailsServiceImpl"/>

    <beans:bean id="encoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder">
        <beans:constructor-arg name="strength" value="11"/>
    </beans:bean>
</beans:beans>

这个是我的web.xml文件。

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

    <display-name>Account Registration Web Application</display-name>

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/resources/appconfig-root.xml</param-value>
    </context-param>

    <filter>
        <filter-name>springSecurityFilterChain</filter-name>
        <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>springSecurityFilterChain</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>


    <servlet>
        <servlet-name>dispatcher</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value/>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>dispatcher</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
</web-app>

现在我已切换到Java配置,那些Config类是我的web.xml和security.xml文件的等效版本。

@Configuration
@EnableWebSecurity
@ComponentScan("com.egs.account.*")
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth.authenticationProvider(authProvider())
                .inMemoryAuthentication()
                .withUser("user").password("password").roles("USER");
    }

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

        http.authorizeRequests()
                .antMatchers("/").permitAll()
                .antMatchers("/welcome**").access("hasRole('USER')")
                .and().formLogin()
                .loginPage("/login")
                .defaultSuccessUrl("/welcome")
                .failureUrl("/login?error");

        http.csrf().disable();
    }

    @Autowired
    public DaoAuthenticationProvider authProvider() {
        DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider();
        authProvider.setUserDetailsService(userDetailsServiceImpl());
        authProvider.setPasswordEncoder(bCryptPasswordEncoder());

        return authProvider;
    }

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

    @Autowired
    public UserDetailsService userDetailsServiceImpl() {
        return new UserDetailsServiceImpl();
    }
}

public class SecurityWebApplicationInitializer extends AbstractSecurityWebApplicationInitializer {

    public SecurityWebApplicationInitializer() {
        super(SecurityConfiguration.class);
    }

}


@Configuration
@PropertySource(value = "classpath:application.properties")
@ComponentScan(basePackages = {"com.egs.account.*"})
@Import({SecurityConfiguration.class, MvcConfig.class})
public class SpringWebAppInitializer implements WebApplicationInitializer {

    @Autowired
    Environment env;

    @Override
    public void onStartup(ServletContext servletContext) throws ServletException {
        AnnotationConfigWebApplicationContext appContext = new AnnotationConfigWebApplicationContext();
        appContext.register(MvcConfig.class);
        appContext.setServletContext(servletContext);
        ServletRegistration.Dynamic dispatcher = servletContext.addServlet(
                "dispatcher", new DispatcherServlet(appContext));
        dispatcher.setLoadOnStartup(1);
        dispatcher.addMapping("/");
    }

    @Bean
    public static PropertySourcesPlaceholderConfigurer propertyPlaceholderConfigurer() {
        return new PropertySourcesPlaceholderConfigurer();
    }
}

当我运行应用程序时,我得到了这样的异常。

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'userController': Unsatisfied dependency expressed through field 'securityService': Error creating bean with name 'securityServiceImpl': Unsatisfied dependency expressed through field 'authenticationManager': No qualifying bean of type [org.springframework.security.authentication.AuthenticationManager] found for dependency [org.springframework.security.authentication.AuthenticationManager]: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [org.springframework.security.authentication.AuthenticationManager] found for dependency [org.springframework.security.authentication.AuthenticationManager]: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'securityServiceImpl': Unsatisfied dependency expressed through field 'authenticationManager': No qualifying bean of type [org.springframework.security.authentication.AuthenticationManager] found for dependency [org.springframework.security.authentication.AuthenticationManager]: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [org.springframework.security.authentication.AuthenticationManager] found for dependency [org.springframework.security.authentication.AuthenticationManager]: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}

我的UserController的这一部分。

@Controller
public class UserController {

    private UserService userService;

    @Autowired
    private CatalogService catalogService;

    @Autowired
    private SecurityService securityService;
}

这个是我的SecurityServiceImpl

@Service("securityServiceImpl")
public class SecurityServiceImpl implements SecurityService {

    @Autowired
    private AuthenticationManager authenticationManager;

    @Autowired
    private UserDetailsService userDetailsService;

    private static final Logger logger = LoggerFactory.getLogger(SecurityServiceImpl.class);

    @Override
    public String findLoggedInUsername() {
        Object userDetails = SecurityContextHolder.getContext().getAuthentication().getDetails();
        if (userDetails instanceof UserDetails) {
            return ((UserDetails) userDetails).getUsername();
        }

        return null;
    }

    @Override
    public void autoLogin(String username, String password) {
        UserDetails userDetails = userDetailsService.loadUserByUsername(username);
        UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken =
                new UsernamePasswordAuthenticationToken(userDetails, password, userDetails.getAuthorities());

        authenticationManager.authenticate(usernamePasswordAuthenticationToken);

        if (usernamePasswordAuthenticationToken.isAuthenticated()) {
            SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
            logger.debug(String.format("Auto login %s successfully!", username));
        }
    }
}

谁能告诉我还有什么我忘记补充的,因为我遇到了如此可怕的例外。

2 个答案:

答案 0 :(得分:-1)

之上将@Autowired替换为@Bean
public DaoAuthenticationProvider authProvider()
SecurityConfiguration.java中的

由于没有用于AuthenticationManager的bean,因此您获得了该异常。

答案 1 :(得分:-2)

问题看起来像 -

        auth.authenticationProvider(authProvider())
            .inMemoryAuthentication()
            .withUser("user").password("password").roles("USER");

您正在将memoryRealm与您的authProvider()混合使用 - 但是不要在xml中使用memoryRealm?您是否可以尝试将其剥离以使用memoryRealm来确认您可以创建身份验证管理器

我希望它会像 -

auth.authenticationProvider(authProvider())