MongoDB
 sql >> Cơ Sở Dữ Liệu >  >> NoSQL >> MongoDB

Xác thực với Spring Security và MongoDB

Thật khó để có được khả năng hiển thị trong thời gian thực đối với một xác thực đang chạy dòng chảy.

Chúng tôi có thể hoàn toàn ẩn các phần của quy trình; nếu quy trình ủy quyền hoàn chỉnh yêu cầu chuyển hướng từ máy chủ sản xuất OAuth từ xa, thì mọi nỗ lực gỡ lỗi phải thông qua máy chủ sản xuất.

Thực tế không khả thi khi gỡ lỗi cục bộ này. Không có cách nào để tạo lại trạng thái chính xác và không có cách nào để kiểm tra những gì đang thực sự xảy ra. Không lý tưởng.

Biết được những thách thức này, chúng tôi đã xây dựng Lightrun - một công cụ gỡ lỗi sản xuất theo thời gian thực - để cho phép bạn hiểu các luồng phức tạp với thông tin cấp mã. Thêm nhật ký, chụp nhanh (điểm ngắt ảo) và số liệu công cụ mà không cần trình gỡ lỗi từ xa, mà không dừng dịch vụ đang chạy và quan trọng nhất - trong thời gian thực và không có tác dụng phụ .

Tìm hiểu thêm với hướng dẫn 5 phút này tập trung vào việc gỡ lỗi các loại tình huống này bằng Lightrun:

>> Gỡ lỗi xác thực và ủy quyền bằng Lightrun

1. Tổng quan

Spring Security cung cấp các hệ thống xác thực khác nhau, chẳng hạn như thông qua cơ sở dữ liệu và UserDetailService .

Thay vì sử dụng lớp liên tục JPA, chúng tôi cũng có thể muốn sử dụng, ví dụ:kho lưu trữ MongoDB. Trong hướng dẫn này, chúng ta sẽ xem cách xác thực người dùng bằng Spring Security và MongoDB.

2. Xác thực bảo mật mùa xuân với MongoDB

Tương tự như sử dụng kho lưu trữ JPA, chúng tôi có thể sử dụng kho lưu trữ MongoDB . Tuy nhiên, chúng tôi cần đặt một cấu hình khác để sử dụng nó.

2.1. Sự phụ thuộc của Maven

Đối với hướng dẫn này, chúng tôi sẽ sử dụng MongoDB được nhúng . Tuy nhiên, một phiên bản MongoDB và Testcontainer có thể là các tùy chọn hợp lệ cho môi trường sản xuất. Trước tiên, hãy thêm spring-boot-starter-data-mongodb de.flapdoodle.embed.mongo phụ thuộc:

<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. Cấu hình

Khi chúng tôi đặt các phần phụ thuộc, chúng tôi có thể tạo cấu hình của mình:

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

Chúng tôi cũng cần định cấu hình AuthenticationManager chẳng hạn với xác thực cơ bản 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. Tên miền và kho lưu trữ của người dùng

Đầu tiên, hãy xác định một người dùng đơn giản với các vai trò để xác thực của chúng tôi. Chúng tôi sẽ yêu cầu nó triển khai Chi tiết người dùng giao diện để sử dụng lại các phương thức commons của một Hiệu trưởng đối tượng:

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

Bây giờ chúng ta có người dùng của mình, hãy xác định một kho lưu trữ đơn giản:

public interface UserRepository extends MongoRepository<User, String> {

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

2.4. Dịch vụ xác thực

Cuối cùng, hãy triển khai UserDetailService của chúng tôi để truy xuất người dùng và kiểm tra xem người dùng đó đã được xác thực chưa :

@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. Kiểm tra xác thực

Để kiểm tra ứng dụng của chúng ta, hãy xác định một bộ điều khiển đơn giản. Ví dụ:chúng tôi đã xác định hai vai trò khác nhau để kiểm tra xác thực và ủy quyền cho các điểm cuối cụ thể:

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

}

Hãy kết thúc tất cả trong Kiểm tra khởi động mùa xuân để kiểm tra xem xác thực của chúng tôi có hoạt động hay không. Như chúng ta có thể thấy, chúng tôi đang mong đợi một mã 401 cho ai đó cung cấp thông tin đăng nhập không hợp lệ hoặc người không tồn tại trong hệ thống của chúng tôi :

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. heroku mongohq và mongoid Mongo ::ConnectionFailure

  2. Làm thế nào để dừng máy chủ mongodb trên Windows?

  3. Sử dụng AngularJs và MongoDB / Mongoose

  4. Lỗi Node.js Lỗi:Không thể tìm thấy mô-đun 'mongoose'

  5. MongoDB giải phóng nhiều mảng