8 Eylül 2020 Salı

SpringSecurity UserDetailsService Arayüzü - Sadece Kullanıcıyı Yükler

Giriş
Şu satırı dahil ederiz
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
İskeleti şöyle
public interface UserDetailsService {
  UserDetails loadByUserName(String var1) throws UserNameNotFoundException;
}
Bu arayüzü gerçekleştiren sınıflardan bazıları şöyle
- JdbcUserDetailsManager

Kullanım
3 farklı kullanım olabilir.

1. WebSecurityConfigurerAdapter sınıfının configure(AuthenticationManagerBuilder) metodu override edilir. Bu nesneye 
- AuthenticaionProvider veya 
- UserDetailsService takılır veya 
- AuthenticationManagerBuilder sınıfının örneğin jdbcAuthentication() bir bir configurer sınıfı kullanılır

2. WebSecurityConfigurerAdapter  sınıfının userDetailsService() metodu override edilir.
Bu kullanım HttpBasic Authentication kullanılıyorsa tercih edilir.

3. Müstakil bir UserDetailsService bean'i yaratılır. Spring otomatik olarak bizim için kendi UserDetailsService sınıfımızı kullanan bir AuthenticationManager yaratır. Açıklaması şöyle
All we need to do to enable our custom UserDetailsService is add it to our application context as a bean.

Since we configured our class with the @Service annotation, the application will automatically detect it during component-scan, and it will create a bean out of this class. Therefore, there isn't anything else we need to do here.

Alternatively, we can:

- configure it in the authenticationManager using the AuthenticationManagerBuilder#userDetailsService method (1)
- set it as a property in a custom authenticationProvider bean, and then inject that using the AuthenticationManagerBuilder# authenticationProvider function (2)
Örnek - 1 İçin
Şöyle yaparız. Burada özel bir AuthenticationProvider nesnesi yaratılıyor.
@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
  @Autowired
  private UserService userService;

  @Bean
  public BCryptPasswordEncoder passwordEncoder() {
    return new BCryptPasswordEncoder();
  }

  @Override
  protected void configure(HttpSecurity http) throws Exception {
    http....;
  }

  @Bean
  public DaoAuthenticationProvider authenticationProvider() {
    DaoAuthenticationProvider auth = new DaoAuthenticationProvider();
    auth.setUserDetailsService(userService);
    auth.setPasswordEncoder(passwordEncoder());
    return auth;
  }

  @Override
  protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    auth.authenticationProvider(authenticationProvider());
  }
}
Örnek - 1 İçin
Şöyle yaparız
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {

  @Autowired
  UserDetailsService userDetailsService;

  @Override
  public void configure(AuthenticationManagerBuilder authenticationManagerBuilder)
    authenticationManagerBuilder
    .userDetailsService(userDetailsService)
    .passwordEncoder(bCryptPasswordEncoder());
  }
}
Örnek - 2 İçin
InMemoryUserDetailsManager yazısına taşıdım.

Örnek - 3 İçin
Şöyle yaparız. Burada hiç bir özel kodlama yok
@Configuration
@EnableWebSecurity
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {

  @Autowired
  private BCryptPasswordEncoder bCryptPasswordEncoder;

  @Autowired
  private MyUserDetailsService userDetailsService;

  @Override
  protected void configure(HttpSecurity http) throws Exception {
    http...;
  }
  ...
}
loadUserByUsername metodu
İmzası şöyleUserDetails arayüzü döner. 
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException;
Bu arayüzü gerçekleştiren sınıflardan birisi org.springframework.security.core.userdetails.User(...); Bu nesne userName + hashedPassword + GrantedAuthority listesi alır. GrantedAuthority arayüzü olarak SimpleGrantedAuthority kullanılabilir.

Örnek - Transactional
Şöyle yaparız
@Service
public class MyUserDetailsService implements UserDetailsService {

  @Autowired
  private UserService userService;

  @Override
  @Transactional
  public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException{
    User user = userService.findUserByEmail(email);
    if(user == null || user.getActive() == null){
      throw new UsernameNotFoundException("User not found!");
    }

    List<GrantedAuthority> authorities = getUserAuthority(user.getRoles());
    return buildUserForAuthentication(user, authorities);
  }
  ...
}
Örnek
Şöyle yaparız
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {

  User user = userRepository.findByEmail(username);
  if (user == null) {
    throw new UsernameNotFoundException("Invalid username or password.");
  }
  return new org.springframework.security.core.userdetails.User(user.getName(),
    user.getPassword(), mapRolesToAuthorities(user.getRoles()));
}

Collection <GrantedAuthority> mapRolesToAuthorities(Collection < Role > roles) {
  return roles.stream()
    .map(role -> new SimpleGrantedAuthority(role.getName()))
    .collect(Collectors.toList());
}
Örnek
Metod exception fırlatırsa kullanıcı doğrulanamaz. Şöyle yaparız.
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
  
  User user=userservice.getUserByusername(username);

  if(user != null && user.isEnabled()) {//here you can check that
    List<GrantedAuthority> authorities = getUserAuthority(user.getRoles());
    return buildUserForAuthentication(user, authorities);
  } 
  else {
    throw new UsernameNotFoundException("username not found");
  }
}
Diğer yardımcı metodlar şöyledir.
List<GrantedAuthority> getUserAuthority(Set<Role> userRoles) {
  Set<GrantedAuthority> roles = new HashSet<>();
  userRoles.forEach((role) -> {
    roles.add(new SimpleGrantedAuthority(role.getRole()));
  });

  List<GrantedAuthority> grantedAuthorities = new ArrayList<>(roles);
  return grantedAuthorities;
}

UserDetails buildUserForAuthentication(User user, List<GrantedAuthority> authorities) {
  return new org.springframework.security.core.userdetails.User(user.getUsername(),
    user.getPassword(), authorities);
}

Hiç yorum yok:

Yorum Gönder