使用Hibernate进行Spring Security 3数据库身份验证


Answers:


134

您必须制作自己的自定义身份验证提供程序。

示例代码:

从Hibernate加载用户的服务:

import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;    

@Service("userDetailsService") 
public class UserDetailsServiceImpl implements UserDetailsService {

  @Autowired private UserDao dao;
  @Autowired private Assembler assembler;

  @Transactional(readOnly = true)
  public UserDetails loadUserByUsername(String username)
      throws UsernameNotFoundException, DataAccessException {

    UserDetails userDetails = null;
    UserEntity userEntity = dao.findByName(username);
    if (userEntity == null)
      throw new UsernameNotFoundException("user not found");

    return assembler.buildUserFromUserEntity(userEntity);
  }
}

将您的实体转换为spring用户对象的服务:

import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.GrantedAuthorityImpl;
import org.springframework.security.core.userdetails.User;

@Service("assembler")
public class Assembler {

  @Transactional(readOnly = true)
  User buildUserFromUserEntity(UserEntity userEntity) {

    String username = userEntity.getName();
    String password = userEntity.getPassword();
    boolean enabled = userEntity.isActive();
    boolean accountNonExpired = userEntity.isActive();
    boolean credentialsNonExpired = userEntity.isActive();
    boolean accountNonLocked = userEntity.isActive();

    Collection<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
    for (SecurityRoleEntity role : userEntity.getRoles()) {
      authorities.add(new GrantedAuthorityImpl(role.getRoleName()));
    }

    User user = new User(username, password, enabled,
      accountNonExpired, credentialsNonExpired, accountNonLocked, authorities, id);
    return user;
  }
}

基于命名空间的application-context-security.xml如下所示:

<http>
  <intercept-url pattern="/login.do*" filters="none"/>
  <intercept-url pattern="/**" access="IS_AUTHENTICATED_ANONYMOUSLY" />
  <form-login login-page="/login.do"
              authentication-failure-url="/login.do?error=failed"
              login-processing-url="/login-please.do" />
  <logout logout-url="/logoff-please.do"
          logout-success-url="/logoff.html" />
</http>

<beans:bean id="daoAuthenticationProvider"
 class="org.springframework.security.authentication.dao.DaoAuthenticationProvider">
  <beans:property name="userDetailsService" ref="userDetailsService"/>
</beans:bean>

<beans:bean id="authenticationManager"
    class="org.springframework.security.authentication.ProviderManager">
  <beans:property name="providers">
    <beans:list>
      <beans:ref local="daoAuthenticationProvider" />
    </beans:list>
  </beans:property>
</beans:bean>

<authentication-manager>
  <authentication-provider user-service-ref="userDetailsService">
    <password-encoder hash="md5"/>
  </authentication-provider>
</authentication-manager>

3
感谢您提供完整代码的详尽解答。你能告诉我为什么需要Assembler类吗,为什么不把那个代码放在loadUserByUsername方法中呢?
newbie 2010年

1
没错,汇编器没有真正的需求。只是认为这是个好主意,使userDetailsS​​ervice保持简单并使转换可通过汇编器服务重用。
Kdeveloper

2
自动装配如何为userDetailsS​​ervice工作,我的自动装配不工作。我必须在安全性xml中定义userDetailsS​​ervice bean。任何想法。自动
布线的

2
@Nikola您不会检查自己的密码(哈希)是否匹配,Spring Security会自动为您执行此操作。如果密码错误,那么Spring Security将重定向到Spring Security XML配置中定义的错误URL。您只需要提供User对象,即可通过正确的哈希算法对密码进行哈希处理。您还可以根据需要使用密码盐,但这需要更多配置。
新手2012年

7
GrantedAuthorityImpl不推荐使用,SimpleGrantedAuthority而是改用
Carlos

4

如果使用的是JDBC可访问的数据库,则可以使用以下身份验证提供程序,而避免创建自定义数据库。它将所需的代码缩减为9行XML:

<authentication-provider>
    <jdbc-user-service data-source-ref="dataSource" users-by-username-query="select username,password from users where username=?" authorities-by-username-query="select u.username, r.authority from users u, roles r where u.userid = r.userid and u.username =?" />
</authentication-provider>

然后,您可以按照以下步骤设置dataSource

<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    <property name="driverClassName" value="com.mysql.jdbc.Driver" />
    <property name="url" value="jdbc:mysql://localhost:3306/DB_NAME" />
    <property name="username" value="root" />
    <property name="password" value="password" />
</bean>

看一下这篇文章: http //codehustler.org/blog/spring-security-tutorial-form-login/ 它涵盖了有关定制Spring Security表单登录所需的所有知识。


我们可以将其与哈希密码一起使用吗?
拉斐尔

1
您应该能够使用<authentication-provider>标记中的<password-encoder ref =“ encoder” />对哈希密码进行哈希处理。编码器引用您希望使用的编码bean,例如org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder。另外,如果您希望使用SHA之类的东西,则可以添加<password-encoder hash =“ sha” />
Alessandro Giannone 2015年

1

Java配置可能看起来像这样

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private UserDetailsServiceImpl userDetailsService;

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

        DaoAuthenticationProvider daoAuthenticationProvider =
                new DaoAuthenticationProvider();
        daoAuthenticationProvider
                .setUserDetailsService(userDetailsService);

        auth.authenticationProvider(daoAuthenticationProvider);
    }
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.