如何使用SpringSecurity3和Hibernate4将SpringSecurityXML配置hibernate转换为java配置

如何使用SpringSecurity3和Hibernate4将SpringSecurityXML配置hibernate转换为java配置,java,hibernate,login,configuration,spring-security,Java,Hibernate,Login,Configuration,Spring Security,我刚刚学习了spring安全性,并希望使用JavaHibernate配置连接到数据库,但我发现很少有示例或教程。通过使用xml配置,我发现了更多。我在这里使用Spring4.0.2、SpringSecurity3.2.0和Hibernate4.3.2 我的问题是: 以下xml如何转换为java配置? <authentication-manager> <authentication-provider user-service-ref="customUserDetailsS

我刚刚学习了spring安全性,并希望使用JavaHibernate配置连接到数据库,但我发现很少有示例或教程。通过使用xml配置,我发现了更多。我在这里使用Spring4.0.2、SpringSecurity3.2.0和Hibernate4.3.2

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

<authentication-manager>
    <authentication-provider user-service-ref="customUserDetailsService">
        <password-encoder hash="plaintext">
    </password-encoder></authentication-provider>
</authentication-manager>
我将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") };
    }

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

我还(在某处)读到了关于创建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));
    }

}
package com.whatever.svtest.init;
导入org.springframework.beans.factory.annotation.Autowired;
导入org.springframework.security.authentication.AuthenticationProvider;
导入org.springframework.security.core.Authentication;
导入org.springframework.security.core.AuthenticationException;
导入com.whater.svtest.dao.UserDao;
导入com.whatever.svtest.model.User;
公共类MyAuthProvider实现AuthenticationProvider{
@自动连线
私有UserDao UserDao;
@凌驾
公共身份验证(身份验证)引发AuthenticationException{
String name=authentication.getName();
字符串密码=authentication.getCredentials().toString();
User=userDao.getByUsername(名称);
authentication.setAuthenticated(user!=null&&password.equals(user.getPassword());
返回认证;
}
@凌驾
公共布尔支持(类身份验证){
返回(MyAuthProvider.class.isAssignableFrom(身份验证));
}
}

配置不一致?

<authentication-manager>
    <authentication-provider user-service-ref="customUserDetailsService">
        <password-encoder hash="plaintext">
    </password-encoder></authentication-provider>
</authentication-manager>
你发布的配置对我来说不太合理。具体如下:

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

@Autowired
private UserDao userDao;

@Bean
public CustomUserDetailsService uds() {
    return new CustomUserDetailsService(userDao);
}
解决方案

您似乎没有定义UserServiceImpl,但定义了CustomUserDetailsService(这可能是应该传入的参数。但是,为了使bean自动连接,您需要将其创建为bean。因此,您应该更改配置:

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

@Bean
public CustomUserDetailsService uds() {
    return new CustomUserDetailsService();
}
通过将CustomUserDetailsService作为@Bean返回,您可以确保Spring正确地自动连接它

还有几点需要注意:

  • 您不需要自定义AuthenticationProvider。这是因为您正在使用用户名/密码进行身份验证,UserDetails服务很好。如果您希望使用用户名/密码以外的内容进行身份验证,则可以创建自定义AuthenticationProvider
  • 无需指定无操作密码编码器,因为这是默认值
改进CustomUserDetails服务

需要指出的一点是,虽然您可以直接@Autowire字段,但这会使出错变得更容易,因此您可能应该将CustomUserDetails服务更改为具有允许注入UserDao的构造函数。这也使单元测试更容易(因此,您不需要使用反射来设置UserDao)。因此,您可以将CustomUserDetailsService更新为:

@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(new UserServiceImpl()).passwordEncoder(NoOpPasswordEncoder.getInstance());
}
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

[SOLVED]

经过两天的努力,我终于找到了解决方案

@Configuration
@EnableWebSecurity
@ComponentScan(basePackageClasses = SecurityConfiguration.class)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Autowired
    private UserService userService;

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userService);
    }

}
我不需要创建新的bean。我只需要将UserService对象传递到userDetailsService方法中,将自动连线,当然还要将@ComponentScan用于当前类。UserService类已经有了一个UserDao,我实现了它其中的用户详细信息服务

@Service("userService")
@Transactional(readOnly = true)
public class UserServiceImpl implements UserService, UserDetailsService {

    @Autowired
    private UserDao userDao;

    // other method

    @Override
    public User getByUsername(String username) {
        return userDao.getByUsername(username);
    }

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        User user = getByUsername(username);
        if (user == null) {
            throw new UsernameNotFoundException("user not found");
        } else {
            List<GrantedAuthority> listAuthorities = new ArrayList<GrantedAuthority>();
            listAuthorities.add(new SimpleGrantedAuthority("ROLE_USER"));
            return new org.springframework.security.core.userdetails.User(username, user.getPassword(), true, true, true, true, listAuthorities);
        }

    }
}
@Service(“用户服务”)
@事务(只读=真)
公共类UserServiceImpl实现UserService、UserDetailsService{
@自动连线
私有UserDao UserDao;
//其他方法
@凌驾
公共用户getByUsername(字符串用户名){
返回userDao.getByUsername(用户名);
}
@凌驾
public UserDetails loadUserByUsername(字符串用户名)引发UsernameNotFoundException{
User User=getByUsername(用户名);
if(user==null){
抛出新的UsernameNotFoundException(“未找到用户”);
}否则{
List ListAuthories=new ArrayList();
添加(新的SimpleGrantedAuthority(“角色用户”);
返回新的org.springframework.security.core.userdetails.User(username,User.getPassword(),true,true,true,listAuthories);
}
}
}

感谢Rob Winch提供的线索。

我能知道您为什么特别寻找注释来配置spring安全性吗?至少对于spring安全性来说,将其作为xml配置具有更大的优势,这样可以在不接触现有代码的情况下灵活地对其进行更改。您可以在是link hi Jay,我没有理由“为什么”。我是spring framework的新手。我从3周前开始学习spring framework。最近我看到了很多变化。所有内容都从xml转换为java配置。所以,为什么我不学习最新的一个呢谢谢你的回答。我按照你的指示去做。但是它仍然不起作用。我发现了错误我找到了这个链接()它解决了我的问题虽然它不使用hibernate,但是正如你说的“我不需要自定义”AuthenticationProvider它让我更加困惑。你的UserDao也需要被定义为一个Bean。查看我的更新