JavaRush /בלוג Java /Random-HE /בואו להציג כניסה רגילה באמצעות דואר אלקטרוני ו-OAuth2 ל-S...

בואו להציג כניסה רגילה באמצעות דואר אלקטרוני ו-OAuth2 ל-Spring Security באמצעות הדוגמה של שירות ההערות

פורסם בקבוצה
במהלך כתיבת הבקשה שלי, נתקלתי בחוסר מאמרים ברורים כיצד לגרום למשתמש להירשם הן באמצעות האימייל והן ברשתות החברתיות. היו הדרכות טובות על הגדרת טופס הכניסה הקלאסי. היו הדרכות טובות על OAuth2 . היה מעט מידע מבחינה פלילית כיצד לשלב את שתי השיטות. במהלך תהליך החיפוש, הצלחנו למצוא פתרון ישים. היא לא מתיימרת להיות האמת האולטימטיבית, אבל היא ממלאת את תפקידה. במאמר זה אראה כיצד ליישם שירות אחסון פתקים עם תצורת Spring Security דומה מאפס. בואו להציג כניסה רגילה באמצעות דואר אלקטרוני ו-OAuth2 ל-Spring Security באמצעות הדוגמה של שירות ההערות - 1הערה: טוב אם הקורא עבר לפחות כמה מדריכים על Spring, כי תשומת הלב תתמקד רק ב-Spring Security, ללא הסברים מפורטים על מאגרים, בקרים וכו'. אחרת, מאמר די גדול כבר יתברר ל להיות ענק. תוֹכֶן
  1. יצירת פרויקט
  2. יצירת ישויות והיגיון יישומים
    1. ישויות
    2. מאגרים
    3. בקרים
    4. דפים
  3. הגדרת Spring Security עבור התחברות קלאסית
    1. תצורה בסיסית SecurityConfig
    2. התחברות משתמש מותאמת אישית
    3. בואו נשפר את הבקר
    4. לְהַשִׁיק
  4. הגדרת OAuth2 באמצעות Google כדוגמה ב-Spring Security
    1. תצורת סינון ויישום.מאפיינים
    2. דגשים ברישום אפליקציה ב-Google Cloud Platform
    3. CustomUserInfoTokenServices
  5. השקה סופית של הפרויקט

יצירת פרויקט

אנחנו הולכים אל start.spring.io ומהווים את הבסיס לפרויקט:
  • אינטרנט - הפעלת אפליקציה על Tomcat המובנה, מיפוי כתובות אתרים וכדומה;
  • JPA - חיבור למסד נתונים;
  • שפם הוא מנוע תבנית המשמש ליצירת דפי אינטרנט;
  • אבטחה - הגנה על אפליקציות. בשביל זה נוצר המאמר הזה.
הורד את הארכיון שנוצר ופרק אותו בתיקייה שאתה צריך. אנו משיקים אותו ב-IDE. אתה יכול לבחור את מסד הנתונים לפי שיקול דעתך. אני משתמש ב-MySQL בתור מסד הנתונים של הפרויקט, אז אני מוסיף את התלות הבאה לקובץ pom.xml בגוש <dependencies>:
<dependency>
     <groupId>mysql</groupId>
     <artifactId>mysql-connector-java</artifactId>
     <version>5.1.34</version>
</dependency>
תצורת application.properties היא כעת כדלקמן:
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

יצירת ישויות והיגיון יישומים

ישויות

בואו ניצור חבילה entitiesבה נמקם את ישויות מסד הנתונים. המשתמש יתואר על ידי מחלקה Userהמיישמת את הממשק UserDetails, אשר יידרש עבור תצורת Spring Security. למשתמש יהיה מזהה, שם משתמש (זהו דוא"ל), סיסמה, שם, תפקיד, דגל פעילות, שם חשבון Google ואימייל ( googleNameו googleUsername).
@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
}
תפקידי משתמש משמשים להסדרת גישה ב-Spring Security. האפליקציה שלנו תשתמש רק בתפקיד אחד:
public enum Role implements GrantedAuthority
{
  USER;

  @Override
  public String getAuthority()
  {
     return name();
  }
}
בואו ניצור מחלקה הערה עם מזהה, כותרת הערה, גוף הערה ומזהה המשתמש שאליו היא שייכת:
@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()
}

מאגרים

כדי לשמור ישויות למסד הנתונים, אנחנו צריכים מאגרים שיעשו עבורנו את כל העבודה המלוכלכת. בואו ניצור חבילה repos, בה ניצור ממשקים UserRepoשהועברו בירושה NoteRepoמהממשק JpaRepository<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);
}

בקרים

לשירות ההערות שלנו יהיו הדפים הבאים:
  • בית;
  • הַרשָׁמָה;
  • כְּנִיסָה;
  • רשימת הערות משתמש.
רק למשתמש מורשה צריכה להיות גישה לרשימת ההערות. שאר הדפים הם ציבוריים. בואו ניצור חבילה controllersהמכילה מחלקה IndexControllerהמכילה את המיפוי הרגיל של העמוד הראשי. הכיתה RegistrationControllerאחראית על רישום המשתמש. פוסט מיפוי לוקח נתונים מהטופס, שומר את המשתמש למסד הנתונים ומפנה לדף הכניסה. PasswordEncoderיתואר בהמשך. הוא משמש להצפנת סיסמאות.
@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";
  }
הבקר האחראי על דף רשימת ההערות מכיל כרגע פונקציונליות פשוטה, שתהפוך מורכבת יותר לאחר יישום Spring Security.
@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";
  }
}
לא נכתוב בקר עבור דף הכניסה מכיוון שהוא משמש את Spring Security. במקום זאת, נצטרך תצורה מיוחדת. כרגיל, בואו ניצור חבילה נוספת, נקרא לה configונמקם את הכיתה שם MvcConfig. כאשר נכתוב את תצורת Spring Security, הוא יידע לאיזה עמוד אנו מתייחסים כאשר אנו משתמשים ב-"/login".
@Configuration
public class MvcConfig implements WebMvcConfigurer
{
  public void addViewControllers(ViewControllerRegistry registry)
  {
     registry.addViewController("/login").setViewName("login");
     registry.setOrder(Ordered.HIGHEST_PRECEDENCE);
  }
}

דפים

אני משתמש במנוע תבנית Mustache כדי ליצור דפים . אתה יכול ליישם עוד אחד, זה לא משנה. נוצר קובץ meta.mustache עבור המטא מידע שנמצא בשימוש בכל הדפים. זה כולל גם Bootstrap כדי לגרום לדפי הפרויקט שלנו להיראות יפים יותר. דפים נוצרים בספריית "src/main/resources/templates". לקבצים יש את הסיומת שפם. הצבת קוד ה-html ישירות במאמר תהפוך אותו לגדול מדי, אז הנה קישור לתיקיית התבניות במאגר GitHub של הפרויקט .

הגדרת Spring Security עבור התחברות קלאסית

Spring Security עוזרת לנו להגן על האפליקציה והמשאבים שלה מפני גישה לא מורשית. ניצור תצורת עבודה תמציתית בכיתה SecurityConfigשעברה בירושה WebSecurityConfigurerAdapter, אותה נמקם בחבילה config. בואו נסמן אותו עם הערת @EnableWebSecurity, שתאפשר תמיכה ב-Spring Security, והערת @Configuration, שמציינת שהמחלקה הזו מכילה תצורה כלשהי. הערה: הגרסה של pom.xml שהוגדרה אוטומטית מכילה את רכיב האב של Spring Boot 2.1.4.RELEASE, שמנעה את הטמעת האבטחה בצורה שנקבעה. כדי למנוע התנגשויות בפרויקט, מומלץ לשנות את הגרסה ל-2.0.1.RELEASE.

תצורה בסיסית SecurityConfig

התצורה שלנו תוכל:
  1. הצפנת סיסמאות באמצעות BCryptPasswordEncoder:

    @Autowired
    private PasswordEncoder passwordEncoder;
    
    @Bean
    PasswordEncoder passwordEncoder()
    {
      PasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
      return passwordEncoder;
    }
  2. היכנס באמצעות ספק אימות שנכתב במיוחד:

    @Autowired
    private AuthProvider authProvider;
    
    @Override
    protected void configure(AuthenticationManagerBuilder auth)
    {
      auth.authenticationProvider(authProvider);
    }
  3. אפשר למשתמשים אנונימיים גישה לדף הבית, לדפי הרישום וההתחברות. כל שאר הבקשות חייבות להתבצע על ידי משתמשים מחוברים. הבה נקצה את ה-"/login" שתואר קודם כדף הכניסה. אם הכניסה מוצלחת, המשתמש יובא לדף עם רשימת הערות; אם יש שגיאה, המשתמש יישאר בדף הכניסה. לאחר יציאה מוצלחת, המשתמש יועבר לעמוד הראשי.

    @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();
    }

התחברות משתמש מותאמת אישית

אחד שנכתב בעצמו AuthProviderיאפשר למשתמש להיכנס לא רק בדוא"ל, אלא גם לפי שם משתמש.
@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;
  }
}
כפי שאולי שמתם לב, הכיתה UserServiceשנמצאת בחבילה אחראית לטעינת המשתמש services. במקרה שלנו, הוא מחפש משתמש לא רק לפי השדה username, כמו היישום המובנה, אלא גם לפי שם משתמש, שם חשבון Google ודוא"ל חשבון Google. שתי השיטות האחרונות יהיו שימושיות עבורנו בעת יישום התחברות באמצעות OAuth2. כאן השיעור ניתן בגרסה מקוצרת.
@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;
  }
}
הערה: אל תשכח לכתוב את השיטות הדרושות ב- UserRepo!

בואו נשפר את הבקר

הגדרנו את Spring Security. עכשיו זה הזמן לנצל את זה בבקר ההערות שלך. כעת כל מיפוי יקבל פרמטר Principal נוסף, שבאמצעותו הוא ינסה למצוא את המשתמש. למה אני לא יכול להזריק ישירות לכיתה User? אז תהיה התנגשות עקב אי התאמה בין סוגי המשתמשים כאשר אנו כותבים כניסה דרך רשתות חברתיות. אנו מספקים את הגמישות הנדרשת מראש. קוד בקר ההערות שלנו נראה כעת כך:
@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";
}
הערה: לפרויקט הגנת CSRF מופעלת כברירת מחדל , אז או שתבטל אותו בעצמך (http.csrf().disable()), או אל תשכח, כמחבר המאמר, להוסיף שדה נסתר עם אסימון csrf לכל הבקשות לפרסום.

לְהַשִׁיק

אנחנו מנסים להשיק את הפרויקט.
בואו להציג כניסה רגילה באמצעות דואר אלקטרוני ו-OAuth2 ל-Spring Security באמצעות הדוגמה של שירות ההערות - 1
בואו להציג כניסה רגילה באמצעות דואר אלקטרוני ו-OAuth2 ל-Spring Security באמצעות הדוגמה של שירות ההערות - 2
אנו רואים שמשתמש חדש הופיע במסד הנתונים. הסיסמה מוצפנת.
בואו להציג כניסה רגילה באמצעות דואר אלקטרוני ו-OAuth2 ל-Spring Security באמצעות הדוגמה של שירות ההערות - 3
Дружим обычный вход через email и OAuth2 в Spring Security на примере сервиса заметок - 4
Дружим обычный вход через email и OAuth2 в Spring Security на примере сервиса заметок - 5
Дружим обычный вход через email и OAuth2 в Spring Security на примере сервиса заметок - 6
ההערות נשמרות במסד הנתונים.
Дружим обычный вход через email и OAuth2 в Spring Security на примере сервиса заметок - 7
אנו רואים שהפרויקט יצא לדרך בהצלחה. בשביל אושר מוחלט, אנחנו צריכים רק את היכולת להיכנס דרך רשתות חברתיות. ובכן, בואו נתחיל!

הגדרת OAuth2 באמצעות Google כדוגמה ב-Spring Security

בעת הטמעת OAuth2, הסתמכתי על הדרכה רשמית זו מ-Spring . כדי לתמוך ב-OAuth2, הוסף את הספרייה הבאה אל pom.xml:
<dependency>
  <groupId>org.springframework.security.oauth.boot</groupId>
  <artifactId>spring-security-oauth2-autoconfigure</artifactId>
  <version>2.0.0.RELEASE</version>
</dependency>
בואו נשנה את תצורת ה-Spring Security שלנו ב- SecurityConfig. ראשית, בואו נוסיף את ההערה @EnableOAuth2Client. זה יביא אוטומטית את מה שאתה צריך כדי להיכנס דרך רשתות חברתיות.

תצורת סינון ויישום.מאפיינים

בואו נזריק את OAuth2ClientContext לשימוש בתצורת האבטחה שלנו.
@Autowired
private OAuth2ClientContext oAuth2ClientContext;
OAuth2ClientContext משמש בעת יצירת מסנן המאמת את בקשת ההתחברות החברתית של המשתמש. המסנן זמין הודות לביאור @EnableOAuth2Client. כל מה שאנחנו צריכים לעשות הוא לקרוא לזה בסדר הנכון, לפני מסנן ה-Spring Security הראשי. רק אז נוכל לתפוס הפניות מחדש במהלך תהליך הכניסה עם OAuth2. לשם כך, אנו משתמשים ב- FilterRegistrationBean, שבו אנו מגדירים את העדיפות של המסנן שלנו ל-100.
@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;
}
אתה גם צריך להוסיף מסנן חדש לפונקציה configure(HttpSecurity http):
http.addFilterBefore(ssoFilter(), UsernamePasswordAuthenticationFilter.class);
המסנן גם צריך לדעת שהלקוח נרשם דרך גוגל. ההערה @ConfigurationProperties מציינת אילו מאפייני תצורה לחפש ב- application.properties.
@Bean
@ConfigurationProperties("google.client")
public AuthorizationCodeResourceDetails google()
{
  return new AuthorizationCodeResourceDetails();
}
כדי להשלים את האימות, עליך לציין את נקודת הקצה של פרטי המשתמש של Google:
@Bean
@ConfigurationProperties("google.resource")
public ResourceServerProperties googleResource()
{
  return new ResourceServerProperties();
}
לאחר שרשמנו את האפליקציה שלנו ב- Google Cloud Platform , נוסיף נכסים עם הקידומות המתאימות ל application.properties:
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

דגשים ברישום אפליקציה ב- Google Cloud Platform

נתיב: ממשקי API ושירותים -> אישורים חלון בקשת גישה ל-OAuth:
  • שם האפליקציה: טופס התחברות אביבית ומדריך OAuth2
  • כתובת דוא"ל לתמיכה: האימייל שלך
  • היקף עבור Google API: אימייל, פרופיל, openid
  • דומיינים מורשים: me.org
  • קישור לעמוד הראשי של האפליקציה: http://me.org:8080
  • קישור למדיניות הפרטיות של האפליקציה: http://me.org:8080
  • קישור לתנאי השימוש של היישום: http://me.org:8080
אישורים:
  • סוג: יישום אינטרנט
  • כותרת: טופס התחברות אביבית ומדריך OAuth2
  • מקורות JavaScript מותרים: http://me.org, http://me.org:8080
  • כתובת URI מותרת להפניה מחדש: http://me.org:8080/login, http://me.org:8080/login/google
הערה: מכיוון שגוגל לא רוצה לעבוד עם הכתובת localhost:8080, הוסף את השורה "127.0.0.1 me.org" או משהו דומה לקובץ C:\Windows\System32\drivers\etc\hosts בסוף. העיקר שהדומיין הוא בצורה קלאסית.

CustomUserInfoTokenServices

שמתם לב למילה Custom בתיאור פונקציית הסינון? מעמד CustomUserInfoTokenServices. כן, ניצור מחלקה משלנו עם בלאק ג'ק ויכולת להציל את המשתמש במסד הנתונים! באמצעות קיצור המקשים Ctrl-N ב- IntelliJ IDEA, תוכל למצוא ולראות כיצד UserInfoTokenServicesמיושמת ברירת המחדל. הבה נעתיק את הקוד שלו למחלקה החדשה שנוצרה CustomUserInfoTokenServices. ניתן להשאיר את רובו ללא שינוי. לפני שנשנה את ההיגיון של הפונקציות, בואו נוסיף UserRepoושדות פרטיים של המחלקה PasswordEncoder. בואו ניצור עבורם מגדירים. בואו נוסיף את @Autowired UserRepo userRepo למחלקה SecurityConfig. אנו מסתכלים כיצד המצביע לשגיאה בשיטת יצירת המסנן נעלם, ואנחנו שמחים. מדוע לא ניתן היה להחיל את @Autowired ישירות על CustomUserInfoTokenServices? מכיוון שהמחלקה הזו לא תקלוט את התלות, מכיוון שהיא עצמה אינה מסומנת בשום הערת Spring, והקונסטרוקטור שלה נוצר במפורש כשהמסנן מוצהר. בהתאם לכך, מנגנון ה-DI של Spring אינו יודע על כך. אם נציין את @Autowired על משהו במחלקה הזו, נקבל NullPointerException בעת השימוש. אבל דרך מגדירים מפורשים הכל עובד טוב מאוד. לאחר הטמעת הרכיבים הדרושים, אובייקט העניין העיקרי הופך לפונקציית loadAuthentication, שבה מאחזר את המפה<String, Object> עם מידע על המשתמש. בפרויקט זה יישמתי את שמירתו של משתמש מחובר דרך רשת חברתית במסד הנתונים. מכיוון שאנו משתמשים בחשבון Google כספק OAuth2, אנו בודקים אם המפה מכילה את השדה "משנה" האופייני לגוגל. אם הוא קיים, זה אומר שהמידע על המשתמש התקבל בצורה נכונה. אנו יוצרים משתמש חדש ושומרים אותו במסד הנתונים.
@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);
}
בעת שימוש במספר ספקים, ניתן לציין אפשרויות שונות ב- CustomUserInfoTokenServices אחד, ולרשום מחלקות שונות של שירותים דומים בשיטת הצהרת המסנן. כעת גם User וגם OAuth2Authentication יכולים לפעול כמנהל. מכיוון שלקחנו בחשבון ב-UserService מראש את טעינת המשתמש דרך נתוני גוגל, האפליקציה תעבוד על שני סוגי המשתמשים. אנו משנים את בקר הדף הראשי של הפרויקט כך שיפנה מחדש משתמשים המחוברים באמצעות OAuth2 לדף ההערות.
@GetMapping("/")
public String index(Principal principal)
{
  if(principal != null)
  {
     return "redirect:/notes";
  }
  return "index";
}

השקה סופית של הפרויקט

לאחר שינויים קוסמטיים קלים והוספת כפתור יציאה, אנו מבצעים את ההשקה הסופית של הפרויקט.
Дружим обычный вход через email и OAuth2 в Spring Security на примере сервиса заметок - 8
Дружим обычный вход через email и OAuth2 в Spring Security на примере сервиса заметок - 9
Дружим обычный вход через email и OAuth2 в Spring Security на примере сервиса заметок - 10
Дружим обычный вход через email и OAuth2 в Spring Security на примере сервиса заметок - 11
Дружим обычный вход через email и OAuth2 в Spring Security на примере сервиса заметок - 12
Дружим обычный вход через email и OAuth2 в Spring Security на примере сервиса заметок - 13
Дружим обычный вход через email и OAuth2 в Spring Security на примере сервиса заметок - 14
Дружим обычный вход через email и OAuth2 в Spring Security на примере сервиса заметок - 15
המשתמש נכנס בהצלחה הן דרך הטופס הרגיל והן דרך חשבון גוגל. זה מה שרצינו! אני מקווה שמאמר זה הבהיר כמה נקודות לגבי יצירת יישום אינטרנט, אבטחתו באמצעות Spring Security ושילוב שיטות כניסה שונות. עם קוד הפרויקט המלא אתה יכול
הערות
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION