JavaRush /Java Blog /Random-TL /Ipakilala natin ang regular na pag-log in sa pamamagitan ...

Ipakilala natin ang regular na pag-log in sa pamamagitan ng email at OAuth2 sa Spring Security gamit ang halimbawa ng serbisyo ng mga tala

Nai-publish sa grupo
Habang isinusulat ang aking aplikasyon, nakatagpo ako ng kakulangan ng malinaw na mga artikulo kung paano maparehistro ang user sa pamamagitan ng email at mga social network. May magagandang tutorial sa pagse-set up ng klasikong form sa pag-login. Nagkaroon ng magagandang tutorial sa OAuth2 . Mayroong maliit na impormasyon sa kriminal kung paano pagsamahin ang dalawang pamamaraan. Sa panahon ng proseso ng paghahanap, nakagawa kami ng isang magagamit na solusyon. Hindi ito nag-aangkin na ang tunay na katotohanan, ngunit tinutupad nito ang tungkulin nito. Sa artikulong ito ipapakita ko kung paano ipatupad ang isang serbisyo sa pag-iimbak ng tala na may katulad na configuration ng Spring Security mula sa simula. Ipakilala natin ang regular na pag-log in sa pamamagitan ng email at OAuth2 sa Spring Security gamit ang halimbawa ng serbisyo ng mga tala - 1Tandaan: mabuti kung ang mambabasa ay dumaan sa hindi bababa sa ilang mga tutorial sa Spring, dahil ang atensyon ay itutuon lamang sa Spring Security, nang walang detalyadong mga paliwanag ng mga repository, controllers, atbp. Kung hindi, ang isang medyo malaking artikulo ay lalabas sa maging dambuhalang. Nilalaman
  1. Paglikha ng isang Proyekto
  2. Paglikha ng mga Entity at Application Logic
    1. Mga entidad
    2. Mga repositoryo
    3. Mga Controller
    4. Mga pahina
  3. Pag-configure ng Spring Security para sa Classic na Pag-login
    1. Pangunahing configuration SecurityConfig
    2. Custom na login ng user
    3. Pagbutihin natin ang controller
    4. Ilunsad
  4. Pagse-set up ng OAuth2 gamit ang Google bilang isang halimbawa sa Spring Security
    1. I-filter ang configuration at application.properties
    2. Mga highlight ng pagpaparehistro ng isang application sa Google Cloud Platform
    3. CustomUserInfoTokenServices
  5. Panghuling paglulunsad ng proyekto

Paglikha ng isang Proyekto

Pumunta kami sa start.spring.io at bumubuo ng batayan ng proyekto:
  • Web - paglulunsad ng isang application sa built-in na Tomcat, mga url mapping at iba pa;
  • JPA - koneksyon sa database;
  • Ang bigote ay isang template engine na ginagamit upang makabuo ng mga web page;
  • Seguridad - proteksyon ng aplikasyon. Ito ay para sa kung ano ang artikulong ito ay nilikha.
I-download ang resultang archive at i-unpack ito sa folder na kailangan mo. Inilunsad namin ito sa IDE. Maaari mong piliin ang database sa iyong paghuhusga. Ginagamit ko ang MySQL bilang database para sa proyekto, kaya idinaragdag ko ang sumusunod na dependency sa pom.xml file sa <dependencies> block:
<dependency>
     <groupId>mysql</groupId>
     <artifactId>mysql-connector-java</artifactId>
     <version>5.1.34</version>
</dependency>
Ang configuration ng application.properties ay kasalukuyang ang mga sumusunod:
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

Paglikha ng mga Entity at Application Logic

Mga entidad

Gumawa tayo ng package entitieskung saan ilalagay natin ang mga entity ng database. Ang user ay ilalarawan ng isang klase Userna nagpapatupad ng interface UserDetails, na kakailanganin para sa configuration ng Spring Security. Ang user ay magkakaroon ng id, username (email ito), password, pangalan, tungkulin, flag ng aktibidad, pangalan ng Google account at email ( googleNameat 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
}
Ginagamit ang mga tungkulin ng user para i-regulate ang pag-access sa Spring Security. Ang aming aplikasyon ay gagamit lamang ng isang tungkulin:
public enum Role implements GrantedAuthority
{
  USER;

  @Override
  public String getAuthority()
  {
     return name();
  }
}
Gumawa tayo ng klase ng tala na may id, pamagat ng tala, katawan ng tala at id ng user kung kanino ito nabibilang:
@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()
}

Mga repositoryo

Upang i-save ang mga entity sa database, kailangan namin ng mga repository na gagawa ng lahat ng maruming gawain para sa amin. Gumawa tayo ng isang pakete repos, sa loob nito gagawa tayo ng mga interface UserRepona minana NoteRepomula sa interface 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);
}

Mga Controller

Ang aming serbisyo sa mga tala ay magkakaroon ng mga sumusunod na pahina:
  • Tahanan;
  • Pagpaparehistro;
  • Pagpasok;
  • Listahan ng mga tala ng gumagamit.
Isang awtorisadong user lang ang dapat magkaroon ng access sa listahan ng mga tala. Ang natitirang mga pahina ay pampubliko. Gumawa tayo ng package controllersna naglalaman ng klase IndexControllerna naglalaman ng karaniwang get-mapping ng pangunahing page. Ang klase RegistrationControlleray may pananagutan sa pagpaparehistro ng gumagamit. Ang post-mapping ay kumukuha ng data mula sa form, ini-save ang user sa database at nagre-redirect sa login page. PasswordEncoderay ilalarawan sa ibang pagkakataon. Ito ay ginagamit upang i-encrypt ang mga password.
@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";
  }
Ang controller na responsable para sa page ng listahan ng mga tala ay kasalukuyang naglalaman ng pinasimpleng functionality, na magiging mas kumplikado pagkatapos ng pagpapatupad ng 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";
  }
}
Hindi kami magsusulat ng controller para sa login page dahil ginagamit ito ng Spring Security. Sa halip, kakailanganin namin ng isang espesyal na pagsasaayos. Gaya ng dati, gumawa tayo ng isa pang package, tawagan ito config, at ilagay ang klase doon MvcConfig. Kapag isinulat namin ang configuration ng Spring Security, malalaman nito kung aling pahina ang aming tinutukoy kapag ginamit namin ang "/login".
@Configuration
public class MvcConfig implements WebMvcConfigurer
{
  public void addViewControllers(ViewControllerRegistry registry)
  {
     registry.addViewController("/login").setViewName("login");
     registry.setOrder(Ordered.HIGHEST_PRECEDENCE);
  }
}

Mga pahina

Ginagamit ko ang template engine ng Mustache upang lumikha ng mga pahina . Maaari kang magpatupad ng isa pa, hindi mahalaga. Isang meta.mustache file ang ginawa para sa meta information na ginagamit sa lahat ng page. Kasama rin dito ang Bootstrap upang gawing mas maganda ang mga pahina ng aming proyekto. Ang mga pahina ay nilikha sa direktoryo ng "src/main/resources/templates". Ang mga file ay may extension na bigote. Ang paglalagay ng html code nang direkta sa artikulo ay gagawin itong masyadong malaki, kaya narito ang isang link sa folder ng mga template sa GitHub repository ng proyekto .

Pag-configure ng Spring Security para sa Classic na Pag-login

Tinutulungan kami ng Spring Security na protektahan ang application at ang mga mapagkukunan nito mula sa hindi awtorisadong pag-access. Gagawa tayo ng isang maigsi na pagsasaayos ng pagtatrabaho sa isang klase SecurityConfigna minana mula sa WebSecurityConfigurerAdapter, na ilalagay natin sa pakete config. Markahan natin ito ng @EnableWebSecurity annotation, na magbibigay-daan sa suporta sa Spring Security, at ang @Configuration annotation, na nagpapahiwatig na ang klase na ito ay naglalaman ng ilang configuration. Tandaan: ang awtomatikong na-configure na pom.xml ay naglalaman ng bersyon ng Spring Boot parent component 2.1.4.RELEASE, na pumigil sa Security na maipatupad sa itinatag na paraan. Upang maiwasan ang mga salungatan sa proyekto, inirerekumenda na baguhin ang bersyon sa 2.0.1.RELEASE.

Pangunahing configuration SecurityConfig

Ang aming configuration ay magagawang:
  1. I-encrypt ang mga password gamit ang BCryptPasswordEncoder:

    @Autowired
    private PasswordEncoder passwordEncoder;
    
    @Bean
    PasswordEncoder passwordEncoder()
    {
      PasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
      return passwordEncoder;
    }
  2. Mag-log in gamit ang isang espesyal na nakasulat na provider ng pagpapatunay:

    @Autowired
    private AuthProvider authProvider;
    
    @Override
    protected void configure(AuthenticationManagerBuilder auth)
    {
      auth.authenticationProvider(authProvider);
    }
  3. Payagan ang mga hindi kilalang user na ma-access ang home page, registration at login page. Ang lahat ng iba pang mga kahilingan ay dapat isagawa ng mga naka-log in na user. Italaga natin ang naunang inilarawan na "/login" bilang pahina sa pag-login. Kung matagumpay ang pag-login, dadalhin ang user sa isang page na may listahan ng mga tala; kung may error, mananatili ang user sa login page. Sa matagumpay na paglabas, dadalhin ang user sa pangunahing pahina.

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

Custom na login ng user

Ang isang self-written AuthProvideray magbibigay-daan sa gumagamit na mag-log in hindi lamang sa pamamagitan ng email, kundi pati na rin sa pamamagitan ng username.
@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;
  }
}
Tulad ng maaaring napansin mo, ang klase UserServicena matatagpuan sa package ay may pananagutan sa pag-load ng user services. Sa aming kaso, naghahanap ito ng user hindi lamang sa pamamagitan ng field username, tulad ng built-in na pagpapatupad, kundi pati na rin sa pamamagitan ng user name, pangalan ng Google account at email ng Google account. Ang huling dalawang pamamaraan ay magiging kapaki-pakinabang sa amin kapag nagpapatupad ng pag-login sa pamamagitan ng OAuth2. Narito ang klase ay ibinigay sa isang pinaikling bersyon.
@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;
  }
}
Tandaan: huwag kalimutang isulat ang mga kinakailangang pamamaraan sa UserRepo!

Pagbutihin natin ang controller

Na-configure namin ang Spring Security. Ngayon na ang oras upang samantalahin ito sa iyong controller ng mga tala. Ngayon, ang bawat pagmamapa ay tatanggap ng karagdagang Principal parameter, kung saan susubukan nitong hanapin ang user. Bakit hindi ako direktang makapag-inject ng klase User? Pagkatapos ay magkakaroon ng salungatan dahil sa hindi pagkakatugma ng mga uri ng user kapag sumulat kami ng login sa pamamagitan ng mga social network. Nagbibigay kami ng kinakailangang flexibility nang maaga. Ang aming code ng controller ng mga tala ay ganito na ngayon:
@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";
}
Tandaan: ang proyekto ay may naka-enable na proteksyon ng CSRF bilang default , kaya i-disable ito para sa iyong sarili (http.csrf().disable()), o huwag kalimutan, bilang may-akda ng artikulo, na magdagdag ng nakatagong field na may csrf token sa lahat ng post requests.

Ilunsad

Sinusubukan naming ilunsad ang proyekto.
Ipakilala natin ang regular na pag-log in sa pamamagitan ng email at OAuth2 sa Spring Security gamit ang halimbawa ng serbisyo ng mga tala - 1
Ipakilala natin ang regular na pag-log in sa pamamagitan ng email at OAuth2 sa Spring Security gamit ang halimbawa ng serbisyo ng mga tala - 2
Nakita namin na may lumitaw na bagong user sa database. Ang password ay naka-encrypt.
Ipakilala natin ang regular na pag-log in sa pamamagitan ng email at OAuth2 sa Spring Security gamit ang halimbawa ng serbisyo ng mga tala - 3
Ipakilala natin ang regular na pag-log in sa pamamagitan ng email at OAuth2 sa Spring Security gamit ang halimbawa ng serbisyo ng mga tala - 4
Ipakilala natin ang regular na pag-log in sa pamamagitan ng email at OAuth2 sa Spring Security gamit ang halimbawa ng serbisyo ng mga tala - 5
Ipakilala natin ang regular na pag-log in sa pamamagitan ng email at OAuth2 sa Spring Security gamit ang halimbawa ng serbisyo ng mga tala - 6
Ang mga tala ay nai-save sa database.
Ipakilala natin ang regular na pag-log in sa pamamagitan ng email at OAuth2 sa Spring Security gamit ang halimbawa ng serbisyo ng mga tala - 7
Nakita namin na matagumpay na nailunsad at tumatakbo ang proyekto. Para sa kumpletong kaligayahan, kailangan lang namin ng kakayahang mag-log in sa pamamagitan ng mga social network. Well, magsimula tayo!

Pagse-set up ng OAuth2 gamit ang Google bilang isang halimbawa sa Spring Security

Kapag nagpapatupad ng OAuth2, umasa ako sa opisyal na tutorial na ito mula sa Spring . Upang suportahan ang OAuth2, idagdag ang sumusunod na library sa pom.xml:
<dependency>
  <groupId>org.springframework.security.oauth.boot</groupId>
  <artifactId>spring-security-oauth2-autoconfigure</artifactId>
  <version>2.0.0.RELEASE</version>
</dependency>
Baguhin natin ang configuration ng Spring Security natin sa SecurityConfig. Una, idagdag natin ang @EnableOAuth2Client annotation. Awtomatiko nitong kukunin kung ano ang kailangan mong mag-log in sa pamamagitan ng mga social network.

I-filter ang configuration at application.properties

Mag-inject tayo ng OAuth2ClientContext na gagamitin sa aming configuration ng seguridad.
@Autowired
private OAuth2ClientContext oAuth2ClientContext;
Ginagamit ang OAuth2ClientContext kapag gumagawa ng filter na nagpapatunay sa kahilingan sa social login ng user. Available ang filter salamat sa @EnableOAuth2Client annotation. Ang kailangan lang nating gawin ay tawagan ito sa tamang pagkakasunud-sunod, bago ang pangunahing filter ng Spring Security. Pagkatapos lamang ay makakahuli kami ng mga pag-redirect sa panahon ng proseso ng pag-log in gamit ang OAuth2. Upang gawin ito, ginagamit namin ang FilterRegistrationBean, kung saan itinakda namin ang priyoridad ng aming filter sa -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;
}
Kailangan mo ring magdagdag ng bagong filter sa configure(HttpSecurity http) function:
http.addFilterBefore(ssoFilter(), UsernamePasswordAuthenticationFilter.class);
Kailangan ding malaman ng filter na nakarehistro ang kliyente sa pamamagitan ng Google. Ang @ConfigurationProperties annotation ay tumutukoy kung aling mga katangian ng configuration ang hahanapin sa application.properties.
@Bean
@ConfigurationProperties("google.client")
public AuthorizationCodeResourceDetails google()
{
  return new AuthorizationCodeResourceDetails();
}
Upang makumpleto ang pagpapatunay, kailangan mong tukuyin ang endpoint ng impormasyon ng user ng Google:
@Bean
@ConfigurationProperties("google.resource")
public ResourceServerProperties googleResource()
{
  return new ResourceServerProperties();
}
Nang mairehistro ang aming application sa Google Cloud Platform , magdaragdag kami ng mga property na may naaangkop na prefix sa 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

Mga highlight ng pagpaparehistro ng isang application sa Google Cloud Platform

Path: Mga API at Serbisyo -> Window ng Kahilingan sa Pag-access ng Mga Kredensyal OAuth:
  • Pangalan ng application: Spring login form at OAuth2 tutorial
  • Suporta sa email address: ang iyong email
  • Saklaw ng Google API: email, profile, openid
  • Mga awtorisadong domain: me.org
  • Mag-link sa pangunahing pahina ng aplikasyon: http://me.org:8080
  • Link sa patakaran sa privacy ng app: http://me.org:8080
  • Link sa mga tuntunin ng paggamit ng application: http://me.org:8080
Mga kredensyal:
  • Uri: Web Application
  • Pamagat: Spring login form at OAuth2 tutorial
  • Pinapayagan ang mga mapagkukunan ng JavaScript: http://me.org, http://me.org:8080
  • Mga pinapayagang URI sa pag-redirect: http://me.org:8080/login, http://me.org:8080/login/google
Tandaan: dahil ayaw gumana ng Google sa address na localhost:8080, idagdag ang linyang “127.0.0.1 me.org” o katulad ng file na C:\Windows\System32\drivers\etc\hosts sa dulo. Ang pangunahing bagay ay ang domain ay nasa isang klasikong anyo.

CustomUserInfoTokenServices

Napansin mo ba ang salitang Custom sa paglalarawan ng function ng filter? Klase CustomUserInfoTokenServices. Oo, gagawa kami ng sarili naming klase na may blackjack at ang kakayahang i-save ang user sa database! Gamit ang Ctrl-N keyboard shortcut sa IntelliJ IDEA, mahahanap at makikita mo kung paano UserInfoTokenServicesipinapatupad ang default. Kopyahin natin ang code nito sa bagong likhang klase CustomUserInfoTokenServices. Karamihan sa mga ito ay maaaring iwanang hindi nagbabago. Bago baguhin ang lohika ng mga function, idagdag natin UserRepoat bilang mga pribadong field ng klase PasswordEncoder. Gumawa tayo ng mga setter para sa kanila. Idagdag natin ang @Autowired UserRepo userRepo sa klase ng SecurityConfig. Tinitingnan namin kung paano nawawala ang pointer sa error sa paraan ng paggawa ng filter, at natutuwa kami. Bakit hindi direktang mailapat ang @Autowired sa CustomUserInfoTokenServices? Dahil ang klase na ito ay hindi kukuha ng dependency, dahil ito mismo ay hindi minarkahan ng anumang Spring annotation, at ang constructor nito ay tahasang nilikha kapag ang filter ay ipinahayag. Alinsunod dito, ang mekanismo ng DI ng Spring ay hindi alam ang tungkol dito. Kung i-annotate namin ang @Autowired sa anumang bagay sa klase na ito, makakakuha kami ng NullPointerException kapag ginamit. Ngunit sa pamamagitan ng mga tahasang setter ay gumagana nang maayos ang lahat. Pagkatapos ipatupad ang mga kinakailangang bahagi, ang pangunahing bagay ng interes ay nagiging function na loadAuthentication, kung saan ang Map<String, Object> na may impormasyon tungkol sa user ay nakuha. Sa proyektong ito ko ipinatupad ang pag-save ng isang user na naka-log in sa pamamagitan ng isang social network sa database. Dahil gumagamit kami ng Google account bilang OAuth2 provider, tinitingnan namin kung ang mapa ay naglalaman ng field na "sub" na karaniwan para sa Google. Kung ito ay naroroon, nangangahulugan ito na ang impormasyon tungkol sa gumagamit ay natanggap nang tama. Lumilikha kami ng bagong user at i-save ito sa database.
@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);
}
Kapag gumagamit ng ilang provider, maaari mong tukuyin ang iba't ibang mga opsyon sa isang CustomUserInfoTokenServices, at magrehistro ng iba't ibang klase ng mga katulad na serbisyo sa paraan ng pagdeklara ng filter. Ngayon ang parehong User at OAuth2Authentication ay maaaring kumilos bilang Principal. Dahil isinaalang-alang namin sa UserService nang maaga ang pag-load ng user sa pamamagitan ng data ng Google, gagana ang application para sa parehong uri ng mga user. Binabago namin ang controller ng pangunahing page ng proyekto upang mai-redirect nito ang mga user na naka-log in gamit ang OAuth2 sa page ng mga tala.
@GetMapping("/")
public String index(Principal principal)
{
  if(principal != null)
  {
     return "redirect:/notes";
  }
  return "index";
}

Panghuling paglulunsad ng proyekto

Pagkatapos ng maliliit na pagbabago sa kosmetiko at pagdaragdag ng exit button, isinasagawa namin ang panghuling paglulunsad ng proyekto.
Ipakilala natin ang regular na pag-log in sa pamamagitan ng email at OAuth2 sa Spring Security gamit ang halimbawa ng serbisyo ng mga tala - 8
Ipakilala natin ang regular na pag-log in sa pamamagitan ng email at OAuth2 sa Spring Security gamit ang halimbawa ng serbisyo ng mga tala - 9
Ipakilala natin ang regular na pag-log in sa pamamagitan ng email at OAuth2 sa Spring Security gamit ang halimbawa ng serbisyo ng mga tala - 10
Ipakilala natin ang regular na pag-log in sa pamamagitan ng email at OAuth2 sa Spring Security gamit ang halimbawa ng serbisyo ng mga tala - 11
Ipakilala natin ang regular na pag-log in sa pamamagitan ng email at OAuth2 sa Spring Security gamit ang halimbawa ng serbisyo ng mga tala - 12
Ipakilala natin ang regular na pag-login sa pamamagitan ng email at OAuth2 sa Spring Security gamit ang halimbawa ng serbisyo ng mga tala - 13
Ipakilala natin ang regular na pag-log in sa pamamagitan ng email at OAuth2 sa Spring Security gamit ang halimbawa ng serbisyo ng mga tala - 14
Ipakilala natin ang regular na pag-log in sa pamamagitan ng email at OAuth2 sa Spring Security gamit ang halimbawa ng serbisyo ng mga tala - 15
Matagumpay na nag-log in ang user sa pamamagitan ng regular na form at sa pamamagitan ng Google account. Ito ang gusto namin! Umaasa ako na ang artikulong ito ay na-clear ang ilang mga punto tungkol sa paglikha ng isang web application, pag-secure nito sa Spring Security, at pagsasama-sama ng iba't ibang paraan ng pag-login. Gamit ang buong code ng proyekto magagawa mo
Mga komento
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION