Аутентификация с помощью Spring Безопасность + Spring данных + MongoDB
Я хочу использовать Spring безопасность с помощью MongoDB (используя данные Spring) и извлекать пользователей из моей собственной базы данных для безопасности Spring. Однако я не могу этого сделать, поскольку мой тип сервиса не поддерживается.
Это мой класс UserService:
public class UserService {
private ApplicationContext applicationContext;
private MongoOperations mongoOperations;
public UserService() {
applicationContext = new AnnotationConfigApplicationContext(MongoConfig.class);
mongoOperations = (MongoOperations) applicationContext.getBean("mongoTemplate");
}
public User find(String username) {
return mongoOperations.findOne(Query.query(Criteria.where("username").is(username)), User.class);
}
}
И мой класс SecurityConfig:
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
UserService userService;
@Autowired
public void configAuthBuilder(AuthenticationManagerBuilder builder) throws Exception {
builder.userDetailsService(userService); //THIS DOES NOT WORK
builder.inMemoryAuthentication().withUser("username").password("password").roles("USER");
}
}
В строке, которую я прокомментировал, говорится:
The inferred type UserService is not a valid substitute for the bounded parameter <T extends UserDetailsService>.
Как я могу его исправить, чтобы я мог получать пользователей из своей собственной базы данных?
Ответы
Ответ 1
Уровень обслуживания
Вам нужно создать отдельный service
реализацию org.springframework.security.core.userdetails.UserDetailsService
и ввести его в AuthenticationManagerBuilder
.
@Component
public class SecUserDetailsService implements UserDetailsService{
@Autowired
private UserRepository userRepository;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
/*Here add user data layer fetching from the MongoDB.
I have used userRepository*/
User user = userRepository.findByUsername(username);
if(user == null){
throw new UsernameNotFoundException(username);
}else{
UserDetails details = new SecUserDetails(user);
return details;
}
}
}
Model
UserDetails
Должно быть также реализовано. Это POJO, который будет хранить пользовательские данные с помощью Spring. Вы можете включить в него объект данных Entity, как я это сделал.
public class SecUserDetails implements UserDetails {
private User user;
public SecUserDetails(User user) {
this.user = user;
}
......
......
......
}
Конфигурация безопасности
Autowire сервис, который мы создали ранее, и установите его внутри AuthenticationManagerBuilder
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
SecUserDetailsService userDetailsService ;
@Autowired
public void configAuthBuilder(AuthenticationManagerBuilder builder) throws Exception {
builder.userDetailsService(userDetailsService);
}
}
Ответ 2
Создайте собственный поставщик аутентификации, предоставляющий класс, который расширяет UserDetailservice.
Убедитесь, что сканирование содержимого включено в вашем xml файле spring.
<authentication-provider user-service-ref="userModelService">
<password-encoder hash="sha" />
</authentication-provider>
@Service
public class UserModelService implements UserDetailsService
{
@Autowired
private UserModelRepositoryImpl repository;
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException
{
UserModel user = repository.findByUsername(username);
if( user == null )
throw new UsernameNotFoundException( "Name not found!" );
List<SimpleGrantedAuthority> authorities = Arrays.asList(new SimpleGrantedAuthority( user.getRole()));
return new User(user.getUsername(), user.getSHA1Password(), authorities );
}
public void saveUserDetails(UserModel userModel)
{
repository.save(userModel);
}
}
Этот класс включит запрос spring mongo запроса для имени пользователя и пароля, необходимых для аутентификации. Затем создайте класс модели пользователя.
public class UserModel
{
private String id;
@Indexed(unique=true)
private String username;
private String password;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
Создайте класс реализации пользователя, который расширяет DAO.
@Service
public class UserModelService implements UserDetailsService
{
@Autowired
private UserModelRepositoryImpl repository;
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException
{
UserModel user = repository.findByUsername(username);
if( user == null )
throw new UsernameNotFoundException( "Oops!" );
List<SimpleGrantedAuthority> authorities = Arrays.asList(new SimpleGrantedAuthority( user.getRole()));
return new User(user.getUsername(), user.getSHA1Password(), authorities );
}
Наконец настройте манго, и все готово.