JavaRush /Java Blogu /Random-AZ /Qeydlər xidmətinin nümunəsindən istifadə edərək, e-poçt v...

Qeydlər xidmətinin nümunəsindən istifadə edərək, e-poçt və OAuth2 vasitəsilə Spring Security-ə müntəzəm giriş təqdim edək

Qrupda dərc edilmişdir
Ərizəmi yazarkən istifadəçinin həm e-poçt, həm də sosial şəbəkələr vasitəsilə qeydiyyatdan keçməsinə dair aydın məqalələrin çatışmazlığı ilə üzləşdim. Klassik giriş formasının qurulması ilə bağlı yaxşı dərsliklər var idi. OAuth2 -də yaxşı dərsliklər var idi . İki metodun necə birləşdiriləcəyinə dair cinayət baxımından az məlumat var idi. Axtarış prosesində biz işlək həll yolu tapdıq. O, son həqiqət olduğunu iddia etmir, lakin öz funksiyasını yerinə yetirir. Bu yazıda mən sıfırdan oxşar Spring Security konfiqurasiyası ilə qeyd saxlama xidmətinin necə həyata keçiriləcəyini göstərəcəyəm. Qeydlər xidmətinin nümunəsindən istifadə edərək, e-poçt və OAuth2 vasitəsilə Spring Security-ə müntəzəm giriş təqdim edək - 1Qeyd: Oxucu ən azı Baharla bağlı bir neçə dərslikdən keçsə yaxşıdır, çünki anbarlar, nəzarətçilər və s. haqqında ətraflı izahat verilmədən diqqət yalnız Bahar Təhlükəsizliyinə yönəldiləcək. Əks halda, onsuz da kifayət qədər böyük məqalə çıxacaq. nəhəng olmaq. Məzmun
  1. Layihənin yaradılması
  2. Müəssisələrin yaradılması və Tətbiq Məntiqi
    1. Müəssisələr
    2. Anbarlar
    3. Nəzarətçilər
    4. Səhifələr
  3. Klassik Giriş üçün Bahar Təhlükəsizlik Konfiqurasiyası
    1. Əsas konfiqurasiya SecurityConfig
    2. Fərdi istifadəçi girişi
    3. Nəzarətçini təkmilləşdirək
    4. Başlayın
  4. Spring Security-də Google-dan istifadə edərək OAuth2-nin qurulması
    1. Filtr konfiqurasiyası və application.properties
    2. Tətbiqin Google Bulud Platforması ilə qeydiyyata alınmasının əsas məqamları
    3. CustomUserInfoTokenServices
  5. Layihənin yekun açılışı

Layihənin yaradılması

start.spring.io saytına gedirik və layihənin əsasını təşkil edirik:
  • Veb - daxili Tomcat, url xəritələri və s.-də tətbiqin işə salınması;
  • JPA - verilənlər bazası bağlantısı;
  • Bığ veb səhifələr yaratmaq üçün istifadə edilən şablon mühərrikidir;
  • Təhlükəsizlik - proqram qorunması. Bu məqalə bunun üçün yaradılmışdır.
Yaranan arxivi yükləyin və lazım olan qovluğa açın. Biz onu IDE-də işə salırıq. Siz öz mülahizənizlə verilənlər bazasını seçə bilərsiniz. Layihə üçün verilənlər bazası kimi MySQL-dən istifadə edirəm, ona görə də <dependencies> blokunda pom.xml faylına aşağıdakı asılılığı əlavə edirəm:
<dependency>
     <groupId>mysql</groupId>
     <artifactId>mysql-connector-java</artifactId>
     <version>5.1.34</version>
</dependency>
application.properties konfiqurasiyası hazırda aşağıdakı kimidir:
spring.datasource.url=jdbc:mysql://localhost:3306/springsectut?createDatabaseIfNotExist=true&useSSL=false&autoReconnect=true&useLegacyDatetimeCode=false&serverTimezone=UTC&useUnicode=yes&characterEncoding=UTF-8
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.username=yourUsername
spring.datasource.password=yourPassword

spring.jpa.generate-ddl=true
spring.jpa.hibernate.ddl-auto=update

spring.jpa.properties.connection.characterEncoding=utf-8
spring.jpa.properties.connection.CharSet=utf-8
spring.jpa.properties.connection.useUnicode=true

spring.mustache.expose-request-attributes=true

Müəssisələrin yaradılması və Tətbiq Məntiqi

Müəssisələr

entitiesVerilənlər bazası obyektlərini yerləşdirəcəyimiz bir paket yaradaq . İstifadəçi, Spring Security konfiqurasiyası üçün lazım olan Userinterfeysi həyata keçirən sinif tərəfindən təsvir ediləcək. UserDetailsİstifadəçinin id, istifadəçi adı (bu e-poçtdur), parol, ad, rol, fəaliyyət bayrağı, Google hesabının adı və e-poçtu ( googleNamegoogleUsername) olacaq.
@Entity
@Table(name = "user")
public class User implements UserDetails
{
  @Id
  @GeneratedValue(strategy = GenerationType.AUTO)
  private Long id;

  private String username;
  private String password;
  private String name;
  private boolean active;
  private String googleName;
  private String googleUsername;

  @ElementCollection(targetClass = Role.class, fetch = FetchType.EAGER)
  @CollectionTable(name = "user_role", joinColumns = @JoinColumn(name = "user_id"))
  @Enumerated(EnumType.STRING)
  private Set<Role> roles;

    //Геттеры, сеттеры, toString(), equals(), hashcode(), имплементация UserDetails
}
İstifadəçi rolları Spring Security-də girişi tənzimləmək üçün istifadə olunur. Tətbiqimiz yalnız bir roldan istifadə edəcək:
public enum Role implements GrantedAuthority
{
  USER;

  @Override
  public String getAuthority()
  {
     return name();
  }
}
Gəlin id, qeyd başlığı, qeyd gövdəsi və aid olduğu istifadəçinin id-si ilə qeyd sinfi yaradaq:
@Entity
@Table(name = "note")
public class Note
{
  @Id
  @GeneratedValue(strategy = GenerationType.AUTO)
  private Long id;

  private String title;
  private String note;
  private Long userId;

    //Геттеры, сеттеры, toString(), equals(), hashcode()
}

Anbarlar

Müəssisələri verilənlər bazasında saxlamaq üçün bizim üçün bütün çirkli işləri görəcək depolara ehtiyacımız var. Gəlin bir paket yaradaq , onda biz interfeysdən miras qalmış reposinterfeysləri yaradacağıq . UserRepoNoteRepoJpaRepository<Entity, Id>
@Service
@Repository
public interface UserRepo extends JpaRepository<User, Long>
{}

@Service
@Repository
public interface NoteRepo extends JpaRepository<Note, Long>
{
  List<Note> findByUserId(Long userId);
}

Nəzarətçilər

Qeydlər xidmətimizdə aşağıdakı səhifələr olacaq:
  • Ev;
  • Qeydiyyat;
  • Giriş;
  • İstifadəçi qeydlərinin siyahısı.
Yalnız səlahiyyətli istifadəçi qeydlər siyahısına daxil ola bilər. Qalan səhifələr açıqdır. Əsas səhifənin adi get-mappingini ehtiva edən controllerssinifdən ibarət paket yaradaq . IndexControllerSinif RegistrationControlleristifadəçinin qeydiyyatına cavabdehdir. Post-mapping məlumatı formadan götürür, istifadəçini verilənlər bazasında saxlayır və giriş səhifəsinə yönləndirir. PasswordEncodersonra təsvir olunacaq. Parolları şifrələmək üçün istifadə olunur.
@Controller
public class RegistrationController
{
  @Autowired
  private UserRepo userRepo;

  @Autowired
  private PasswordEncoder passwordEncoder;

  @GetMapping("/registration")
  public String registration()
  {
     return "registration";
  }

  @PostMapping("/registration")
  public String addUser(String name, String username, String password)
  {
     User user = new User();
     user.setName(name);
     user.setUsername(username);
     user.setPassword(passwordEncoder.encode(password));
     user.setActive(true);
     user.setRoles(Collections.singleton(Role.USER));

     userRepo.save(user);

     return "redirect:/login";
  }
Qeydlər siyahısı səhifəsinə cavabdeh olan nəzarətçi hazırda Bahar Təhlükəsizliyi tətbiq edildikdən sonra daha mürəkkəbləşəcək sadələşdirilmiş funksionallığı ehtiva edir.
@Controller
public class NoteController
{
  @Autowired
  private NoteRepo noteRepo;

  @GetMapping("/notes")
  public String notes(Model model)
  {
     List<Note> notes = noteRepo.findAll();
     model.addAttribute("notes", notes);

     return "notes";
  }

  @PostMapping("/addnote")
  public String addNote(String title, String note)
  {
     Note newNote = new Note();
     newNote.setTitle(title);
     newNote.setNote(note);

     noteRepo.save(newNote);

     return "redirect:/notes";
  }
}
Giriş səhifəsi üçün nəzarətçi yazmayacağıq, çünki o, Spring Security tərəfindən istifadə olunur. Bunun əvəzinə xüsusi konfiqurasiyaya ehtiyacımız olacaq. Həmişə olduğu kimi, gəlin başqa bir paket yaradaq, ona zəng edək configvə sinfi orada yerləşdirək MvcConfig. Spring Security konfiqurasiyasını yazdığımız zaman "/login" istifadə edərkən hansı səhifəyə istinad etdiyimizi biləcək.
@Configuration
public class MvcConfig implements WebMvcConfigurer
{
  public void addViewControllers(ViewControllerRegistry registry)
  {
     registry.addViewController("/login").setViewName("login");
     registry.setOrder(Ordered.HIGHEST_PRECEDENCE);
  }
}

Səhifələr

Səhifələr yaratmaq üçün Bığ şablon mühərrikindən istifadə edirəm . Başqasını həyata keçirə bilərsiniz, fərq etməz. Bütün səhifələrdə istifadə olunan meta məlumat üçün meta.mustache faylı yaradılmışdır. Layihəmizin səhifələrinin daha gözəl görünməsi üçün Bootstrap da daxildir. Səhifələr "src/main/resources/templates" kataloqunda yaradılır. Fayllarda uzadılmış bığ var. Html kodunu birbaşa məqaləyə yerləşdirmək onu çox böyük edəcək, ona görə də layihənin GitHub repozitoriyasında şablonlar qovluğuna keçid buradadır .

Klassik Giriş üçün Bahar Təhlükəsizlik Konfiqurasiyası

Spring Security proqramı və onun resurslarını icazəsiz girişdən qorumağa kömək edir. Paketdə yerləşdirəcəyimiz SecurityConfigmiras qalan sinifdə yığcam iş konfiqurasiyası yaradacağıq . Gəlin onu Spring Security dəstəyini aktivləşdirəcək @EnableWebSecurity annotasiyası və bu sinifdə bəzi konfiqurasiyanın olduğunu göstərən @Configuration annotasiyası ilə qeyd edək. Qeyd: avtomatik konfiqurasiya edilmiş pom.xml, Təhlükəsizliyin müəyyən edilmiş şəkildə həyata keçirilməsinə mane olan Spring Boot əsas komponenti 2.1.4.RELEASE versiyasını ehtiva edir. Layihədə münaqişələrin qarşısını almaq üçün versiyanı 2.0.1.RELEASE-ə dəyişmək tövsiyə olunur. WebSecurityConfigurerAdapterconfig

Əsas konfiqurasiya SecurityConfig

Konfiqurasiyamız aşağıdakıları edə biləcək:
  1. Parolları şifrələyin BCryptPasswordEncoder:

    @Autowired
    private PasswordEncoder passwordEncoder;
    
    @Bean
    PasswordEncoder passwordEncoder()
    {
      PasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
      return passwordEncoder;
    }
  2. Xüsusi yazılmış autentifikasiya provayderindən istifadə edərək daxil olun:

    @Autowired
    private AuthProvider authProvider;
    
    @Override
    protected void configure(AuthenticationManagerBuilder auth)
    {
      auth.authenticationProvider(authProvider);
    }
  3. Anonim istifadəçilərə ana səhifə, qeydiyyat və giriş səhifələrinə daxil olmaq imkanı verin. Bütün digər sorğular daxil olmuş istifadəçilər tərəfindən yerinə yetirilməlidir. Daha əvvəl təsvir edilmiş “/login”i giriş səhifəsi kimi təyin edək. Giriş uğurlu olarsa, istifadəçi qeydlərin siyahısı olan səhifəyə aparılacaq, xəta olarsa, istifadəçi giriş səhifəsində qalacaq. Uğurlu çıxışdan sonra istifadəçi əsas səhifəyə aparılacaq.

    @Override
    protected void configure(HttpSecurity http) throws Exception
    {
      http
            .authorizeRequests()
            .antMatchers("/resources/**", "/", "/login**", "/registration").permitAll()
            .anyRequest().authenticated()
            .and().formLogin().loginPage("/login")
            .defaultSuccessUrl("/notes").failureUrl("/login?error").permitAll()
            .and().logout().logoutSuccessUrl("/").permitAll();
    }

Fərdi istifadəçi girişi

Öz-özünə yazılmış bir AuthProvideristifadəçiyə yalnız e-poçtla deyil, həm də istifadəçi adı ilə daxil olmağa imkan verəcəkdir.
@Component
public class AuthProvider implements AuthenticationProvider
{
  @Autowired
  private UserService userService;

  @Autowired
  private PasswordEncoder passwordEncoder;

  public Authentication authenticate(Authentication authentication) throws AuthenticationException
  {
     String username = authentication.getName();
     String password = (String) authentication.getCredentials();

     User user = (User) userService.loadUserByUsername(username);

     if(user != null && (user.getUsername().equals(username) || user.getName().equals(username)))
     {
        if(!passwordEncoder.matches(password, user.getPassword()))
        {
           throw new BadCredentialsException("Wrong password");
        }

        Collection<? extends GrantedAuthority> authorities = user.getAuthorities();

        return new UsernamePasswordAuthenticationToken(user, password, authorities);
     }
     else
        throw new BadCredentialsException("Username not found");
  }

  public boolean supports(Class<?> arg)
  {
     return true;
  }
}
Bildiyiniz kimi, UserServicepaketdə yerləşən sinif istifadəçinin yüklənməsinə cavabdehdir services. Bizim vəziyyətimizdə o, istifadəçini yalnız sahə üzrə deyil username, daxili tətbiqetmə kimi, həm də istifadəçi adı, Google hesabının adı və Google hesabı e-poçtu ilə axtarır. Son iki üsul OAuth2 vasitəsilə giriş həyata keçirərkən bizim üçün faydalı olacaq. Burada sinif qısaldılmış versiyada verilir.
@Service
public class UserService implements UserDetailsService
{
  @Autowired
  private UserRepo userRepo;

  @Override
  public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException
  {
     User userFindByUsername = userRepo.findByUsername(username);
     //Остальные поиски

     if(userFindByUsername != null)
     {
        return userFindByUsername;
     }
     //Остальные проверки
     return null;
  }
}
Qeyd: lazımi üsulları -da yazmağı unutmayın UserRepo!

Nəzarətçini təkmilləşdirək

Spring Security-ni konfiqurasiya etdik. İndi qeyd nəzarətçinizdə bundan yararlanmağın vaxtıdır. İndi hər bir xəritəçəkmə istifadəçini tapmağa çalışacaq əlavə Principal parametrini qəbul edəcək. Niyə mən birbaşa sinfə inyeksiya edə bilmirəm User? Sonra sosial şəbəkələr vasitəsilə login yazanda istifadəçi tiplərinin uyğunsuzluğundan münaqişə yaranacaq. Biz əvvəlcədən lazımi çevikliyi təmin edirik. Qeyd nəzarətçi kodumuz indi belə görünür:
@GetMapping("/notes")
public String notes(Principal principal, Model model)
{
  User user = (User) userService.loadUserByUsername(principal.getName());
  List<Note> notes = noteRepo.findByUserId(user.getId());
  model.addAttribute("notes", notes);
  model.addAttribute("user", user);

  return "notes";
}

@PostMapping("/addnote")
public String addNote(Principal principal, String title, String note)
{
  User user = (User) userService.loadUserByUsername(principal.getName());

  Note newNote = new Note();
  newNote.setTitle(title);
  newNote.setNote(note);
  newNote.setUserId(user.getId());

  noteRepo.save(newNote);

  return "redirect:/notes";
}
Qeyd: layihədə standart olaraq CSRF mühafizəsi aktivləşdirilmişdir , ona görə də ya onu özünüz üçün deaktiv edin (http.csrf().disable()), ya da məqalənin müəllifi kimi csrf işarəsi ilə gizli sahə əlavə etməyi unutmayın. bütün post sorğularına.

Başlayın

Layihəni işə salmağa çalışırıq.
Qeydlər xidmətinin nümunəsindən istifadə edərək, e-poçt və OAuth2 vasitəsilə Spring Security-ə müntəzəm giriş təqdim edək - 1
Qeydlər xidmətinin nümunəsindən istifadə edərək Spring Security-ə e-poçt və OAuth2 vasitəsilə müntəzəm giriş təqdim edək - 2
Məlumat bazasında yeni istifadəçinin peyda olduğunu görürük. Parol şifrələnib.
Qeydlər xidmətinin nümunəsindən istifadə edərək Spring Security-ə e-poçt və OAuth2 vasitəsilə müntəzəm giriş təqdim edək - 3
Qeydlər xidmətinin nümunəsindən istifadə edərək Spring Security-ə e-poçt və OAuth2 vasitəsilə müntəzəm giriş təqdim edək - 4
Qeydlər xidmətinin nümunəsindən istifadə edərək, e-poçt və OAuth2 vasitəsilə Spring Security-ə müntəzəm giriş təqdim edək - 5
Qeydlər xidmətinin nümunəsindən istifadə edərək, e-poçt və OAuth2 vasitəsilə Spring Security-ə müntəzəm giriş təqdim edək - 6
Qeydlər verilənlər bazasında saxlanılır.
Qeydlər xidmətinin nümunəsindən istifadə edərək Spring Security-ə e-poçt və OAuth2 vasitəsilə müntəzəm giriş təqdim edək - 7
Biz görürük ki, layihə uğurla həyata keçirilir və fəaliyyət göstərir. Tam xoşbəxtlik üçün bizə yalnız sosial şəbəkələr vasitəsilə daxil olmaq imkanı lazımdır. Yaxşı, başlayaq!

Spring Security-də Google-dan istifadə edərək OAuth2-nin qurulması

OAuth2-ni tətbiq edərkən mən Spring-dən bu rəsmi təlimata etibar etdim . OAuth2-ni dəstəkləmək üçün pom.xml-ə aşağıdakı kitabxananı əlavə edin:
<dependency>
  <groupId>org.springframework.security.oauth.boot</groupId>
  <artifactId>spring-security-oauth2-autoconfigure</artifactId>
  <version>2.0.0.RELEASE</version>
</dependency>
Gəlin Bahar Təhlükəsizlik konfiqurasiyamızı dəyişdirək SecurityConfig. Əvvəlcə @EnableOAuth2Client annotasiyasını əlavə edək. Sosial şəbəkələr vasitəsilə daxil olmaq üçün lazım olanları avtomatik olaraq çəkəcək.

Filtr konfiqurasiyası və application.properties

Təhlükəsizlik konfiqurasiyamızda istifadə etmək üçün OAuth2ClientContext inyeksiya edək.
@Autowired
private OAuth2ClientContext oAuth2ClientContext;
OAuth2ClientContext istifadəçinin sosial giriş sorğusunu təsdiq edən filtr yaratarkən istifadə olunur. Filtr @EnableOAuth2Client annotasiyası sayəsində əlçatandır. Etməli olduğumuz yeganə şey onu əsas Spring Security filtrindən əvvəl düzgün ardıcıllıqla çağırmaqdır. Yalnız bundan sonra biz OAuth2 ilə giriş prosesi zamanı yönləndirmələri tuta biləcəyik. FilterRegistrationBeanBunu etmək üçün filtrimizin prioritetini -100 olaraq təyin etdiyimizdən istifadə edirik .
@Bean
public FilterRegistrationBean oAuth2ClientFilterRegistration(OAuth2ClientContextFilter oAuth2ClientContextFilter)
{
  FilterRegistrationBean registration = new FilterRegistrationBean();
  registration.setFilter(oAuth2ClientContextFilter);
  registration.setOrder(-100);
  return registration;
}

private Filter ssoFilter()
{
  OAuth2ClientAuthenticationProcessingFilter googleFilter = new OAuth2ClientAuthenticationProcessingFilter("/login/google");
  OAuth2RestTemplate googleTemplate = new OAuth2RestTemplate(google(), oAuth2ClientContext);
  googleFilter.setRestTemplate(googleTemplate);
  CustomUserInfoTokenServices tokenServices = new CustomUserInfoTokenServices(googleResource().getUserInfoUri(), google().getClientId());
  tokenServices.setRestTemplate(googleTemplate);
  googleFilter.setTokenServices(tokenServices);
  tokenServices.setUserRepo(userRepo);
  tokenServices.setPasswordEncoder(passwordEncoder);
  return googleFilter;
}
Siz həmçinin konfiqurasiya (HttpSecurity http) funksiyasına yeni filtr əlavə etməlisiniz:
http.addFilterBefore(ssoFilter(), UsernamePasswordAuthenticationFilter.class);
Filtr həmçinin müştərinin Google vasitəsilə qeydiyyatdan keçdiyini bilməlidir. @ConfigurationProperties annotasiyası application.properties-də hansı konfiqurasiya xassələrinin axtarılacağını müəyyən edir.
@Bean
@ConfigurationProperties("google.client")
public AuthorizationCodeResourceDetails google()
{
  return new AuthorizationCodeResourceDetails();
}
Doğrulamanı başa çatdırmaq üçün Google istifadəçi məlumatının son nöqtəsini göstərməlisiniz:
@Bean
@ConfigurationProperties("google.resource")
public ResourceServerProperties googleResource()
{
  return new ResourceServerProperties();
}
Tətbiqimizi Google Cloud Platform- da qeydiyyatdan keçirdikdən sonra biz application.properties-ə müvafiq prefikslərlə xassələr əlavə edəcəyik:
google.client.clientId=yourClientId
google.client.clientSecret=yourClientSecret
google.client.accessTokenUri=https://www.googleapis.com/oauth2/v4/token
google.client.userAuthorizationUri=https://accounts.google.com/o/oauth2/v2/auth
google.client.clientAuthenticationScheme=form
google.client.scope=openid,email,profile
google.resource.userInfoUri=https://www.googleapis.com/oauth2/v3/userinfo
google.resource.preferTokenInfo=true

Tətbiqin Google Bulud Platforması ilə qeydiyyata alınmasının əsas məqamları

Yol: API və Xidmətlər -> Etibarnamə OAuth Giriş Sorğusu Pəncərəsi:
  • Tətbiqin adı: Bahar giriş forması və OAuth2 təlimatı
  • Dəstək e-poçt ünvanı: e-poçtunuz
  • Google API üçün əhatə dairəsi: e-poçt, profil, openid
  • Səlahiyyətli domenlər: me.org
  • Tətbiqin əsas səhifəsinə keçid: http://me.org:8080
  • Tətbiq məxfilik siyasətinə keçid: http://me.org:8080
  • Tətbiqdən istifadə şərtlərinə keçid: http://me.org:8080
Etibarnamələr:
  • Növ: Veb Tətbiq
  • Başlıq: Bahar giriş forması və OAuth2 təlimatı
  • İcazə verilən JavaScript mənbələri: http://me.org, http://me.org:8080
  • İcazə verilən yönləndirmə URI-ləri: http://me.org:8080/login, http://me.org:8080/login/google
Qeyd: Google localhost:8080 ünvanı ilə işləmək istəmədiyi üçün sonuna “127.0.0.1 me.org” sətrini və ya C:\Windows\System32\drivers\etc\hosts faylına bənzər bir şey əlavə edin. Əsas odur ki, domen klassik formadadır.

CustomUserInfoTokenServices

Filtr funksiyasının təsvirində Xüsusi sözünə diqqət yetirdinizmi? Sinif CustomUserInfoTokenServices. Bəli, biz blackjack və istifadəçini verilənlər bazasında saxlamaq imkanı ilə öz sinfimizi yaradacağıq! UserInfoTokenServicesIntelliJ IDEA-da Ctrl-N klaviatura qısa yolundan istifadə edərək, standartın necə həyata keçirildiyini tapa və görə bilərsiniz . Gəlin onun kodunu yeni yaradılmış sinfə kopyalayaq CustomUserInfoTokenServices. Əksəriyyəti dəyişməz qala bilər. Funksiyaların məntiqini dəyişməzdən əvvəl sinifin özəl sahələri kimi əlavə UserRepoedək PasswordEncoder. Gəlin onlar üçün tənzimləyicilər yaradaq. SecurityConfig sinfinə @Autowired UserRepo userRepo əlavə edək. Süzgəc yaratma metodunda səhvin göstəricisinin necə yox olmasına baxırıq və sevinirik. Niyə @Autowired birbaşa CustomUserInfoTokenServices-ə tətbiq oluna bilmədi? Çünki bu sinif asılılığı qəbul etməyəcək, çünki onun özü heç bir Spring annotasiyası ilə qeyd olunmur və onun konstruktoru filtr elan edildikdə açıq şəkildə yaradılır. Müvafiq olaraq, Baharın DI mexanizmi bu barədə bilmir. Bu sinifdə hər hansı bir şeyə @Autowired annotasiyası qoysaq, istifadə edildikdə NullPointerException alacağıq. Ancaq açıq təyinedicilər vasitəsilə hər şey çox yaxşı işləyir. Lazımi komponentləri həyata keçirdikdən sonra maraq doğuran əsas obyekt istifadəçi haqqında məlumatı olan Map<String, Object>-in götürüldüyü loadAuthentication funksiyasına çevrilir. Məhz bu layihədə mən sosial şəbəkə vasitəsilə daxil olmuş istifadəçinin məlumat bazasında saxlanmasını həyata keçirdim. OAuth2 provayderi kimi Google hesabından istifadə etdiyimiz üçün xəritədə Google üçün xarakterik olan “alt” sahənin olub-olmadığını yoxlayırıq. Əgər varsa, bu o deməkdir ki, istifadəçi haqqında məlumat düzgün qəbul edilib. Yeni istifadəçi yaradırıq və onu verilənlər bazasında saxlayırıq.
@Override
public OAuth2Authentication loadAuthentication(String accessToken)
     throws AuthenticationException, InvalidTokenException
{
  Map<String, Object> map = getMap(this.userInfoEndpointUrl, accessToken);

  if(map.containsKey("sub"))
  {
     String googleName = (String) map.get("name");
     String googleUsername = (String) map.get("email");

     User user = userRepo.findByGoogleUsername(googleUsername);

     if(user == null)
     {
        user = new User();
        user.setActive(true);
        user.setRoles(Collections.singleton(Role.USER));
     }

     user.setName(googleName);
     user.setUsername(googleUsername);
     user.setGoogleName(googleName);
     user.setGoogleUsername(googleUsername);
     user.setPassword(passwordEncoder.encode("oauth2user"));

     userRepo.save(user);
  }

  if (map.containsKey("error"))
  {
     this.logger.debug("userinfo returned error: " + map.get("error"));
     throw new InvalidTokenException(accessToken);
  }
  return extractAuthentication(map);
}
Bir neçə provayderdən istifadə edərkən, siz bir CustomUserInfoTokenServices-də müxtəlif seçimləri təyin edə və filtr bəyannamə metodunda oxşar xidmətlərin müxtəlif siniflərini qeyd edə bilərsiniz. İndi həm İstifadəçi, həm də OAuth2Authentication Principal kimi çıxış edə bilər. UserService-də istifadəçinin Google məlumatları vasitəsilə yüklənməsini əvvəlcədən nəzərə aldığımız üçün proqram hər iki istifadəçi növü üçün işləyəcək. Biz layihənin əsas səhifə nəzarətçisini elə dəyişdiririk ki, o, OAuth2-dən istifadə edərək daxil olmuş istifadəçiləri qeydlər səhifəsinə yönləndirsin.
@GetMapping("/")
public String index(Principal principal)
{
  if(principal != null)
  {
     return "redirect:/notes";
  }
  return "index";
}

Layihənin yekun açılışı

Kiçik kosmetik dəyişikliklərdən və çıxış düyməsini əlavə etdikdən sonra layihənin son buraxılışını həyata keçiririk.
Qeydlər xidmətinin nümunəsindən istifadə edərək Spring Security-ə e-poçt və OAuth2 vasitəsilə müntəzəm giriş təqdim edək - 8
Qeydlər xidmətinin nümunəsindən istifadə edərək Spring Security-ə e-poçt və OAuth2 vasitəsilə müntəzəm giriş təqdim edək - 9
Qeydlər xidmətinin nümunəsindən istifadə edərək Spring Security-ə e-poçt və OAuth2 vasitəsilə müntəzəm giriş təqdim edək - 10
Qeydlər xidmətinin nümunəsindən istifadə edərək Spring Security-ə e-poçt və OAuth2 vasitəsilə müntəzəm giriş təqdim edək - 11
Qeydlər xidmətinin nümunəsindən istifadə edərək Spring Security-ə e-poçt və OAuth2 vasitəsilə müntəzəm giriş təqdim edək - 12
Qeydlər xidmətinin nümunəsindən istifadə edərək Spring Security-ə e-poçt və OAuth2 vasitəsilə müntəzəm giriş təqdim edək - 13
Qeydlər xidmətinin nümunəsindən istifadə edərək Spring Security-ə e-poçt və OAuth2 vasitəsilə müntəzəm giriş təqdim edək - 14
Qeydlər xidmətinin nümunəsindən istifadə edərək Spring Security-ə e-poçt və OAuth2 vasitəsilə müntəzəm giriş təqdim edək - 15
İstifadəçi həm adi formada, həm də Google hesabı vasitəsilə uğurla daxil olur. İstədiyimiz budur! Ümid edirəm ki, bu məqalə veb proqram yaratmaq, onu Spring Security ilə təmin etmək və müxtəlif giriş üsullarını birləşdirməklə bağlı bəzi məqamları aydınlaşdırıb. Tam layihə kodu ilə edə bilərsiniz
Şərhlər
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION