java - 如何使用 Spring-Security 3 和 Hibernate 4 将 spring security xml 配置 hibernate 转换为 java 配置

标签 java hibernate authentication configuration spring-security

我刚刚了解了 spring security,并想使用 java hibernate 配置连接到数据库,但我发现很少有示例或教程。我通过使用 xml 配置找到了更多信息。我在这里使用 Spring 4.0.2、Spring-Security 3.2.0 和 Hibernate 4.3.2

我的问题是: 下面的xml如何转换成java配置?

<authentication-manager>
    <authentication-provider user-service-ref="customUserDetailsService">
        <password-encoder hash="plaintext">
    </password-encoder></authentication-provider>
</authentication-manager>

其中CustomUserDetailsS​​ervice.java

package com.whatever.svtest.service.impl;

import java.util.ArrayList;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.whatever.svtest.dao.UserDao;

@Service
@Transactional(readOnly = true)
public class CustomUserDetailsService implements UserDetailsService {

    @Autowired
    private UserDao userDao;

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

        com.whatever.svtest.model.User domainUser = userDao.getByUsername(username);

        if (domainUser == null) {
            throw new UsernameNotFoundException("user not found");
        }

        List<SimpleGrantedAuthority> authorities = new ArrayList<SimpleGrantedAuthority>();
        authorities.add(new SimpleGrantedAuthority("USER"));        

        return new User(username, domainUser.getPassword(), true, true, true, true, authorities);
    }

}

在SecurityConfig.java上,我使用spring创建的默认登录表单。我正在尝试自己弄清楚如何将 xml 配置转换为 java 配置。

package com.whatever.svtest.init;

import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;

import com.whatever.svtest.service.impl.UserServiceImpl;

@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {

        auth.userDetailsService(new UserServiceImpl()).passwordEncoder(NoOpPasswordEncoder.getInstance());

    }

}

我将 SecurityConfiguration.java 放在 Initializer.java 上,如下所示

package com.whatever.svtest.init;

import javax.servlet.Filter;

import org.springframework.web.filter.DelegatingFilterProxy;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;

public class Initializer extends AbstractAnnotationConfigDispatcherServletInitializer {

    @Override
    protected Class<?>[] getRootConfigClasses() {
        // return null;
        return new Class[] { SecurityConfiguration.class };
    }

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

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

    @Override
    protected Filter[] getServletFilters() {
        return new Filter[] { new DelegatingFilterProxy("springSecurityFilterChain") };
    }

}

WebAppConfig.java

package com.whatever.svtest.init;

import javax.annotation.Resource;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.PropertySource;
import org.springframework.context.support.ResourceBundleMessageSource;
import org.springframework.core.env.Environment;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.view.InternalResourceViewResolver;

@Configuration
@EnableWebMvc
@Import({ DatabaseConfig.class })
@ComponentScan(basePackages = { "com.whatever.svtest.controller" })
@PropertySource({ "classpath:persistence-mysql.properties" })
public class WebAppConfig extends WebMvcConfigurerAdapter {

    @Resource   
    private Environment env;

    @Override   
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/assets/**").addResourceLocations("/assets/");
    }

    @Bean
    public ResourceBundleMessageSource messageSource() {
        ResourceBundleMessageSource source = new ResourceBundleMessageSource();
        source.setBasename("messages");
        source.setUseCodeAsDefaultMessage(true);
        return source;
    }

    @Bean
    public ViewResolver setupViewResolver() {
        InternalResourceViewResolver resolver = new InternalResourceViewResolver();
        resolver.setPrefix("/WEB-INF/view/");
        resolver.setSuffix(".jsp");
        return resolver;
    }

}

当我运行我的网络应用程序时,我得到了这个。 (我把图片放在这里/image/Mssrc.jpg)

我还(在某处)阅读了有关创建 AuthenticationProvider.java 的自定义实现的信息,但我不知道在哪里放置此代码..

package com.whatever.svtest.init;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;

import com.whatever.svtest.dao.UserDao;
import com.whatever.svtest.model.User;

public class MyAuthProvider implements AuthenticationProvider {

    @Autowired
    private UserDao userDao;

    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        String name = authentication.getName();
        String password = authentication.getCredentials().toString();
        User user = userDao.getByUsername(name);
        authentication.setAuthenticated(user != null && password.equals(user.getPassword()));
        return authentication;
    }

    @Override
    public boolean supports(Class<?> authentication) {

        return (MyAuthProvider.class.isAssignableFrom(authentication));
    }

}

最佳答案

配置不一致?

您发布的配置对我来说不太有意义。具体如下:

protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    auth.userDetailsService(new UserServiceImpl()).passwordEncoder(NoOpPasswordEncoder.getInstance());
}

解决方案

看来您还没有定义 UserServiceImpl,但您已经定义了 CustomUserDetailsS​​ervice (这可能是应该传入的参数。但是,为了 Autowiring bean,您需要将其创建为 bean。所以您应该这样更改您的配置:

protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    auth.userDetailsService(uds());
}

@Bean
public CustomUserDetailsService uds() {
    return new CustomUserDetailsService();
}

通过将 CustomUserDetailsS​​ervice 作为 @Bean 返回,您可以确保 Spring 正确地 Autowiring 它。

一些附加说明:

  • 您不需要自定义 AuthenticationProvider。这是因为您使用用户名/密码进行身份验证,UserDetailsS​​ervice 就可以了。如果您想使用用户名/密码以外的其他内容进行身份验证,您可以创建一个自定义的 AuthenticationProvider
  • 无需指定无操作密码编码器,因为这是默认值。

改进 CustomUserDetailsS​​ervice

在当前的实现中需要指出的一件事是,虽然您可以直接 @Autowire 字段,但它会更容易犯错误,因此您可能应该更改 CustomUserDetailsS​​ervice 以具有允许注入(inject) UserDao 的构造函数。这也使得单元测试更加容易(因此您不需要使用反射来设置 UserDao)。因此,您可以将 CustomUserDetailsS​​ervice 更新为:

@Service
@Transactional(readOnly = true)
public class CustomUserDetailsService implements UserDetailsService {

    private UserDao userDao;

    @Autowired
    public CustomUserDetailsService(UserDao userDao) {
        this.userDao = userDao;
    }

那么您的配置可以如下:

protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    auth.userDetailsService(uds());
}

@Autowired
private UserDao userDao;

@Bean
public CustomUserDetailsService uds() {
    return new CustomUserDetailsService(userDao);
}

根据新错误进行更新

您还需要确保您的 UserDao 被作为 Bean 选取。例如:

@Bean
public UserDao userDao() {
    return new UserDao(...);
}

注意:确保正确初始化 UserDao(即确保其所有依赖项均已初始化。如果您在 UserDao 上使用 Autowired,请确保这些依赖项也是 @Bean

关于java - 如何使用 Spring-Security 3 和 Hibernate 4 将 spring security xml 配置 hibernate 转换为 java 配置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22176693/

相关文章:

java - 在java中维护线程中变量的值

php - 使用常规登录密码保护 Magento Storeview

java - 如何使用 getText() 从不同类的字段中获取文本

java - 用 retrofit2 发送这个 formjson

java - Apache Kafka 0.9 Java API 使用主题开头的所有消息

java - 覆盖绘制而不扩展 JFrame

java - 使用 Hibernate 查询

database - Grails:从外部加载数据后更新 hibernate

PHP 登录代码未设置永久 Cookie(通过浏览器关闭)

java - 尽管捕获了异常,线程仍然运行