将数据库身份验证添加到Spring Data Rest应用程序中



我正在使用带有Thymelaf的Spring Data REST创建一个应用程序。

最初,我创建了我的模型、控制器、dao和服务。一切都很好。我现在正在尝试为我的应用程序添加安全性。现在我只关注登录/注销。

我已经能够创建如下的内存中身份验证:

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {


@Autowired
@Qualifier("securityDataSource")
private DataSource securityDataSource;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {

// add users for in memory authentication
UserBuilder users = User.withDefaultPasswordEncoder();

auth.inMemoryAuthentication()
.withUser(users.username("paul").password("test123").roles("MEMBER", "ADMIN"))
.withUser(users.username("sandra").password("test123").roles("MEMBER", "ADMIN"))
.withUser(users.username("matthew").password("test123").roles("MEMBER"));
}
}

不过,我想将其更改为数据库身份验证。我确信我可以创建一个jdbc连接,并将我的配置方法更改为这样的方法:

@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.jdbcAuthentication().dataSource(securityDataSource);

}

我的问题是,我已经在通过我的DAO接口访问数据库了。例如:

public interface UserRepository extends JpaRepository<User, Integer> {

// method to sort by last name
public List<User> findAllByOrderByLastNameAsc();
}

我的用户表有一个电子邮件和密码列,将用作用户名/密码。

是否也可以通过某种方式使用它进行身份验证?我可以提供更多的信息,但我不愿意只是发布所有的信息,希望有人能为我写出来

由于您已经创建了DAO接口,因此创建DAO接口可能更容易UserDetailsService实现:

@Service
@NoArgsConstructor @ToString @Log4j2
public class UserDetailsServiceImpl implements UserDetailsService {
@Autowired private UserRepository userRepository = null;
@Override
@Transactional(readOnly = true)
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
org.springframework.security.core.userdetails.User user = null;
try {
Optional<User> optional = userRepository.findBy...(username);
HashSet<GrantedAuthority> set = new HashSet<>();
/*
* Add SimpleGrantedAuthority to set as appropriate
*/
user = new org.springframework.security.core.userdetails.User(username, optional.get().getPassword(), set);
} catch (UsernameNotFoundException exception) {
throw exception;
} catch (Exception exception) {
throw new UsernameNotFoundException(username);
}
return user;
}
}

并将其连接到:

@Autowired private UserDetailsService userDetailsService = null;
... private PasswordEncoder passwordEncoder = ...;
@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService)
.passwordEncoder(passwordEncoder);
}

为了更加清晰,以下是我实现的完整上下文:

@Service
@NoArgsConstructor @ToString @Log4j2
public class UserDetailsServiceImpl implements UserDetailsService {
@Autowired private CredentialRepository credentialRepository = null;
@Autowired private AuthorityRepository authorityRepository = null;
@Override
@Transactional(readOnly = true)
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = null;
try {
Optional<Credential> credential = credentialRepository.findById(username);
Optional<Authority> authority = authorityRepository.findById(username);
HashSet<GrantedAuthority> set = new HashSet<>();
if (authority.isPresent()) {
authority.get().getGrants().stream()
.map(Authorities::name)
.map(SimpleGrantedAuthority::new)
.forEach(set::add);
}
user = new User(username, credential.get().getPassword(), set);
} catch (UsernameNotFoundException exception) {
throw exception;
} catch (Exception exception) {
throw new UsernameNotFoundException(username);
}
return user;
}
}

假设db表名为users和authority。dataSource在application.yml.中配置

@Autowired
private DataSource dataSource;

@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.jdbcAuthentication()
.dataSource(dataSource)
.usersByUsernameQuery("select username,password,enabled from users WHERE username=?")
.authoritiesByUsernameQuery("select username,authority from authorities where username=?")
.passwordEncoder(new BCryptPasswordEncoder());
}
}

最新更新