知識庫 / NoSQL RSS 訂閱

Spring Security 與 MongoDB 認證

NoSQL,Spring Security
HongKong
10
12:16 PM · Dec 06 ,2025

1. 概述

Spring Security 提供多種身份驗證系統,例如通過數據庫和 UserDetailService

與其使用 JPA 持久層,我們也可以使用,例如 MongoDB 倉庫。 在本教程中,我們將看到如何使用 Spring Security 和 MongoDB 認證用户。

2. 使用 Spring Security 與 MongoDB 進行身份驗證

類似於使用 JPA 倉庫,我們可以使用 MongoDB 倉庫。但是,為了使用它,我們需要配置不同的設置。

2.1. Maven 依賴

為了本教程,我們將使用嵌入式 MongoDB。 但是,MongoDB 實例和 Testcontainer 也可以作為生產環境的有效選項。首先,讓我們添加 spring-boot-starter-data-mongodbde.flapdoodle.embed.mongo.spring30x 依賴項:

<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.spring30x</artifactId>
    <version>4.11.0</version>
</dependency>

2.2. 配置

一旦我們設置了依賴項,就需要使用諸如 HTTP 基本身份驗證之類的配置來設置我們的 AuthenticationManager

@Configuration
@EnableWebSecurity
@EnableMethodSecurity(securedEnabled = true, jsr250Enabled = true)
public class SecurityConfig {

    //....

    public SecurityConfig(UserDetailsService userDetailsService) {
        this.userDetailsService = userDetailsService;
    }

    @Bean
    public AuthenticationManager customAuthenticationManager(HttpSecurity http) throws Exception {
        AuthenticationManagerBuilder authenticationManagerBuilder = http.getSharedObject(AuthenticationManagerBuilder.class);
        authenticationManagerBuilder.userDetailsService(userDetailsService)
            .passwordEncoder(bCryptPasswordEncoder());
        return authenticationManagerBuilder.build();
    }

    @Bean
    public BCryptPasswordEncoder bCryptPasswordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http.csrf(AbstractHttpConfigurer::disable)
            .authorizeHttpRequests(Customizer.withDefaults())
            .httpBasic(Customizer.withDefaults())
            .authorizeHttpRequests(authorizationManagerRequestMatcherRegistry -> authorizationManagerRequestMatcherRegistry.anyRequest().permitAll())
            .sessionManagement(httpSecuritySessionManagementConfigurer -> httpSecuritySessionManagementConfigurer.sessionCreationPolicy(SessionCreationPolicy.STATELESS));
        return http.build();
    }

}

2.3. 用户域和存儲庫

首先,讓我們定義一個具有角色的簡單用户,用於我們的身份驗證。它將實現 <em>UserDetails</em> 接口,以重用 <em>Principal</em> 對象中的常用方法。

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

}

讓我們用一個 Spring Boot 測試來驗證我們的身份驗證是否正常工作。正如你所看到的,我們期望當用户提供無效憑據或不在我們的系統中存在時,返回一個 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());
    }
}

3. 結論

在本文中,我們探討了使用 Spring Security 進行 MongoDB 身份驗證。

我們已經瞭解瞭如何創建可工作的配置以及實現自定義 UserDetailService。我們還了解了如何模擬 MVC 上下文並測試身份驗證和授權。

user avatar
0 位用戶收藏了這個故事!
收藏

發佈 評論

Some HTML is okay.