Murojaatimni yozish paytida men foydalanuvchini elektron pochta va ijtimoiy tarmoqlar orqali qanday qilib ro'yxatdan o'tkazishga oid aniq maqolalar etishmasligiga duch keldim. Klassik kirish formasini o'rnatish bo'yicha yaxshi darsliklar bor edi. OAuth2 bo'yicha yaxshi darsliklar bor edi . Ikki usulni qanday birlashtirish haqida jinoiy jihatdan kam ma'lumot bor edi. Qidiruv jarayonida biz amaliy yechim topishga muvaffaq bo'ldik. U o'zini yakuniy haqiqat deb da'vo qilmaydi, lekin u o'z vazifasini bajaradi. Ushbu maqolada men noldan o'xshash Spring Security konfiguratsiyasi bilan eslatma saqlash xizmatini qanday amalga oshirishni ko'rsataman. Eslatma: agar o'quvchi bahor bo'yicha hech bo'lmaganda bir nechta darsliklardan o'tgan bo'lsa yaxshi bo'ladi, chunki e'tibor faqat bahor xavfsizligiga qaratiladi, omborlar, kontrollerlar va boshqalar haqida batafsil tushuntirishlarsiz. Aks holda, allaqachon juda katta maqola chiqadi. ulkan bo'ling. Tarkib
Ma'lumotlar bazasida yangi foydalanuvchi paydo bo'lganini ko'ramiz. Parol shifrlangan.
Eslatmalar ma'lumotlar bazasida saqlanadi.
Loyiha muvaffaqiyatli boshlanganini va ishlayotganini ko'ramiz. To'liq baxt uchun bizga faqat ijtimoiy tarmoqlar orqali kirish imkoniyati kerak. Xo'sh, boshlaylik!
Endi foydalanuvchi ham, OAuth2Authentication ham asosiy vazifani bajarishi mumkin. Biz UserService-da foydalanuvchining Google ma'lumotlari orqali yuklanishini oldindan hisobga olganimiz sababli, dastur ikkala turdagi foydalanuvchilar uchun ham ishlaydi. Biz loyihaning asosiy sahifa boshqaruvchisini OAuth2 yordamida tizimga kirgan foydalanuvchilarni qaydlar sahifasiga yoʻnaltirish uchun oʻzgartiramiz.
Foydalanuvchi oddiy shakl orqali ham, Google hisobi orqali ham muvaffaqiyatli tizimga kiradi. Bu biz xohlagan narsa edi! Umid qilamanki, ushbu maqola veb-ilovani yaratish, uni Spring Security bilan himoya qilish va turli xil kirish usullarini birlashtirish bo'yicha ba'zi fikrlarni aniqladi. To'liq loyiha kodi bilan mumkin
- Loyiha yaratish
- Ob'ektlar va ilovalar mantig'ini yaratish
- Klassik kirish uchun bahor xavfsizligini sozlash
- SecurityConfig asosiy konfiguratsiyasi
- Shaxsiy foydalanuvchi login
- Keling, boshqaruvchini yaxshilaymiz
- Ishga tushirish
- Spring Security-da Google-dan foydalanib, OAuth2-ni o'rnatish
- Filtr konfiguratsiyasi va application.properties
- Ilovani Google Cloud Platform bilan ro'yxatdan o'tkazishning muhim jihatlari
- CustomUserInfoTokenServices
- Loyihaning yakuniy boshlanishi
Loyiha yaratish
Biz start.spring.io saytiga o'tamiz va loyihaning asosini tashkil qilamiz:- Web - o'rnatilgan Tomcat-da dasturni ishga tushirish, url xaritalari va shunga o'xshashlar;
- JPA - ma'lumotlar bazasiga ulanish;
- Mo'ylov - veb-sahifalarni yaratish uchun ishlatiladigan shablon mexanizmi;
- Xavfsizlik - ilovalarni himoya qilish. Ushbu maqola aynan shu maqsadda yaratilgan.
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.34</version>
</dependency>
application.properties konfiguratsiyasi hozirda quyidagicha:
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
Ob'ektlar va ilovalar mantig'ini yaratish
Ob'ektlar
entities
Keling , ma'lumotlar bazasi ob'ektlarini joylashtiradigan paket yarataylik . Foydalanuvchi Spring Security konfiguratsiyasi uchun zarur bo'lgan User
interfeysni amalga oshiradigan sinf tomonidan tavsiflanadi . UserDetails
Foydalanuvchi identifikatori, foydalanuvchi nomi (bu elektron pochta), parol, ism, rol, faoliyat bayrog'i, Google hisobi nomi va elektron pochta manziliga ega bo'ladi ( googleName
va 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
}
Foydalanuvchi rollari Spring Security-ga kirishni tartibga solish uchun ishlatiladi. Bizning ilovamiz faqat bitta roldan foydalanadi:
public enum Role implements GrantedAuthority
{
USER;
@Override
public String getAuthority()
{
return name();
}
}
Keling, id, eslatma sarlavhasi, eslatma tanasi va u tegishli foydalanuvchi identifikatori bilan eslatma sinfini yarataylik:
@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()
}
Repozitariylar
Ob'ektlarni ma'lumotlar bazasiga saqlash uchun biz uchun barcha iflos ishlarni bajaradigan omborlar kerak. Keling, paketni yaratamiz , unda biz interfeysdan meros bo'lib qolganrepos
interfeyslarni yaratamiz . 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);
}
Kontrollerlar
Bizning eslatmalar xizmatimiz quyidagi sahifalarga ega bo'ladi:- Uy;
- Ro'yxatdan o'tish;
- Kirish;
- Foydalanuvchi qaydlari ro'yxati.
controllers
sinfni o'z ichiga olgan paketni yarataylik . IndexController
Sinf RegistrationController
foydalanuvchini ro'yxatdan o'tkazish uchun javobgardir. Post-mapping shakldan ma'lumotlarni oladi, foydalanuvchini ma'lumotlar bazasiga saqlaydi va kirish sahifasiga yo'naltiradi. PasswordEncoder
keyinroq bayon qilinadi. U parollarni shifrlash uchun ishlatiladi.
@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";
}
Eslatmalar ro'yxati sahifasi uchun mas'ul boshqaruvchida hozirda soddalashtirilgan funksiyalar mavjud bo'lib, ular Spring Security joriy etilgandan keyin yanada murakkablashadi.
@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";
}
}
Biz kirish sahifasi uchun kontroller yozmaymiz, chunki u Spring Security tomonidan qo'llaniladi. Buning o'rniga bizga maxsus konfiguratsiya kerak bo'ladi. Odatdagidek, keling, boshqa paket yaratamiz, uni chaqiramiz config
va sinfni o'sha yerga joylashtiramiz MvcConfig
. Spring Security konfiguratsiyasini yozganimizda, biz "/login" dan foydalanganda qaysi sahifaga murojaat qilayotganimizni bilib oladi.
@Configuration
public class MvcConfig implements WebMvcConfigurer
{
public void addViewControllers(ViewControllerRegistry registry)
{
registry.addViewController("/login").setViewName("login");
registry.setOrder(Ordered.HIGHEST_PRECEDENCE);
}
}
Sahifalar
Sahifalar yaratish uchun Mo'ylov shablon mexanizmidan foydalanaman . Siz boshqasini amalga oshirishingiz mumkin, bu muhim emas. Barcha sahifalarda ishlatiladigan meta-ma'lumot uchun meta.mo'ylov fayli yaratilgan. Loyihamiz sahifalarini yanada chiroyli qilish uchun unga Bootstrap ham kiradi. Sahifalar "src/main/resources/templates" katalogida yaratiladi. Fayllarda kengaytmali mo'ylov mavjud. HTML kodini to'g'ridan-to'g'ri maqolaga joylashtirish uni juda katta qiladi, shuning uchun bu erda loyihaning GitHub omboridagi andozalar jildiga havola .Klassik kirish uchun bahor xavfsizligini sozlash
Spring Security ilova va uning resurslarini ruxsatsiz kirishdan himoya qilishga yordam beradi.SecurityConfig
Biz meros qilib olingan sinfda qisqacha ishlaydigan konfiguratsiyani yaratamiz WebSecurityConfigurerAdapter
, uni paketga joylashtiramiz config
. Keling, uni Spring Security qo'llab-quvvatlashini ta'minlaydigan @EnableWebSecurity izohi va ushbu sinfda ba'zi konfiguratsiyalar mavjudligini ko'rsatadigan @Configuration izohi bilan belgilaymiz. Eslatma: Avtomatik sozlangan pom.xml 2.1.4.RELEASE Spring Boot asosiy komponentining versiyasini o'z ichiga olgan bo'lib, bu xavfsizlikning belgilangan tarzda amalga oshirilishiga to'sqinlik qildi. Loyihada ziddiyatlarni oldini olish uchun versiyani 2.0.1.RELEASE ga o'zgartirish tavsiya etiladi.
SecurityConfig asosiy konfiguratsiyasi
Bizning konfiguratsiyamiz quyidagilarni amalga oshirishi mumkin:-
Parollarni shifrlash
BCryptPasswordEncoder
:@Autowired private PasswordEncoder passwordEncoder; @Bean PasswordEncoder passwordEncoder() { PasswordEncoder passwordEncoder = new BCryptPasswordEncoder(); return passwordEncoder; }
-
Maxsus yozilgan autentifikatsiya provayderi yordamida tizimga kiring:
@Autowired private AuthProvider authProvider; @Override protected void configure(AuthenticationManagerBuilder auth) { auth.authenticationProvider(authProvider); }
-
Anonim foydalanuvchilarga bosh sahifaga, ro'yxatdan o'tish va kirish sahifalariga kirishga ruxsat bering. Boshqa barcha so'rovlar tizimga kirgan foydalanuvchilar tomonidan bajarilishi kerak. Kirish sahifasi sifatida avval tavsiflangan “/login” ni belgilaymiz. Agar tizimga kirish muvaffaqiyatli bo'lsa, foydalanuvchi qaydlar ro'yxati bilan sahifaga o'tadi, agar xato bo'lsa, foydalanuvchi kirish sahifasida qoladi. Muvaffaqiyatli chiqqandan so'ng, foydalanuvchi asosiy sahifaga o'tadi.
@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(); }
Shaxsiy foydalanuvchi login
O'z-o'zidan yozilganAuthProvider
foydalanuvchiga nafaqat elektron pochta orqali, balki foydalanuvchi nomi bilan ham kirish imkonini beradi.
@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;
}
}
Siz sezganingizdek, UserService
paketda joylashgan sinf foydalanuvchini yuklash uchun javobgardir services
. Bizning holatda, u foydalanuvchini nafaqat maydon username
, masalan, o'rnatilgan dastur, balki foydalanuvchi nomi, Google hisobi nomi va Google hisobi elektron pochtasi bo'yicha ham qidiradi. OAuth2 orqali kirishni amalga oshirishda oxirgi ikki usul biz uchun foydali bo'ladi. Bu erda sinf qisqartirilgan versiyada berilgan.
@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;
}
}
Eslatma: kerakli usullarni yozishni unutmang UserRepo
!
Keling, boshqaruvchini yaxshilaymiz
Biz Spring Security-ni sozladik. Endi qaydlar boshqaruvchisida bundan foydalanish vaqti keldi. Endi har bir xaritalash qo'shimcha Principal parametrini qabul qiladi va u orqali foydalanuvchini topishga harakat qiladi. Nega men sinfni to'g'ridan-to'g'ri kirita olmaymanUser
? Keyin ijtimoiy tarmoqlar orqali login yozganimizda foydalanuvchilar turlarining mos kelmasligi sababli ziddiyat yuzaga keladi. Biz oldindan kerakli moslashuvchanlikni ta'minlaymiz. Endi bizning qaydlar boshqaruvchisi kodi quyidagicha ko'rinadi:
@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";
}
Eslatma: loyihada sukut bo'yicha CSRF himoyasi yoqilgan , shuning uchun uni o'zingiz uchun o'chirib qo'ying (http.csrf().disable()) yoki maqola muallifi sifatida csrf tokeni bilan yashirin maydon qo'shishni unutmang. barcha post so'rovlariga.
Ishga tushirish
Loyihani ishga tushirishga harakat qilyapmiz.Spring Security-da Google-dan foydalanib, OAuth2-ni o'rnatish
OAuth2 ni amalga oshirishda men Spring dan ushbu rasmiy qo'llanmaga tayandim . OAuth2-ni qo'llab-quvvatlash uchun pom.xml-ga quyidagi kutubxonani qo'shing:<dependency>
<groupId>org.springframework.security.oauth.boot</groupId>
<artifactId>spring-security-oauth2-autoconfigure</artifactId>
<version>2.0.0.RELEASE</version>
</dependency>
Keling, Spring Security konfiguratsiyasini o'zgartiraylik SecurityConfig
. Birinchidan, @EnableOAuth2Client izohini qo'shamiz. Ijtimoiy tarmoqlar orqali tizimga kirishingiz kerak bo'lgan narsalarni avtomatik ravishda tortib oladi.
Filtr konfiguratsiyasi va application.properties
Xavfsizlik konfiguratsiyasida foydalanish uchun OAuth2ClientContext ni kiritamiz.@Autowired
private OAuth2ClientContext oAuth2ClientContext;
OAuth2ClientContext foydalanuvchining ijtimoiy kirish soʻrovini tasdiqlovchi filtr yaratishda foydalaniladi. Filtr @EnableOAuth2Client izohi tufayli mavjud. Biz qilishimiz kerak bo'lgan yagona narsa, asosiy Spring Security filtridan oldin uni to'g'ri tartibda chaqirishdir . Shundan keyingina biz OAuth2 bilan tizimga kirish jarayonida qayta yo'naltirishlarni ushlay olamiz. Buning uchun biz dan foydalanamiz FilterRegistrationBean
, unda biz filtrimizning ustuvorligini -100 ga o'rnatamiz.
@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;
}
Shuningdek, configure(HttpSecurity http) funksiyasiga yangi filtr qo'shishingiz kerak:
http.addFilterBefore(ssoFilter(), UsernamePasswordAuthenticationFilter.class);
Filtr mijozning Google orqali ro'yxatdan o'tganligini ham bilishi kerak. @ConfigurationProperties izohi application.properties da qaysi konfiguratsiya xususiyatlarini izlash kerakligini belgilaydi.
@Bean
@ConfigurationProperties("google.client")
public AuthorizationCodeResourceDetails google()
{
return new AuthorizationCodeResourceDetails();
}
Autentifikatsiyani yakunlash uchun Google foydalanuvchi maʼlumotlarining soʻnggi nuqtasini koʻrsatishingiz kerak:
@Bean
@ConfigurationProperties("google.resource")
public ResourceServerProperties googleResource()
{
return new ResourceServerProperties();
}
Ilovamizni Google Cloud Platform- da ro'yxatdan o'tkazgandan so'ng , biz application.properties ga tegishli prefikslar bilan xususiyatlarni qo'shamiz:
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
Ilovani Google Cloud Platform bilan ro'yxatdan o'tkazishning muhim jihatlari
Yoʻl: API va xizmatlar -> Hisob maʼlumotlari OAuth kirish soʻrovi oynasi:- Ilova nomi: Bahorgi login formasi va OAuth2 qoʻllanmasi
- Yordam elektron pochta manzili: sizning elektron pochtangiz
- Google API uchun qamrov: elektron pochta, profil, openid
- Vakolatli domenlar: me.org
- Ilovaning asosiy sahifasiga havola: http://me.org:8080
- Ilova maxfiylik siyosatiga havola: http://me.org:8080
- Ilovadan foydalanish shartlariga havola: http://me.org:8080
- Turi: Veb-ilova
- Sarlavha: Bahorgi tizimga kirish shakli va OAuth2 qo'llanmasi
- Ruxsat etilgan JavaScript manbalari: http://me.org, http://me.org:8080
- Ruxsat etilgan qayta yo'naltirish URI'lari: http://me.org:8080/login, http://me.org:8080/login/google
CustomUserInfoTokenServices
Filtr funksiyasi tavsifida Custom so'zini payqadingizmi? SinfCustomUserInfoTokenServices
. Ha, biz blackjack va foydalanuvchini ma'lumotlar bazasida saqlash qobiliyati bilan o'z sinfimizni yaratamiz! IntelliJ IDEA-da Ctrl-N klaviatura yorlig'idan foydalanib, siz UserInfoTokenServices
sukut bo'yicha qanday amalga oshirilishini topishingiz va ko'rishingiz mumkin. Keling, uning kodini yangi yaratilgan sinfga ko'chiraylik CustomUserInfoTokenServices
. Uning ko'p qismini o'zgarishsiz qoldirish mumkin. Funktsiyalar mantig'ini o'zgartirishdan oldin sinfning shaxsiy maydonlari UserRepo
sifatida qo'shamiz PasswordEncoder
. Keling, ular uchun sozlagichlarni yarataylik. SecurityConfig sinfiga @Autowired UserRepo userRepo qo'shamiz. Filtrni yaratish usulidagi xatoga ko'rsatgich qanday yo'qolganiga qaraymiz va biz quvonamiz. Nima uchun @Autowired to'g'ridan-to'g'ri CustomUserInfoTokenServices xizmatiga qo'llanilmadi? Chunki bu sinf bog'liqlikni tanlamaydi, chunki uning o'zi hech qanday Spring izohi bilan belgilanmagan va filtr e'lon qilinganda uning konstruktori aniq yaratilgan. Shunga ko'ra, Springning DI mexanizmi bu haqda bilmaydi. Agar biz ushbu sinfdagi biror narsaga @Autowired izohini qo'shsak, biz foydalanilganda NullPointerExceptionni olamiz. Ammo aniq sozlagichlar orqali hamma narsa juda yaxshi ishlaydi. Kerakli komponentlarni amalga oshirgandan so'ng, asosiy qiziqish ob'ekti foydalanuvchi haqidagi ma'lumotlarga ega Map<String, Object> olinadigan loadAuthentication funksiyasiga aylanadi. Aynan shu loyihada men ijtimoiy tarmoq orqali kirgan foydalanuvchini ma'lumotlar bazasiga saqlashni amalga oshirdim. Biz Google hisobidan OAuth2 provayderi sifatida foydalanayotganimiz sababli, xaritada Google uchun odatiy bo‘lgan “sub” maydoni mavjudligini tekshiramiz. Agar u mavjud bo'lsa, bu foydalanuvchi haqidagi ma'lumot to'g'ri qabul qilinganligini anglatadi. Biz yangi foydalanuvchi yaratamiz va uni ma'lumotlar bazasiga saqlaymiz.
@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 nechta provayderlardan foydalanganda siz bitta CustomUserInfoTokenServices-da turli xil variantlarni belgilashingiz va filtr deklaratsiyasi usulida o'xshash xizmatlarning turli sinflarini ro'yxatdan o'tkazishingiz mumkin.
@GetMapping("/")
public String index(Principal principal)
{
if(principal != null)
{
return "redirect:/notes";
}
return "index";
}
GO TO FULL VERSION