1. Dependency

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-web</artifactId>
</dependency>

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-security</artifactId>
</dependency>

2. Config

package io.os.mongo.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.crypto.factory.PasswordEncoderFactories;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;

@Configuration
@EnableWebSecurity
public class SecurityConfig {

	@Bean
	PasswordEncoder passwordEncoder(){
		return PasswordEncoderFactories.createDelegatingPasswordEncoder();
	}

    @Bean
    SecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Exception {
        httpSecurity
            .csrf(AbstractHttpConfigurer::disable)
            .authorizeHttpRequests(
                auth -> auth.requestMatchers("/register", "/error").permitAll()
                    .anyRequest().authenticated()
                )
            .httpBasic(Customizer.withDefaults())
            .formLogin(Customizer.withDefaults());
        return httpSecurity.build();
    }

}

3. Domain

package io.os.mongo.domain;

import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.index.Indexed;
import org.springframework.data.mongodb.core.mapping.Document;

@Document("user")
public class AuthUser {

    @Id
    private String id;

    @Indexed
    private String username;
    private String password;
    private boolean active;

    public AuthUser(){}
	public String getId() {
		return id;
	}
	public String getUsername() {
		return username;
	}
	public void setUsername(String username) {
		this.username = username;
	}
	public String getPassword() {
		return password;
	}
	public void setPassword(String password) {
		this.password = password;
	}
	public boolean isActive() {
		return active;
	}
	public void setActive(boolean active) {
		this.active = active;
	}

}

4. Repository

package io.os.mongo.repository;

import org.springframework.data.mongodb.repository.MongoRepository;
import org.springframework.stereotype.Repository;
import io.os.mongo.domain.AuthUser;
import java.util.Optional;

@Repository
public interface AuthUserRepository extends MongoRepository<AuthUser, String> {

    Optional<AuthUser> findByUsername(String username);

}

5. Service

package io.os.mongo.service;

import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import io.os.mongo.domain.AuthUser;
import io.os.mongo.repository.AuthUserRepository;
import java.util.Optional;

@Service
public class AuthUserDetailService implements UserDetailsService {

    private final AuthUserRepository authUserRepository;

    public AuthUserDetailService(AuthUserRepository authUserRepository) {
    	this.authUserRepository = authUserRepository;
    }

    @Override
    public UserDetails loadUserByUsername(String username)
    	throws UsernameNotFoundException {
        Optional<AuthUser> authUser =
        	authUserRepository.findByUsername(username.toLowerCase());

        if (!authUser.isPresent()){
            throw new UsernameNotFoundException("Username not found: " + username);
        }else {
            return User.builder()
	            .username(authUser.get().getUsername())
	            .password(authUser.get().getPassword())
	            .disabled(!authUser.get().isActive())
	            .build();
        }
    }
}

6. Controller

package io.os.mongo.controller;

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import io.os.mongo.domain.AuthUser;
import io.os.mongo.repository.AuthUserRepository;

@RestController
public class UserController {

	private final PasswordEncoder passwordEncoder;
    private final AuthUserRepository authUserRepository;

    public UserController(PasswordEncoder passwordEncoder,
    	AuthUserRepository authUserRepository) {
    	this.passwordEncoder = passwordEncoder;
    	this.authUserRepository = authUserRepository;
    }

    @PostMapping("/register")
    public ResponseEntity<?> registerUser(@RequestBody AuthUser user){
        try {
            if (authUserRepository.findByUsername(user.getUsername()).isPresent()) {
            	return ResponseEntity.status(HttpStatus.CONFLICT).body("Username already ");
            }
            user.setPassword(passwordEncoder.encode(user.getPassword()));
            AuthUser savedUser = authUserRepository.save(user);
            return ResponseEntity.ok(savedUser);
        }catch (Exception e){
            return ResponseEntity.internalServerError().body(e.getMessage());
        }
    }

}

package io.os.mongo.controller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/api/v1")
public class ProtectionestController {

    @GetMapping("/greet")
    public String greeting() {
        return "Hello,World!";
    }

}

7. Entry

package io.os.mongo;

import java.lang.invoke.MethodHandles;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.data.mongodb.repository.config.EnableMongoRepositories;

@SpringBootApplication
@EnableMongoRepositories
public class MongoEntry {

	public static void main(String[] sa) {
		Class<?> cls = MethodHandles.lookup().lookupClass();
		SpringApplication.run(cls, sa);
	}

}

8. Yaml

server:
  port: 8080
spring:
  data:
    mongodb:
      # uri请指定authSrource,authMechanism:认证方式,默认SCRAM-SHA-1
      uri: mongodb://elf:mongo@192.168.0.123:27017/mongo?authSource=admin&authMechanism=SCRAM-SHA-1

9. Post Request

{
    "username": "xiaom",
    "password": "mongo",
    "active": true
}

{
    "id": "65debff7aa11701b9f184517",
    "username": "xiaom",
    "password": "{bcrypt}$2a$10$CUTHsUxi.74nunkwtQEZSeErEmbhT.NMKB/8KlltenpiUlbzJuvdW",
    "active": true
}

{
  "_id": {
    "$oid": "65debff7aa11701b9f184517"
  },
  "username": "xiaom",
  "password": "{bcrypt}$2a$10$CUTHsUxi.74nunkwtQEZSeErEmbhT.NMKB/8KlltenpiUlbzJuvdW",
  "active": true,
  "_class": "io.os.mongo.domain.AuthUser"
}