MongoDB
 sql >> Teknologi Basis Data >  >> NoSQL >> MongoDB

Otentikasi Dengan Keamanan Musim Semi dan MongoDB

Sangat sulit untuk menjadi kenyataan, visibilitas waktu-nyata ke dalam autentikasi yang sedang berjalan mengalir.

Bagian dari proses dapat sepenuhnya disembunyikan dari kami; jika proses otorisasi lengkap memerlukan pengalihan dari server produksi OAuth jarak jauh, maka setiap upaya debug harus melalui server produksi.

Secara praktis tidak mungkin untuk men-debug ini secara lokal. Tidak ada cara untuk mereproduksi keadaan yang tepat dan tidak ada cara untuk memeriksa apa yang sebenarnya terjadi di bawah tenda. Tidak ideal.

Mengetahui jenis tantangan ini, kami membuat Lightrun - alat debugging produksi waktu nyata - untuk memungkinkan Anda memahami alur rumit dengan informasi tingkat kode. Tambahkan log, ambil snapshot (titik henti sementara virtual), dan metrik instrumen tanpa debugger jarak jauh, tanpa menghentikan layanan yang sedang berjalan, dan yang paling penting - secara real-time dan tanpa efek samping .

Pelajari lebih lanjut dengan tutorial 5 menit ini fokus pada debugging skenario semacam ini menggunakan Lightrun:

>> Debugging Otentikasi dan Otorisasi Menggunakan Lightrun

1. Ikhtisar

Spring Security menawarkan sistem otentikasi yang berbeda, seperti melalui database dan UserDetailService .

Daripada menggunakan lapisan persistensi JPA, kami mungkin juga ingin menggunakan, misalnya, repositori MongoDB. Dalam tutorial ini, kita akan melihat cara mengautentikasi pengguna menggunakan Spring Security dan MongoDB.

2. Otentikasi Keamanan Musim Semi dengan MongoDB

Mirip dengan menggunakan repositori JPA, kita dapat menggunakan repositori MongoDB . Namun, kita perlu mengatur konfigurasi yang berbeda untuk menggunakannya.

2.1. Ketergantungan Maven

Untuk tutorial ini, kita akan menggunakan Embedded MongoDB . Namun, instance MongoDB dan Testcontainer bisa menjadi pilihan yang valid untuk lingkungan produksi. Pertama, mari tambahkan spring-boot-starter-data-mongodb dan de.flapdoodle.embed.mongo dependensi:

<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. Konfigurasi

Setelah kita mengatur dependensi, kita dapat membuat konfigurasi kita:

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

Kita juga perlu mengonfigurasi AuthenticationManager dengan, misalnya, autentikasi dasar 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. Domain Pengguna dan Repositori

Pertama, mari kita definisikan pengguna sederhana dengan peran untuk otentikasi kita. Kami akan memintanya mengimplementasikan UserDetails antarmuka untuk menggunakan kembali metode umum dari Principal objek:

@Document
public class User implements UserDetails {
    private @MongoId ObjectId id;
    private String username;
    private String password;
    private Set<UserRole> userRoles;
    // getters and setters
}

Sekarang setelah kita memiliki pengguna, mari kita definisikan repositori sederhana:

public interface UserRepository extends MongoRepository<User, String> {

    @Query("{username:'?0'}")
    User findUserByUsername(String username);
}

2.4. Layanan Otentikasi

Terakhir, mari implementasikan UserDetailService our kami untuk mengambil pengguna dan memeriksa apakah itu diautentikasi :

@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. Uji Otentikasi

Untuk menguji aplikasi kita, mari kita definisikan pengontrol sederhana. Sebagai contoh, kami telah menetapkan dua peran berbeda untuk menguji autentikasi dan otorisasi untuk titik akhir tertentu:

@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!";
    }

}

Mari kita selesaikan semuanya dalam Tes Boot Musim Semi untuk memeriksa apakah otentikasi kita berfungsi. Seperti yang dapat kita lihat, kami mengharapkan kode 401 untuk seseorang yang memberikan kredensial yang tidak valid atau yang tidak ada di sistem kami :

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

  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Penggunaan data buffer tahap sortir overflow melebihi batas internal

  2. Mengintegrasikan ClusterControl dengan SNMP - Bukti Konsep:Bagian Satu

  3. Kasus untuk Indeks Hash MongoDB

  4. Apa gunanya file mongo.lock?

  5. Ekspor Koleksi MongoDB ke File CSV