AlgoGalaxy

AlgoGalaxy

University
CodeRush
Jobs
Tools
Insights
Explore
Personalize
Node.jsSpring SecurityHibernateNestJSJPAExpress.jsGraphQLREST APIsAuthenticationASPDjangoIndexingPostgreSQLSQLViewsJoinsStored ProceduresT-SQLMongoDBMySQL

Spring Boot Security: Password Storage

In this Spring Boot lesson, we will study Password Storage through small executable cases. First we will make the normal result clear; then inspect data flow, ownership, failure behavior, and the caller contract before adding framework or infrastructure complexity.

Professional code is readable under change. A future developer should be able to identify which input is trusted, who may update state, where I/O happens, and how an expected error reaches a caller without reconstructing the whole application.

What You Will Build

20 focused Spring Boot examples for Password Storage. Each has a visible result, an explicit contract, and a next change to test so the lesson becomes reusable knowledge rather than passive reading.

Example 1: Bootstrap one application

Let’s isolate one Spring Boot Security rule together. Run it, trace the inputs and output, then change one boundary value before reusing the pattern. Small observable programs turn syntax into a reliable engineering habit.

Keep contracts explicit: validate data before use, make ownership and mutation visible, and return a named result or failure a caller can test. Static types and a successful build help, but runtime boundaries still need intentional checks.

Spring Boot

@SpringBootApplication
public class CatalogApplication {
    public static void main(String[] args) {
        SpringApplication.run(CatalogApplication.class, args);
    }
}

Expected Result

The CatalogApplication context starts and owns the HTTP server

Try next: make the nearest empty, invalid, missing, or boundary case observable instead of leaving behavior to an unchecked assumption.

Example 2: Declare focused dependencies

Let’s isolate one Spring Boot Security rule together. Run it, trace the inputs and output, then change one boundary value before reusing the pattern. Small observable programs turn syntax into a reliable engineering habit.

Keep contracts explicit: validate data before use, make ownership and mutation visible, and return a named result or failure a caller can test. Static types and a successful build help, but runtime boundaries still need intentional checks.

Spring Boot

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

Expected Result

The build includes Spring MVC and an embedded web server

Try next: make the nearest empty, invalid, missing, or boundary case observable instead of leaving behavior to an unchecked assumption.

Example 3: Return a small REST representation

Let’s isolate one Spring Boot Security rule together. Run it, trace the inputs and output, then change one boundary value before reusing the pattern. Small observable programs turn syntax into a reliable engineering habit.

Keep contracts explicit: validate data before use, make ownership and mutation visible, and return a named result or failure a caller can test. Static types and a successful build help, but runtime boundaries still need intentional checks.

Spring Boot

@RestController
@RequestMapping("/api/topics")
class TopicController {
    @GetMapping("/{id}")
    TopicResponse find(@PathVariable UUID id) {
        return new TopicResponse(id, "Spring Boot");
    }
}

record TopicResponse(UUID id, String title) {}

Expected Result

200 OK with a JSON id and title

Try next: make the nearest empty, invalid, missing, or boundary case observable instead of leaving behavior to an unchecked assumption.

Example 4: Keep API DTOs separate from entities

Let’s isolate one Spring Boot Security rule together. Run it, trace the inputs and output, then change one boundary value before reusing the pattern. Small observable programs turn syntax into a reliable engineering habit.

Keep contracts explicit: validate data before use, make ownership and mutation visible, and return a named result or failure a caller can test. Static types and a successful build help, but runtime boundaries still need intentional checks.

Spring Boot

record CreateTopicRequest(
    @NotBlank String title,
    @Size(max = 240) String summary
) {}

record TopicResponse(UUID id, String title) {}

Expected Result

The API accepts only the fields it intentionally exposes

Try next: make the nearest empty, invalid, missing, or boundary case observable instead of leaving behavior to an unchecked assumption.

Example 5: Use constructor injection

Let’s isolate one Spring Boot Security rule together. Run it, trace the inputs and output, then change one boundary value before reusing the pattern. Small observable programs turn syntax into a reliable engineering habit.

Keep contracts explicit: validate data before use, make ownership and mutation visible, and return a named result or failure a caller can test. Static types and a successful build help, but runtime boundaries still need intentional checks.

Spring Boot

@Service
class TopicService {
    private final TopicRepository repository;

    TopicService(TopicRepository repository) {
        this.repository = repository;
    }
}

Expected Result

TopicService receives its repository explicitly and is easy to test

Try next: make the nearest empty, invalid, missing, or boundary case observable instead of leaving behavior to an unchecked assumption.

Example 6: Model a persistent aggregate

Let’s isolate one Spring Boot Security rule together. Run it, trace the inputs and output, then change one boundary value before reusing the pattern. Small observable programs turn syntax into a reliable engineering habit.

Keep contracts explicit: validate data before use, make ownership and mutation visible, and return a named result or failure a caller can test. Static types and a successful build help, but runtime boundaries still need intentional checks.

Spring Boot

@Entity
class Topic {
    @Id
    @GeneratedValue
    UUID id;

    @Column(nullable = false, length = 120)
    String title;
}

Expected Result

JPA maps Topic to a table with a generated id and required title

Try next: make the nearest empty, invalid, missing, or boundary case observable instead of leaving behavior to an unchecked assumption.

Example 7: Use a repository query

Let’s isolate one Spring Boot Security rule together. Run it, trace the inputs and output, then change one boundary value before reusing the pattern. Small observable programs turn syntax into a reliable engineering habit.

Keep contracts explicit: validate data before use, make ownership and mutation visible, and return a named result or failure a caller can test. Static types and a successful build help, but runtime boundaries still need intentional checks.

Spring Boot

interface TopicRepository extends JpaRepository<Topic, UUID> {
    Page<Topic> findByTitleContainingIgnoreCase(
        String text,
        Pageable pageable
    );
}

Expected Result

A paged title search is available without controller SQL

Try next: make the nearest empty, invalid, missing, or boundary case observable instead of leaving behavior to an unchecked assumption.

Example 8: Keep a write inside one transaction

Let’s isolate one Spring Boot Security rule together. Run it, trace the inputs and output, then change one boundary value before reusing the pattern. Small observable programs turn syntax into a reliable engineering habit.

Keep contracts explicit: validate data before use, make ownership and mutation visible, and return a named result or failure a caller can test. Static types and a successful build help, but runtime boundaries still need intentional checks.

Spring Boot

@Transactional
public TopicResponse rename(UUID id, String title) {
    Topic topic = repository.findById(id)
        .orElseThrow(() -> new TopicNotFound(id));
    topic.title = title;
    return new TopicResponse(topic.id, topic.title);
}

Expected Result

The read, validation, update, and commit succeed or fail together

Try next: make the nearest empty, invalid, missing, or boundary case observable instead of leaving behavior to an unchecked assumption.

Example 9: Externalize runtime configuration

Let’s isolate one Spring Boot Security rule together. Run it, trace the inputs and output, then change one boundary value before reusing the pattern. Small observable programs turn syntax into a reliable engineering habit.

Keep contracts explicit: validate data before use, make ownership and mutation visible, and return a named result or failure a caller can test. Static types and a successful build help, but runtime boundaries still need intentional checks.

Spring Boot

server:
  port: 8080
app:
  catalog:
    page-size: 25
spring:
  datasource:
    url: ${DATABASE_URL}

Expected Result

Port, page size, and datasource URL come from configuration

Try next: make the nearest empty, invalid, missing, or boundary case observable instead of leaving behavior to an unchecked assumption.

Example 10: Bind typed configuration

Let’s isolate one Spring Boot Security rule together. Run it, trace the inputs and output, then change one boundary value before reusing the pattern. Small observable programs turn syntax into a reliable engineering habit.

Keep contracts explicit: validate data before use, make ownership and mutation visible, and return a named result or failure a caller can test. Static types and a successful build help, but runtime boundaries still need intentional checks.

Spring Boot

@ConfigurationProperties(prefix = "app.catalog")
@Validated
public record CatalogProperties(
    @Min(1) int pageSize
) {}

Expected Result

Invalid page-size configuration fails during startup

Try next: make the nearest empty, invalid, missing, or boundary case observable instead of leaving behavior to an unchecked assumption.

Example 11: Validate a request at the boundary

Let’s isolate one Spring Boot Security rule together. Run it, trace the inputs and output, then change one boundary value before reusing the pattern. Small observable programs turn syntax into a reliable engineering habit.

Keep contracts explicit: validate data before use, make ownership and mutation visible, and return a named result or failure a caller can test. Static types and a successful build help, but runtime boundaries still need intentional checks.

Spring Boot

@PostMapping
ResponseEntity<TopicResponse> create(
    @Valid @RequestBody CreateTopicRequest request
) {
    return ResponseEntity.status(HttpStatus.CREATED)
        .body(service.create(request));
}

Expected Result

Invalid input receives a deliberate 400 response before mutation

Try next: make the nearest empty, invalid, missing, or boundary case observable instead of leaving behavior to an unchecked assumption.

Example 12: Return one intentional API error shape

Let’s isolate one Spring Boot Security rule together. Run it, trace the inputs and output, then change one boundary value before reusing the pattern. Small observable programs turn syntax into a reliable engineering habit.

Keep contracts explicit: validate data before use, make ownership and mutation visible, and return a named result or failure a caller can test. Static types and a successful build help, but runtime boundaries still need intentional checks.

Spring Boot

@RestControllerAdvice
class ApiErrors {
    @ExceptionHandler(TopicNotFound.class)
    ResponseEntity<ApiError> notFound(TopicNotFound error) {
        return ResponseEntity.status(HttpStatus.NOT_FOUND)
            .body(new ApiError("TOPIC_NOT_FOUND", error.getMessage()));
    }
}

record ApiError(String code, String message) {}

Expected Result

A missing topic becomes a stable 404 API response

Try next: make the nearest empty, invalid, missing, or boundary case observable instead of leaving behavior to an unchecked assumption.

Example 13: Protect routes with a security filter chain

Let’s isolate one Spring Boot Security rule together. Run it, trace the inputs and output, then change one boundary value before reusing the pattern. Small observable programs turn syntax into a reliable engineering habit.

Keep contracts explicit: validate data before use, make ownership and mutation visible, and return a named result or failure a caller can test. Static types and a successful build help, but runtime boundaries still need intentional checks.

Spring Boot

@Bean
SecurityFilterChain security(HttpSecurity http) throws Exception {
    return http
        .csrf(csrf -> csrf.disable())
        .authorizeHttpRequests(auth -> auth
            .requestMatchers("/actuator/health").permitAll()
            .anyRequest().authenticated()
        )
        .httpBasic(Customizer.withDefaults())
        .build();
}

Expected Result

Health is public; all remaining routes require authentication

Try next: make the nearest empty, invalid, missing, or boundary case observable instead of leaving behavior to an unchecked assumption.

Example 14: Hash passwords instead of storing them

Let’s isolate one Spring Boot Security rule together. Run it, trace the inputs and output, then change one boundary value before reusing the pattern. Small observable programs turn syntax into a reliable engineering habit.

Keep contracts explicit: validate data before use, make ownership and mutation visible, and return a named result or failure a caller can test. Static types and a successful build help, but runtime boundaries still need intentional checks.

Spring Boot

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

String stored = passwordEncoder().encode("replace-at-registration");

Expected Result

The stored value is an algorithm-tagged password hash

Try next: make the nearest empty, invalid, missing, or boundary case observable instead of leaving behavior to an unchecked assumption.

Example 15: Authorize close to the protected action

Let’s isolate one Spring Boot Security rule together. Run it, trace the inputs and output, then change one boundary value before reusing the pattern. Small observable programs turn syntax into a reliable engineering habit.

Keep contracts explicit: validate data before use, make ownership and mutation visible, and return a named result or failure a caller can test. Static types and a successful build help, but runtime boundaries still need intentional checks.

Spring Boot

@PreAuthorize("hasRole('EDITOR') or @topicAccess.owns(#id, authentication)")
public TopicResponse update(UUID id, UpdateTopicRequest request) {
    return service.update(id, request);
}

Expected Result

Only an editor or the resource owner may update the topic

Try next: make the nearest empty, invalid, missing, or boundary case observable instead of leaving behavior to an unchecked assumption.

Example 16: Test a service rule quickly

Let’s isolate one Spring Boot Security rule together. Run it, trace the inputs and output, then change one boundary value before reusing the pattern. Small observable programs turn syntax into a reliable engineering habit.

Keep contracts explicit: validate data before use, make ownership and mutation visible, and return a named result or failure a caller can test. Static types and a successful build help, but runtime boundaries still need intentional checks.

Spring Boot

@ExtendWith(MockitoExtension.class)
class TopicServiceTest {
    @Mock TopicRepository repository;

    @Test
    void rejectsMissingTopic() {
        when(repository.findById(any())).thenReturn(Optional.empty());
        assertThrows(TopicNotFound.class, () -> service.rename(UUID.randomUUID(), "New"));
    }
}

Expected Result

The domain failure is verified without starting Spring

Try next: make the nearest empty, invalid, missing, or boundary case observable instead of leaving behavior to an unchecked assumption.

Example 17: Test the HTTP contract

Let’s isolate one Spring Boot Security rule together. Run it, trace the inputs and output, then change one boundary value before reusing the pattern. Small observable programs turn syntax into a reliable engineering habit.

Keep contracts explicit: validate data before use, make ownership and mutation visible, and return a named result or failure a caller can test. Static types and a successful build help, but runtime boundaries still need intentional checks.

Spring Boot

@WebMvcTest(TopicController.class)
class TopicControllerTest {
    @Autowired MockMvc mvc;

    @Test
    void returnsTopic() throws Exception {
        mvc.perform(get("/api/topics/{id}", UUID.randomUUID()))
            .andExpect(status().isOk());
    }
}

Expected Result

The controller contract returns HTTP 200 for a valid route

Try next: make the nearest empty, invalid, missing, or boundary case observable instead of leaving behavior to an unchecked assumption.

Example 18: Call a remote service through an explicit client

Let’s isolate one Spring Boot Security rule together. Run it, trace the inputs and output, then change one boundary value before reusing the pattern. Small observable programs turn syntax into a reliable engineering habit.

Keep contracts explicit: validate data before use, make ownership and mutation visible, and return a named result or failure a caller can test. Static types and a successful build help, but runtime boundaries still need intentional checks.

Spring Boot

@FeignClient(name = "catalog-search", path = "/api/search")
interface SearchClient {
    @GetMapping
    SearchResponse find(@RequestParam String query);
}

record SearchResponse(List<String> ids) {}

Expected Result

The catalog service has a typed boundary to catalog-search

Try next: make the nearest empty, invalid, missing, or boundary case observable instead of leaving behavior to an unchecked assumption.

Example 19: Contain remote failure

Let’s isolate one Spring Boot Security rule together. Run it, trace the inputs and output, then change one boundary value before reusing the pattern. Small observable programs turn syntax into a reliable engineering habit.

Keep contracts explicit: validate data before use, make ownership and mutation visible, and return a named result or failure a caller can test. Static types and a successful build help, but runtime boundaries still need intentional checks.

Spring Boot

@CircuitBreaker(name = "search", fallbackMethod = "emptySearch")
public SearchResponse search(String query) {
    return searchClient.find(query);
}

SearchResponse emptySearch(String query, Throwable error) {
    return new SearchResponse(List.of());
}

Expected Result

A failed dependency produces an intentional empty fallback result

Try next: make the nearest empty, invalid, missing, or boundary case observable instead of leaving behavior to an unchecked assumption.

Example 20: Expose operational health without secrets

Let’s isolate one Spring Boot Security rule together. Run it, trace the inputs and output, then change one boundary value before reusing the pattern. Small observable programs turn syntax into a reliable engineering habit.

Keep contracts explicit: validate data before use, make ownership and mutation visible, and return a named result or failure a caller can test. Static types and a successful build help, but runtime boundaries still need intentional checks.

Spring Boot

management:
  endpoints:
    web:
      exposure:
        include: health,info,metrics
  endpoint:
    health:
      probes:
        enabled: true

Expected Result

Health, info, and metrics are available while sensitive endpoints stay closed

Try next: make the nearest empty, invalid, missing, or boundary case observable instead of leaving behavior to an unchecked assumption.

Design Review and Worked Trace

Review Spring Boot Security: Password Storage as a full trace: input, validation, calculation or side effect, output, and cleanup. State the normal result, then state the boundary behavior. If either is hard to explain, split the work into a smaller function with a narrower contract.

Keep secret values and privileged decisions outside display code. Authentication establishes an identity; authorization decides what that identity may do. Check both close to protected operations, and use intentional failure responses rather than leaking internal details or crashing generically.

  • Run the normal input and record the exact result.
  • Test an empty, malformed, or boundary input deliberately.
  • Keep state, ownership, and side effects visible to the caller.
  • Return a result or named failure that can be tested.
  • Never log credentials, tokens, or sensitive input.

This discipline makes Spring Boot code easier to review, safer to change, and more useful in production than a collection of untested syntax fragments.

Common Mistakes

  • Skipping input validation because a local example happened to work.
  • Hiding mutation, ownership, or failure behavior inside a convenient shortcut.
  • Using a client-side display rule as the only protection for sensitive work.
  • Copying code without changing an input to prove its contract.
logo of AlgoGalaxy

Newsletter

Subscribe to our newsletter for weekly updates and promotions.

AlgoGalaxy University

University HomeTechnology LearningCoding ProblemsLearning ProgressCareer OpportunitiesTechnology InsightsUtilNexa ToolsAlgoGalaxy HomeContact Support

AlgoGalaxy CodeRush

CodeRush HomeProblem SetsProgress TrackerLearn TechnologyTechnology JobsEngineering InsightsDeveloper UtilitiesAlgoGalaxy HomePrivacy Policy
Privacy Policy

 • 

Terms of Service

Copyright © AlgoGalaxy 2026