منهنجي ايپليڪيشن لکڻ دوران، مون کي واضح مضمونن جي کوٽ جو سامنا ٿيو ته ڪيئن حاصل ڪجي صارف کي اي ميل ۽ سماجي نيٽ ورڪن ذريعي رجسٽر ڪرڻ لاءِ. کلاسک لاگ ان فارم قائم ڪرڻ تي سٺا سبق هئا. OAuth2 تي سٺا سبق هئا . ٻن طريقن کي ڪيئن گڏ ڪرڻ تي مجرمانه طور تي ٿوري معلومات هئي. ڳولا جي عمل دوران، اسان هڪ قابل عمل حل سان گڏ اچڻ جي قابل هئا. اهو حتمي سچ هجڻ جي دعويٰ نٿو ڪري، پر اهو پنهنجو ڪم پورو ڪري ٿو. هن آرٽيڪل ۾ آئون ڏيکاريندس ته هڪ نوٽ اسٽوريج سروس کي ڪيئن لاڳو ڪجي ساڳئي اسپرنگ سيڪيورٽي ترتيب سان شروع کان. نوٽ: اهو سٺو آهي ته پڙهندڙ گهٽ ۾ گهٽ بهار جي باري ۾ ڪجهه سبقن مان گذري چڪو آهي، ڇو ته ذخيرن، ڪنٽرولرز وغيره جي تفصيلي وضاحتن کان سواء، صرف اسپرنگ سيڪيورٽي تي ڌيان ڏنو ويندو. ٻي صورت ۾، اڳ ۾ ئي هڪ وڏو مضمون نڪري ويندو. وڏو ٿيڻ. مواد
اسان ڏسون ٿا ته ڊيٽابيس ۾ هڪ نئون صارف ظاهر ٿيو آهي. پاسورڊ انڪريپٽ ٿيل آهي.
نوٽس ڊيٽابيس ۾ محفوظ ڪيا ويا آهن.
اسان ڏسون ٿا ته پروجيڪٽ ڪاميابيءَ سان شروع ۽ هلندڙ آهي. مڪمل خوشي لاء، اسان کي صرف سماجي نيٽ ورڪ ذريعي لاگ ان ڪرڻ جي صلاحيت جي ضرورت آهي. خير، اچو ته شروع ڪريون!
ھاڻي ٻئي صارف ۽ OAuth2Authentication پرنسپل طور ڪم ڪري سگھن ٿا. جيئن ته اسان صارف جي خدمت ۾ گوگل ڊيٽا ذريعي صارف جي لوڊ ٿيڻ کي اڳ ۾ ئي حساب ۾ ورتو، ايپليڪيشن ٻنهي قسمن جي استعمال ڪندڙن لاءِ ڪم ڪندي. اسان پروجيڪٽ جي مکيه صفحي جي ڪنٽرولر کي تبديل ڪريون ٿا ته جيئن اهو OAuth2 استعمال ڪندي لاگ ان ٿيل صارفين کي نوٽس واري صفحي ڏانهن منتقل ڪري.
صارف ڪاميابيءَ سان لاگ ان ٿئي ٿو باقاعدي فارم ۽ گوگل اڪائونٽ ذريعي. اهو ئي آهي جيڪو اسان چاهيون ٿا! مون کي اميد آهي ته هي آرٽيڪل ويب ايپليڪيشن ٺاهڻ، ان کي اسپرنگ سيڪيورٽي سان محفوظ ڪرڻ، ۽ مختلف لاگ ان طريقن کي گڏ ڪرڻ بابت ڪجهه نقطا صاف ڪري چڪو آهي. مڪمل پروجيڪٽ ڪوڊ سان توهان ڪري سگهو ٿا
- پروجيڪٽ ٺاهڻ
- ايجاد ۽ ايپليڪيشن منطق
- ڪلاسيڪل لاگ ان لاءِ اسپرنگ سيڪيورٽي کي ترتيب ڏيڻ
- OAuth2 ترتيب ڏيڻ گوگل کي استعمال ڪندي مثال طور اسپرنگ سيڪيورٽي ۾
- فلٽر ٺاھ جوڙ ۽ application.properties
- گوگل ڪلائوڊ پليٽ فارم سان ايپليڪيشن رجسٽر ڪرڻ جا نمايان
- CustomUserInfoTokenServices
- منصوبي جي آخري لانچ
پروجيڪٽ ٺاهڻ
اسان وڃو start.spring.io ۽ پروجيڪٽ جو بنياد ٺاهيو:- ويب - بلٽ ان ٽامڪٽ تي هڪ ايپليڪيشن لانچ ڪرڻ، يو آر ايل ميپنگ ۽ ان وانگر؛
- JPA - ڊيٽابيس ڪنيڪشن؛
- Mustache هڪ ٽيمپليٽ انجڻ آهي جيڪو ويب صفحا ٺاهڻ لاءِ استعمال ٿيندو آهي.
- سيڪيورٽي - ايپليڪيشن تحفظ. اھو اھو آھي جنھن لاء ھي مضمون ٺاھيو ويو آھي.
<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
، جيڪو بهار جي حفاظت جي ترتيب لاءِ گهربل هوندو. استعمال ڪندڙ وٽ هڪ id، يوزرنيم (هي اي ميل آهي)، پاسورڊ، نالو، ڪردار، سرگرمي پرچم، گوگل کاتي جو نالو ۽ اي ميل هوندو ( 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
}
استعمال ڪندڙ ڪردار اسپرنگ سيڪيورٽي ۾ رسائي کي منظم ڪرڻ لاءِ استعمال ڪيا ويندا آهن. اسان جي ايپليڪيشن صرف هڪ ڪردار استعمال ڪندي:
public enum Role implements GrantedAuthority
{
USER;
@Override
public String getAuthority()
{
return name();
}
}
اچو ته id، نوٽ عنوان، نوٽ باڊي ۽ صارف جي سڃاڻپ سان هڪ نوٽ ڪلاس ٺاهيون جنهن سان اهو تعلق رکي ٿو:
@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";
}
نوٽس لسٽ واري صفحي لاءِ ذميوار ڪنٽرولر هن وقت آسان ڪارڪردگيءَ تي مشتمل آهي، جيڪا اسپرنگ سيڪيورٽي جي لاڳو ٿيڻ کان پوءِ وڌيڪ پيچيده ٿي ويندي.
@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";
}
}
اسان لاگ ان صفحي لاءِ ڪنٽرولر نه لکنداسين ڇاڪاڻ ته اهو اسپرنگ سيڪيورٽي پاران استعمال ڪيو ويندو آهي. ان جي بدران، اسان کي هڪ خاص ترتيب جي ضرورت پوندي. هميشه وانگر، اچو ته هڪ ٻيو پيڪيج ٺاهيو، ان کي ڪال ڪريو config
، ۽ ڪلاس کي اتي رکو MvcConfig
. جڏهن اسان اسپرنگ سيڪيورٽي ڪنفيگريشن لکندا آهيون، اهو معلوم ٿيندو ته اسان ڪهڙي صفحي ڏانهن اشارو ڪري رهيا آهيون جڏهن اسان "/ لاگ ان" استعمال ڪندا آهيون.
@Configuration
public class MvcConfig implements WebMvcConfigurer
{
public void addViewControllers(ViewControllerRegistry registry)
{
registry.addViewController("/login").setViewName("login");
registry.setOrder(Ordered.HIGHEST_PRECEDENCE);
}
}
صفحا
مان صفحا ٺاهڻ لاءِ Mustache ٽيمپليٽ انجڻ استعمال ڪريان ٿو . توهان هڪ ٻئي کي لاڳو ڪري سگهو ٿا، اهو مسئلو ناهي. ميٽا معلومات لاءِ هڪ meta.mustache فائل ٺاهي وئي آهي جيڪا سڀني صفحن تي استعمال ٿئي ٿي. ان ۾ اسان جي پروجيڪٽ جي صفحن کي خوبصورت ڏسڻ لاءِ بوٽ اسٽريپ پڻ شامل آهي. صفحا ٺاهيا ويندا آهن "src/main/resources/templates" ڊاريڪٽري ۾. فائلن کي ايڪسٽينشن مُڇن آھي. آرٽيڪل ۾ سڌو HTML ڪوڊ رکڻ سان اهو تمام وڏو ٿيندو، تنهنڪري هتي هڪ لنڪ آهي ٽيمپليٽ فولڊر جي پروجيڪٽ جي GitHub مخزن ۾ .ڪلاسيڪل لاگ ان لاءِ اسپرنگ سيڪيورٽي کي ترتيب ڏيڻ
اسپرنگ سيڪيورٽي اسان کي ايپليڪيشن ۽ ان جي وسيلن کي غير مجاز رسائي کان بچائڻ ۾ مدد ڪري ٿي.SecurityConfig
اسان ورثي ۾ ورثي واري طبقي ۾ هڪ جامع ڪم ڪندڙ ترتيب ٺاهينداسين WebSecurityConfigurerAdapter
، جنهن کي اسان پيڪيج ۾ رکنداسين config
. اچو ته ان کي @EnableWebSecurity تشريح سان نشان لڳايو، جيڪو بهار جي سيڪيورٽي سپورٽ کي فعال ڪندو، ۽ @Configuration تشريح، جنهن مان ظاهر ٿئي ٿو ته هي ڪلاس ڪجهه ترتيبن تي مشتمل آهي. نوٽ: خود بخود ترتيب ڏنل pom.xml ۾ اسپرنگ بوٽ جي پريننٽ جزو 2.1.4.RELEASE جو ورجن موجود آهي، جنهن سيڪيورٽي کي قائم ڪيل طريقي سان لاڳو ٿيڻ کان روڪيو. پروجيڪٽ ۾ تڪرار کان بچڻ لاء، اهو نسخو 2.0.1.RELEASE ۾ تبديل ڪرڻ جي سفارش ڪئي وئي آهي.
بنيادي ٺاھ جوڙ SecurityConfig
اسان جي تشڪيل ڪرڻ جي قابل ٿي ويندي:-
انڪريپٽ پاسورڊ استعمال ڪندي
BCryptPasswordEncoder
:@Autowired private PasswordEncoder passwordEncoder; @Bean PasswordEncoder passwordEncoder() { PasswordEncoder passwordEncoder = new BCryptPasswordEncoder(); return passwordEncoder; }
-
خاص طور تي لکيل تصديق ڪندڙ مهيا ڪندڙ استعمال ڪندي لاگ ان ڪريو:
@Autowired private AuthProvider authProvider; @Override protected void configure(AuthenticationManagerBuilder auth) { auth.authenticationProvider(authProvider); }
-
گمنام صارفين کي هوم پيج، رجسٽريشن ۽ لاگ ان صفحن تائين رسائي جي اجازت ڏيو. ٻين سڀني درخواستن کي لازمي طور تي لاگ ان ٿيل استعمال ڪندڙن طرفان ڪيو وڃي. اچو ته اڳ ۾ بيان ڪيل "/ لاگ ان" کي لاگ ان صفحي جي طور تي تفويض ڪريو. جيڪڏهن لاگ ان ڪامياب آهي، صارف کي نوٽس جي فهرست سان هڪ صفحي تي ورتو ويندو؛ جيڪڏهن ڪو غلطي آهي، صارف لاگ ان صفحي تي رهندو. ڪامياب نڪرڻ تي، صارف کي مکيه صفحي تي ورتو ويندو.
@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
، جهڙوڪ بلٽ ان پليپشن، پر پڻ صارف جو نالو، گوگل کاتي جو نالو ۽ گوگل اڪائونٽ اي ميل. آخري ٻه طريقا اسان لاءِ ڪارآمد هوندا جڏهن لاگ ان کي 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
!
اچو ته ڪنٽرولر کي بهتر بڻايون
اسان بهار جي سيڪيورٽي کي ترتيب ڏنو آهي. ھاڻي اھو وقت آھي توھان جي نوٽس ڪنٽرولر ۾ ھن جو فائدو وٺو. هاڻي هر ميپنگ هڪ اضافي پرنسپل پيٽرولر کي قبول ڪندي، جنهن جي ذريعي اهو صارف کي ڳولڻ جي ڪوشش ڪندو. مان ڪلاس کي سڌو ڇو نه ٿو داخل ڪري سگهان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 ترتيب ڏيڻ گوگل کي استعمال ڪندي مثال طور اسپرنگ سيڪيورٽي ۾
OAuth2 کي لاڳو ڪرڻ وقت، مون هن سرڪاري سبق تي ڀروسو ڪيو اسپرنگ کان . OAuth2 کي سپورٽ ڪرڻ لاءِ، هيٺين لائبريري کي pom.xml ۾ شامل ڪريو:<dependency>
<groupId>org.springframework.security.oauth.boot</groupId>
<artifactId>spring-security-oauth2-autoconfigure</artifactId>
<version>2.0.0.RELEASE</version>
</dependency>
اچو ته اسان جي اسپرنگ سيڪيورٽي جي ترتيب ۾ ترميم ڪريون SecurityConfig
. پهرين، اچو ته شامل ڪريون @EnableOAuth2Client تشريح. اهو خودڪار طريقي سان ڇڪيندو جيڪو توهان کي سماجي نيٽ ورڪن ذريعي لاگ ان ٿيڻ جي ضرورت آهي.
فلٽر ٺاھ جوڙ ۽ application.properties
اچو ته انجيڪٽ ڪريون OAuth2ClientContext اسان جي حفاظتي ترتيب ۾ استعمال ڪرڻ لاءِ.@Autowired
private OAuth2ClientContext oAuth2ClientContext;
OAuth2ClientContext استعمال ڪيو ويندو آهي جڏهن هڪ فلٽر ٺاهيو جيڪو صارف جي سماجي لاگ ان درخواست جي تصديق ڪري ٿو. فلٽر دستياب آهي مهرباني ڪري @EnableOAuth2Client تشريح. اسان سڀني کي ڪرڻ جي ضرورت آهي ان کي صحيح ترتيب ۾ سڏڻ کان اڳ، مکيه اسپرنگ سيڪيورٽي فلٽر کان اڳ . صرف پوءِ اسان لاگ ان عمل دوران ريڊائريڪٽس کي پڪڙڻ جي قابل ٿي وينداسين 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();
}
تصديق مڪمل ڪرڻ لاءِ، توهان کي وضاحت ڪرڻ جي ضرورت آهي گوگل صارف معلومات جي آخري پوائنٽ:
@Bean
@ConfigurationProperties("google.resource")
public ResourceServerProperties googleResource()
{
return new ResourceServerProperties();
}
گوگل ڪلائوڊ پليٽ فارم ۾ اسان جي ايپليڪيشن کي رجسٽر ڪرڻ کان پوءِ ، اسان 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
گوگل ڪلائوڊ پليٽ فارم سان ايپليڪيشن رجسٽر ڪرڻ جا نمايان
رستو: APIs ۽ خدمتون -> سندون OAuth رسائي جي درخواست ونڊو:- ايپليڪيشن جو نالو: اسپرنگ لاگ ان فارم ۽ OAuth2 سبق
- سپورٽ اي ميل پتو: توهان جو اي ميل
- گوگل API لاءِ اسڪوپ: اي ميل، پروفائل، اوپن ايڊ
- بااختيار ڊومينز: me.org
- ايپليڪيشن جي مکيه صفحي ڏانهن لنڪ: http://me.org:8080
- ايپ جي رازداري پاليسي سان لنڪ: http://me.org:8080
- ايپليڪيشن جي استعمال جي شرطن سان لنڪ: http://me.org:8080
- قسم: ويب ايپليڪيشن
- عنوان: اسپرنگ لاگ ان فارم ۽ OAuth2 سبق
- اجازت ڏنل جاوا اسڪرپٽ ذريعن: http://me.org، http://me.org:8080
- اجازت ڏنل URIs: http://me.org:8080/login, http://me.org:8080/login/google
CustomUserInfoTokenServices
ڇا توھان محسوس ڪيو لفظ ڪسٽم فلٽر فنڪشن جي وضاحت ۾؟ ڪلاسCustomUserInfoTokenServices
. ها، اسان بليڪ جيڪ ۽ ڊيٽابيس ۾ صارف کي محفوظ ڪرڻ جي صلاحيت سان اسان جو پنهنجو ڪلاس ٺاهينداسين! IntelliJ IDEA ۾ Ctrl-N ڪيبورڊ شارٽ ڪٽ استعمال ڪندي، توھان ڳولي سگھوٿا ۽ ڏسي سگھوٿا ته UserInfoTokenServices
ڊفالٽ ڪيئن لاڳو ٿئي ٿو. اچو ته ان جو ڪوڊ ڪاپي ڪري نئين ٺهيل ڪلاس ۾ CustomUserInfoTokenServices
. گهڻو ڪري ان کي بغير تبديل ڪري سگهجي ٿو. افعال جي منطق کي تبديل ڪرڻ کان اڳ، اچو ته شامل ڪريون UserRepo
۽ ڪلاس جي خانگي شعبن جي طور تي PasswordEncoder
. اچو ته انهن لاء سيٽرز ٺاهي. اچو ته شامل ڪريون @Autowired UserRepo userRepo کي SecurityConfig ڪلاس ۾. اسان ڏسون ٿا ته فلٽر ٺاهڻ واري طريقي ۾ غلطي ڏانهن اشارو ڪيئن غائب ٿي وڃي ٿو، ۽ اسان خوش ٿيو. ڇو نه ٿي سگهيو @Autowired سڌو سنئون CustomUserInfoTokenServices تي لاڳو ڪيو وڃي؟ ڇاڪاڻ ته هي طبقو انحصار نه کڻندو، ڇاڪاڻ ته اهو پاڻ کي ڪنهن به بهار جي تشريح سان نشان نه لڳايو ويو آهي، ۽ ان جو تعمير ڪندڙ واضح طور تي ٺاهيو ويندو آهي جڏهن فلٽر جو اعلان ڪيو ويندو آهي. ان جي مطابق، اسپرنگ جي ڊي آئي ميڪانيزم جي باري ۾ ڄاڻ نه آهي. جيڪڏهن اسان @Autowired هن ڪلاس ۾ ڪنهن به شيءِ تي تشريح ڪريون ٿا، اسان کي استعمال ٿيڻ تي NullPointerException حاصل ڪنداسين. پر واضح سيٽرن ذريعي هر شي تمام سٺو ڪم ڪري ٿو. ضروري جزن کي لاڳو ڪرڻ کان پوءِ، دلچسپي جو مکيه اعتراض loadAuthentication فنڪشن بڻجي ويندو آهي، جنهن ۾ Map<String, Object> استعمال ڪندڙ جي معلومات سان گڏ حاصل ڪيو ويندو آهي. اهو هن پروجيڪٽ ۾ هو ته مون هڪ صارف جي بچت کي لاڳو ڪيو جيڪو سوشل نيٽ ورڪ ذريعي ڊيٽابيس ۾ لاگ ان ٿيو. جيئن ته اسان گوگل کاتو استعمال ڪري رهيا آهيون هڪ 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 ۾ مختلف آپشن بيان ڪري سگهو ٿا، ۽ فلٽر اعلان جي طريقي ۾ ساڳئي خدمتن جي مختلف طبقن کي رجسٽر ڪري سگهو ٿا.
@GetMapping("/")
public String index(Principal principal)
{
if(principal != null)
{
return "redirect:/notes";
}
return "index";
}
GO TO FULL VERSION