1. अवलोकन
स्प्रिंग सिक्योरिटी विभिन्न प्रमाणीकरण प्रणाली प्रदान करती है, जैसे डेटाबेस और UserDetailService . के माध्यम से .
एक जेपीए दृढ़ता परत का उपयोग करने के बजाय, हम उदाहरण के लिए, एक मोंगोडीबी भंडार का भी उपयोग करना चाह सकते हैं। इस ट्यूटोरियल में, हम देखेंगे कि स्प्रिंग सिक्योरिटी और MongoDB का उपयोग करके उपयोगकर्ता को कैसे प्रमाणित किया जाए।
2. MongoDB के साथ स्प्रिंग सुरक्षा प्रमाणीकरण
JPA रिपॉजिटरी के उपयोग के समान, हम MongoDB रिपॉजिटरी का उपयोग कर सकते हैं . हालांकि, इसका उपयोग करने के लिए हमें एक अलग कॉन्फ़िगरेशन सेट करने की आवश्यकता है।
2.1. मावेन निर्भरताएं
इस ट्यूटोरियल के लिए, हम एंबेडेड MongoDB का उपयोग करने जा रहे हैं . हालांकि, एक MongoDB उदाहरण और टेस्टकंटेनर उत्पादन वातावरण के लिए वैध विकल्प हो सकते हैं। सबसे पहले, आइए स्प्रिंग-बूट-स्टार्टर-डेटा-मोंगोडब जोड़ें और de.flapdoodle.embed.mongo निर्भरताएँ:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
<dependency>
<groupId>de.flapdoodle.embed</groupId>
<artifactId>de.flapdoodle.embed.mongo</artifactId>
<version>3.3.1</version>
</dependency>
2.2. कॉन्फ़िगरेशन
निर्भरता सेट करने के बाद, हम अपना कॉन्फ़िगरेशन बना सकते हैं:
@Configuration
public class MongoConfig {
private static final String CONNECTION_STRING = "mongodb://%s:%d";
private static final String HOST = "localhost";
@Bean
public MongoTemplate mongoTemplate() throws Exception {
int randomPort = SocketUtils.findAvailableTcpPort();
ImmutableMongodConfig mongoDbConfig = MongodConfig.builder()
.version(Version.Main.PRODUCTION)
.net(new Net(HOST, randomPort, Network.localhostIsIPv6()))
.build();
MongodStarter starter = MongodStarter.getDefaultInstance();
MongodExecutable mongodExecutable = starter.prepare(mongoDbConfig);
mongodExecutable.start();
return new MongoTemplate(MongoClients.create(String.format(CONNECTION_STRING, HOST, randomPort)), "mongo_auth");
}
}
हमें अपने प्रमाणीकरण प्रबंधक . को भी कॉन्फ़िगर करने की आवश्यकता है उदाहरण के लिए, एक HTTP मूल प्रमाणीकरण के साथ:
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled = true, jsr250Enabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
// ...
public SecurityConfig(UserDetailsService userDetailsService) {
this.userDetailsService = userDetailsService;
}
@Bean
public AuthenticationManager customAuthenticationManager() throws Exception {
return authenticationManager();
}
@Bean
public BCryptPasswordEncoder bCryptPasswordEncoder() {
return new BCryptPasswordEncoder();
}
@Override
protected void configure(@Autowired AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService)
.passwordEncoder(bCryptPasswordEncoder());
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf()
.disable()
.authorizeRequests()
.and()
.httpBasic()
.and()
.authorizeRequests()
.anyRequest()
.permitAll()
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}
}
2.3. उपयोगकर्ता डोमेन और रिपोजिटरी
सबसे पहले, आइए हमारे प्रमाणीकरण के लिए भूमिकाओं के साथ एक साधारण उपयोगकर्ता को परिभाषित करें। हम इसे उपयोगकर्ता विवरण लागू करेंगे प्रिंसिपल . के सामान्य तरीकों का पुन:उपयोग करने के लिए इंटरफ़ेस वस्तु:
@Document
public class User implements UserDetails {
private @MongoId ObjectId id;
private String username;
private String password;
private Set<UserRole> userRoles;
// getters and setters
}
अब जब हमारे पास हमारा उपयोगकर्ता है, तो आइए एक साधारण भंडार को परिभाषित करें:
public interface UserRepository extends MongoRepository<User, String> {
@Query("{username:'?0'}")
User findUserByUsername(String username);
}
2.4. प्रमाणीकरण सेवा
आखिरकार, आइए हमारी UserDetailService को लागू करें किसी उपयोगकर्ता को पुनः प्राप्त करने और यह जांचने के लिए कि क्या यह प्रमाणित है :
@Service
public class MongoAuthUserDetailService implements UserDetailsService {
// ...
@Override
public UserDetails loadUserByUsername(String userName) throws UsernameNotFoundException {
com.baeldung.mongoauth.domain.User user = userRepository.findUserByUsername(userName);
Set<GrantedAuthority> grantedAuthorities = new HashSet<>();
user.getAuthorities()
.forEach(role -> {
grantedAuthorities.add(new SimpleGrantedAuthority(role.getRole()
.getName()));
});
return new User(user.getUsername(), user.getPassword(), grantedAuthorities);
}
}
2.5. परीक्षण प्रमाणीकरण
हमारे आवेदन का परीक्षण करने के लिए, आइए एक साधारण नियंत्रक को परिभाषित करें। एक उदाहरण के रूप में, हमने विशिष्ट समापन बिंदुओं के लिए प्रमाणीकरण और प्राधिकरण का परीक्षण करने के लिए दो अलग-अलग भूमिकाएँ परिभाषित की हैं:
@RestController
public class ResourceController {
@RolesAllowed("ROLE_ADMIN")
@GetMapping("/admin")
public String admin() {
return "Hello Admin!";
}
@RolesAllowed({ "ROLE_ADMIN", "ROLE_USER" })
@GetMapping("/user")
public String user() {
return "Hello User!";
}
}
यह जाँचने के लिए कि हमारा प्रमाणीकरण काम करता है या नहीं, इसे स्प्रिंग बूट टेस्ट में पूरा करते हैं। जैसा कि हम देख सकते हैं, हम किसी ऐसे व्यक्ति के लिए 401 कोड की अपेक्षा कर रहे हैं जो अमान्य क्रेडेंशियल प्रदान करता है या जो हमारे सिस्टम में मौजूद नहीं है :
class MongoAuthApplicationTest {
// set up
@Test
void givenUserCredentials_whenInvokeUserAuthorizedEndPoint_thenReturn200() throws Exception {
mvc.perform(get("/user").with(httpBasic(USER_NAME, PASSWORD)))
.andExpect(status().isOk());
}
@Test
void givenUserNotExists_whenInvokeEndPoint_thenReturn401() throws Exception {
mvc.perform(get("/user").with(httpBasic("not_existing_user", "password")))
.andExpect(status().isUnauthorized());
}
@Test
void givenUserExistsAndWrongPassword_whenInvokeEndPoint_thenReturn401() throws Exception {
mvc.perform(get("/user").with(httpBasic(USER_NAME, "wrong_password")))
.andExpect(status().isUnauthorized());
}
@Test
void givenUserCredentials_whenInvokeAdminAuthorizedEndPoint_thenReturn403() throws Exception {
mvc.perform(get("/admin").with(httpBasic(USER_NAME, PASSWORD)))
.andExpect(status().isForbidden());
}
@Test
void givenAdminCredentials_whenInvokeAdminAuthorizedEndPoint_thenReturn200() throws Exception {
mvc.perform(get("/admin").with(httpBasic(ADMIN_NAME, PASSWORD)))
.andExpect(status().isOk());
mvc.perform(get("/user").with(httpBasic(ADMIN_NAME, PASSWORD)))
.andExpect(status().isOk());
}
}