12 Eylül 2021 Pazar

SpringSecurity Custom AuthenticationProvider Nesnesi

Giriş
Yapılması gereken temel şeyler şöyle
1. AbstractAuthenticationToken sınıfından kalıtan kendi token sınıfımız yazılır. MyToken diyelim

2. AuthenticationProvider arayüzünü gerçekleştiren bir sınıf yazılır. MyAuthenticationProvider diyelim.
Bu sınıfın supports metodunda MyToken için true dönülür.

3. Kendi filtre sınıfımızı yazarız. Bu filtre UsernamePasswordAuthenticationFilter filtresinden önce gelmelidir. Açıklaması şöyle
... there is a set of Spring Security filters and one of them is UsernamePasswordAuthenticationFilter.java. We place our filter before it, because from the set of filters, at this filter only the authentication process starts. So we need to place right before it as we update the SecurityContextHolder thread-local.

4. MyAuthenticationProvider nesnesini WebSecurityConfigurerAdapter sınıfına takarız. Bunun için şöyle yaparız
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

  @Autowired
  private final JwtAuthenticationTokenProvider jwtAuthenticationProvider;

  @Override
  protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    auth.authenticationProvider(jwtAuthenticationProvider);
  }
  
}
Örnek
Elimizde harici bir servisi kullanan şöyle bir kod olsun
@Service public class OTPServiceImpl implements OTPService { // Implement your third-party OTP provider here @Override public String generateOTP(String phoneNumber) { // Call the third-party OTP provider to generate an OTP and return it } @Override public boolean validateOTP(String phoneNumber, String otp) { // Call the third-party OTP provider to validate the OTP and return true if valid, // false otherwise } }
Doğrulamayı yapan şöyle bir kod olsun
public class PhoneNumberAuthenticationProvider implements AuthenticationProvider { @Autowired private OTPService otpService; @Override public Authentication authenticate(Authentication authentication) throws AuthenticationException { String phoneNumber = authentication.getName(); String otp = otpService.generateOTP(phoneNumber); // Send the generated OTP to the user's phone number using the third-party provider // Store the generated OTP in the user's session or another storage mechanism for // later validation return null; // Return null since the user is not yet authenticated } @Override public boolean supports(Class<?> authentication) { return PhoneNumberAuthenticationToken.class.isAssignableFrom(authentication); } public Authentication validateOTP(String phoneNumber, String otp) throws AuthenticationException { // Validate the OTP entered by the user using the OTPService boolean isValid = otpService.validateOTP(phoneNumber, otp); if (isValid) { // If the OTP is valid, create an authenticated Authentication object with the // user's phone number List<GrantedAuthority> authorities = new ArrayList<>(); authorities.add(new SimpleGrantedAuthority("ROLE_USER")); PhoneNumberAuthenticationToken authentication = new PhoneNumberAuthenticationToken(phoneNumber, authorities); return authentication; } else { // If the OTP is not valid, throw an AuthenticationException throw new BadCredentialsException("Invalid OTP"); } } }
Filtre için şöyle bir kod olsun
public class PhoneNumberAuthenticationFilter extends AbstractAuthenticationProcessingFilter { public PhoneNumberAuthenticationFilter() { super(new AntPathRequestMatcher("/login/phone", "POST")); } @Override public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException, IOException, ServletException { String phoneNumber = request.getParameter("phoneNumber"); String otp = request.getParameter("otp"); PhoneNumberAuthenticationToken authRequest = new PhoneNumberAuthenticationToken(phoneNumber); Authentication authentication = getAuthenticationManager().authenticate(authRequest); if (authentication == null) { // If the user is not yet authenticated, call the validateOTP method in the // PhoneNumberAuthenticationProvider class PhoneNumberAuthenticationProvider provider = (PhoneNumberAuthenticationProvider) getAuthenticationManager() .getProviders().stream() .filter(p -> p instanceof PhoneNumberAuthenticationProvider) .findFirst() .orElseThrow(() -> new AuthenticationServiceException("PhoneNumberAuthenticationProvider not found")); authentication = provider.validateOTP(phoneNumber, otp); } return authentication; } }
Filtreyi takan şöyle bir kod olsun
@EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Autowired private PhoneNumberAuthenticationProvider phoneNumberAuthenticationProvider; @Override protected void configure(HttpSecurity http) throws Exception { http.addFilterBefore(phoneNumberAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class) .authenticationProvider(phoneNumberAuthenticationProvider) .authorizeRequests() .antMatchers("/login/phone").permitAll() .anyRequest().authenticated(); } @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.authenticationProvider(phoneNumberAuthenticationProvider); } @Bean public PhoneNumberAuthenticationFilter phoneNumberAuthenticationFilter() throws Exception { PhoneNumberAuthenticationFilter filter = new PhoneNumberAuthenticationFilter(); filter.setAuthenticationManager(authenticationManagerBean()); return filter; } @Bean @Override public AuthenticationManager authenticationManagerBean() throws Exception { return super.authenticationManagerBean(); } }




Hiç yorum yok:

Yorum Gönder