Home Blog Page 85

Unit Testing with JUnit and Mockito in Java

0
java spring boot course
java spring boot course

Table of Contents

  1. Introduction to Unit Testing
  2. Setting Up JUnit and Mockito
  3. Writing Your First Unit Test with JUnit
  4. Understanding Assertions
  5. Introduction to Mockito
  6. Writing Unit Tests Using Mockito
  7. Mocking and Stubbing Dependencies
  8. Argument Matchers and Verification
  9. Best Practices in Unit Testing
  10. Summary

1. Introduction to Unit Testing

Unit testing is the process of testing individual units or components of a software application in isolation to ensure they work as expected. In Java, JUnit is the most popular framework for writing unit tests, and Mockito is the de facto standard for mocking dependencies.

The main goals of unit testing are to:

  • Ensure correctness of individual units (methods/classes)
  • Simplify debugging
  • Improve code quality and reliability
  • Enable refactoring with confidence

2. Setting Up JUnit and Mockito

Using Maven

Add the following dependencies to your pom.xml:

<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.9.1</version>
<scope>test</scope>
</dependency>

<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>5.2.0</version>
<scope>test</scope>
</dependency>

Using Gradle

testImplementation 'org.junit.jupiter:junit-jupiter:5.9.1'
testImplementation 'org.mockito:mockito-core:5.2.0'

Also, ensure JUnit 5 is enabled with:

test {
useJUnitPlatform()
}

3. Writing Your First Unit Test with JUnit

Create a simple class:

public class Calculator {
public int add(int a, int b) {
return a + b;
}
}

Test it using JUnit:

import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;

class CalculatorTest {
@Test
void testAddition() {
Calculator calc = new Calculator();
assertEquals(5, calc.add(2, 3));
}
}

4. Understanding Assertions

JUnit provides a variety of assertion methods:

  • assertEquals(expected, actual)
  • assertNotEquals(expected, actual)
  • assertTrue(condition)
  • assertFalse(condition)
  • assertThrows(exception.class, executable)
  • assertAll() — to group multiple assertions

Example:

assertAll(
() -> assertEquals(4, calc.add(2, 2)),
() -> assertNotEquals(5, calc.add(2, 2))
);

5. Introduction to Mockito

Mockito allows you to create mock objects for dependencies. It’s useful when testing service classes that rely on repositories or external systems.

import static org.mockito.Mockito.*;

MyRepository mockRepo = mock(MyRepository.class);

6. Writing Unit Tests Using Mockito

Let’s say we have a service class:

public class UserService {
private final UserRepository userRepository;

public UserService(UserRepository userRepository) {
this.userRepository = userRepository;
}

public User findUser(String id) {
return userRepository.findById(id);
}
}

Test with Mockito:

import org.junit.jupiter.api.Test;
import static org.mockito.Mockito.*;
import static org.junit.jupiter.api.Assertions.*;

class UserServiceTest {
@Test
void testFindUser() {
UserRepository mockRepo = mock(UserRepository.class);
User user = new User("1", "Alice");
when(mockRepo.findById("1")).thenReturn(user);

UserService service = new UserService(mockRepo);
User result = service.findUser("1");

assertEquals("Alice", result.getName());
verify(mockRepo).findById("1");
}
}

7. Mocking and Stubbing Dependencies

Mocking allows you to:

  • Replace actual implementations with controlled behavior
  • Simulate exceptions
  • Return dummy values for tests

Example:

when(repository.save(any(User.class))).thenThrow(new RuntimeException("DB Error"));

8. Argument Matchers and Verification

Mockito provides matchers like any(), eq(), contains(), etc.

verify(repository, times(1)).findById(eq("1"));

You can also capture arguments with ArgumentCaptor.

ArgumentCaptor<User> captor = ArgumentCaptor.forClass(User.class);
verify(repository).save(captor.capture());
assertEquals("Bob", captor.getValue().getName());

9. Best Practices in Unit Testing

  • Test one unit of functionality per test case
  • Keep test methods short and focused
  • Use meaningful test method names
  • Don’t overuse mocks—test real behavior where possible
  • Write both positive and negative test cases
  • Ensure tests are independent and deterministic

10. Summary

Unit testing with JUnit and Mockito enables you to build reliable and maintainable Java applications. You can test classes in isolation, mock dependencies, and simulate various scenarios without relying on external systems.

CORS, CSRF, and Secure Headers in Spring Boot

0
java spring boot course
java spring boot course

Table of Contents

  1. Introduction
  2. What is CORS?
    • Why CORS Exists
    • Configuring CORS in Spring Boot
  3. What is CSRF?
    • CSRF Explained
    • CSRF in State vs Stateless Applications
    • Disabling or Enabling CSRF in Spring Boot
  4. Secure HTTP Headers
    • Why Headers Matter
    • Using Spring Security Headers
  5. Best Practices for API Security
  6. Summary

1. Introduction

When securing a Spring Boot application—especially one exposed over HTTP or HTTPS—it’s crucial to handle CORS, CSRF, and security headers properly. These are often overlooked but form the first line of defense against attacks like cross-site scripting (XSS), cross-site request forgery, clickjacking, and more.


2. What is CORS? (Cross-Origin Resource Sharing)

CORS is a browser mechanism that blocks requests from one origin to another unless explicitly allowed by the server.

Why CORS Exists

Say your frontend (React, Angular) is running on http://localhost:3000 and your backend is on http://localhost:8080. This is considered cross-origin. Browsers block such requests unless the backend says, “I trust this origin.”

Configuring CORS in Spring Boot

There are multiple ways to enable CORS:

At Controller Level

@CrossOrigin(origins = "http://localhost:3000")
@RestController
public class MyController {
// endpoints
}

Globally via WebMvcConfigurer

@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("http://localhost:3000")
.allowedMethods("GET", "POST", "PUT", "DELETE")
.allowedHeaders("*")
.allowCredentials(true);
}
}

With Spring Security

@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http.cors(Customizer.withDefaults());
return http.build();
}

And define a CorsConfigurationSource bean if you need fine control.


3. What is CSRF? (Cross-Site Request Forgery)

CSRF Explained

CSRF is an attack where a malicious site tricks a user’s browser into sending unwanted requests to your site, exploiting authenticated sessions.

CSRF in State vs Stateless Applications

  • Stateful Apps (with Sessions): CSRF is a real threat.
  • Stateless REST APIs: Usually CSRF protection is disabled because JWT tokens or other mechanisms are used, and no session is maintained.

Disabling CSRF in Spring Boot

http.csrf().disable();

This is typical in JWT-based authentication scenarios.

Enabling CSRF (If Needed)

For form-based login:

http.csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse());

This stores a CSRF token in a cookie and expects it in a header with every request.


4. Secure HTTP Headers

Headers can protect your app from various attacks:

Common Secure Headers

HeaderPurpose
X-Content-Type-OptionsPrevents MIME type sniffing
X-Frame-OptionsPrevents clickjacking
Strict-Transport-SecurityForces HTTPS
X-XSS-ProtectionEnables basic XSS protection
Content-Security-PolicyRestricts sources for scripts, etc.
Referrer-PolicyControls referrer information

Enable Headers in Spring Security

http.headers()
.contentTypeOptions()
.and()
.frameOptions().deny()
.and()
.httpStrictTransportSecurity().includeSubDomains(true).maxAgeInSeconds(31536000)
.and()
.xssProtection().block(true);

For CSP (Content Security Policy):

http.headers()
.contentSecurityPolicy("script-src 'self'; object-src 'none';");

5. Best Practices for API Security

  • Always validate input on both client and server side.
  • Enable CORS only for trusted origins.
  • Disable CSRF if using stateless tokens (JWT, OAuth2), else enable it.
  • Enforce HTTPS and HSTS.
  • Apply security headers for browsers.
  • Rate limit and throttle API requests.
  • Log and monitor for unusual activity.

6. Summary

Security features like CORS, CSRF, and secure HTTP headers may seem minor, but they’re essential to protect your app from common web threats.

  • CORS allows cross-origin requests securely.
  • CSRF should be disabled in token-based APIs but enabled for form-based sessions.
  • Security headers add layers of protection against XSS, clickjacking, and protocol downgrade attacks.

Role-Based Access Control (RBAC) in Spring Security

0
java spring boot course
java spring boot course

Table of Contents

  1. What is RBAC?
  2. Benefits of Using RBAC
  3. Defining Roles in Spring Security
  4. Role-Based Access with Annotations
  5. Role Hierarchy in Spring Security
  6. Fine-Grained Access Control Using Expressions
  7. Best Practices for Implementing RBAC
  8. Summary

1. What is RBAC?

Role-Based Access Control (RBAC) is a security mechanism that restricts access to resources based on the roles assigned to users. In Spring Security, roles determine what actions a user can perform or what endpoints they can access.

Example:

  • Role ADMIN may access /admin/**
  • Role USER may only access /user/**

2. Benefits of Using RBAC

  • Centralized control: Easier management of access rules.
  • Scalability: Adding new roles or users doesn’t require changing application logic.
  • Improved security: Reduces chances of unauthorized access.
  • Auditable: Easier to audit and enforce organizational security policies.

3. Defining Roles in Spring Security

Step 1: User Definition with Roles

@Bean
public InMemoryUserDetailsManager userDetailsService() {
UserDetails user = User.withUsername("user")
.password(passwordEncoder().encode("user123"))
.roles("USER")
.build();

UserDetails admin = User.withUsername("admin")
.password(passwordEncoder().encode("admin123"))
.roles("ADMIN")
.build();

return new InMemoryUserDetailsManager(user, admin);
}

Spring automatically prefixes ROLE_ to each role. So roles("ADMIN") becomes ROLE_ADMIN.


4. Role-Based Access with Annotations

@PreAuthorize and @Secured

Using @Secured:

@Secured("ROLE_ADMIN")
@GetMapping("/admin/dashboard")
public String adminDashboard() {
return "Welcome Admin!";
}

Using @PreAuthorize:

@PreAuthorize("hasRole('ADMIN')")
@GetMapping("/admin/dashboard")
public String adminDashboard() {
return "Welcome Admin!";
}

To enable annotations:

@EnableMethodSecurity(securedEnabled = true, prePostEnabled = true)
@Configuration
public class SecurityConfig {
// your security beans
}

5. Role Hierarchy in Spring Security

You can define role inheritance so that a higher role includes the authorities of lower roles.

@Bean
public RoleHierarchy roleHierarchy() {
RoleHierarchyImpl hierarchy = new RoleHierarchyImpl();
hierarchy.setHierarchy("ROLE_ADMIN > ROLE_USER");
return hierarchy;
}

This means an ADMIN implicitly has all permissions of a USER.


6. Fine-Grained Access Control Using Expressions

Spring Security provides rich expression support with @PreAuthorize and @PostAuthorize.

Examples:

@PreAuthorize("hasRole('ADMIN') or hasRole('MODERATOR')")
public String accessControl() {
return "Admin or Moderator Access";
}

@PreAuthorize("#user.username == authentication.name")
public String getUserData(User user) {
return "Accessing own data";
}

You can access:

  • authentication: the current authentication object
  • principal: the current logged-in user
  • #param: method parameters

7. Best Practices for Implementing RBAC

  • Use meaningful role names (ROLE_VIEWER, ROLE_MANAGER) over generic ones.
  • Externalize role definitions if possible (e.g., in DB or LDAP).
  • Use role hierarchy to simplify rules.
  • Apply the principle of least privilege—grant only necessary permissions.
  • Regularly audit roles and access mappings.

8. Summary

RBAC is a powerful and scalable way to manage access control in Spring applications. It lets you separate who can access what, based on roles rather than hard-coded user IDs.

Key Concepts Covered:

  • Defining users with roles
  • Using @Secured, @PreAuthorize for enforcement
  • Configuring role hierarchies
  • Using security expressions for dynamic control

Next, we’ll explore more advanced topics like JWT-based authentication, OAuth2, and custom authorization filters for building highly secure RESTful applications.

Basic Authentication Setup in Spring Security

0
java spring boot course
java spring boot course

Table of Contents

  1. What is Basic Authentication?
  2. How Basic Authentication Works in Spring Security
  3. Setting Up Basic Authentication in a Spring Boot Application
  4. Creating Custom User Details
  5. Configuring a Custom Security Filter Chain
  6. Testing Basic Authentication with Postman or curl
  7. Summary

1. What is Basic Authentication?

Basic Authentication is a simple authentication scheme built into the HTTP protocol. It transmits credentials (username and password) encoded in Base64 in the Authorization header. Though easy to implement, it should always be used over HTTPS to protect credentials from interception.

Example Authorization Header:

Authorization: Basic dXNlcjpwYXNzd29yZA==

The encoded string is just username:password in Base64.


2. How Basic Authentication Works in Spring Security

Spring Security supports HTTP Basic Authentication out of the box. Once enabled, Spring Security:

  • Intercepts all HTTP requests
  • Checks for an Authorization: Basic header
  • Decodes the credentials
  • Validates the user using a UserDetailsService
  • Grants or denies access based on authentication and roles

3. Setting Up Basic Authentication in a Spring Boot Application

Step 1: Add Spring Security Dependency

For Maven:

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

Step 2: Default Behavior

If you don’t configure anything, Spring Security auto-generates a default user (user) with a random password. You can test this immediately via browser or API tools.

To override this behavior and set custom credentials, configure the following in application.properties:

spring.security.user.name=admin
spring.security.user.password=admin123

4. Creating Custom User Details

You can define your own users and roles using the UserDetailsService interface and InMemoryUserDetailsManager.

@Configuration
public class SecurityConfig {

@Bean
public InMemoryUserDetailsManager userDetailsService() {
UserDetails user = User.withUsername("john")
.password(passwordEncoder().encode("john123"))
.roles("USER")
.build();

UserDetails admin = User.withUsername("admin")
.password(passwordEncoder().encode("admin123"))
.roles("ADMIN")
.build();

return new InMemoryUserDetailsManager(user, admin);
}

@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}

5. Configuring a Custom Security Filter Chain

Next, create a filter chain to specify security rules:

@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.csrf().disable()
.authorizeHttpRequests()
.requestMatchers("/public/**").permitAll()
.anyRequest().authenticated()
.and()
.httpBasic(); // Enables basic authentication

return http.build();
}

This config:

  • Disables CSRF (not recommended for web apps, okay for REST APIs)
  • Allows open access to /public/**
  • Secures all other endpoints with basic authentication

6. Testing Basic Authentication with Postman or curl

Using curl:

curl -u john:john123 http://localhost:8080/api/secure-data

Using Postman:

  1. Open Postman and select your endpoint.
  2. Go to Authorization tab.
  3. Choose Basic Auth.
  4. Enter your username and password.
  5. Hit Send.

Spring Security will decode credentials and authorize based on roles and configuration.


7. Summary

Basic authentication is a fast and minimal way to protect your endpoints, ideal for internal tools or simple APIs. However, it sends credentials with every request, so it must be used with HTTPS to ensure security.

Key Points:

  • Easy to set up with Spring Security and Spring Boot.
  • Credentials are passed in Base64, not encrypted—SSL is essential.
  • Works well with tools like Postman, curl, and simple API clients.
  • Not recommended for public-facing applications without token-based enhancements.

In future modules, we’ll cover form-based login, JWT-based authentication, and integrating with external identity providers for more advanced and secure setups.

Introduction to Spring Security

0
java spring boot course
java spring boot course

Table of Contents

  1. What is Spring Security?
  2. Core Features of Spring Security
  3. How Spring Security Works
  4. Spring Security Architecture
  5. Adding Spring Security to a Spring Boot Application
  6. Default Behavior and Auto-Configuration
  7. Summary

1. What is Spring Security?

Spring Security is a powerful and customizable authentication and access control framework for Java applications, especially those built using the Spring framework. It is the de facto standard for securing Spring-based applications.

Spring Security offers comprehensive security services for:

  • Authentication – verifying the identity of users.
  • Authorization – controlling access to resources based on roles/permissions.

It supports a wide range of security features including form-based login, OAuth2, JWT, LDAP, method-level security, and much more.


2. Core Features of Spring Security

Spring Security comes with a rich set of security features:

  • Authentication and Authorization: Built-in support for user login and role-based access control.
  • Password Encoding: Uses secure hashing algorithms (like BCrypt) to store passwords.
  • Security Headers: Helps protect against attacks such as XSS, clickjacking, etc.
  • CSRF Protection: Cross-Site Request Forgery protection is enabled by default.
  • Session Management: Controls concurrent sessions and session invalidation.
  • Method-Level Security: Allows securing methods using annotations such as @PreAuthorize, @Secured.
  • Integration: Easily integrates with OAuth2, LDAP, SAML, and custom authentication providers.

3. How Spring Security Works

Spring Security works by configuring a filter chain that intercepts incoming HTTP requests and processes them through various security filters.

Basic Flow:

  1. A user sends a request to a secured resource.
  2. The request hits the Security Filter Chain, which checks if the resource requires authentication.
  3. If yes, Spring Security checks whether the user is authenticated and has the necessary authority.
  4. If authenticated and authorized, access is granted. If not, a suitable error (like 401 or 403) is returned.

The filters in the chain can handle:

  • Logging in/out
  • Validating session or tokens
  • CSRF validation
  • Applying security headers

4. Spring Security Architecture

Key components in Spring Security:

  • SecurityFilterChain: Central component for applying security filters to incoming requests.
  • AuthenticationManager: Responsible for processing authentication requests.
  • UserDetailsService: Interface to fetch user-specific data.
  • GrantedAuthority: Represents the role or privilege assigned to a user.
  • SecurityContext: Holds the currently authenticated user’s details in a thread-local storage.
  • PasswordEncoder: Used to hash passwords before storing and comparing them.

5. Adding Spring Security to a Spring Boot Application

Step 1: Add Dependency

In pom.xml:

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

Or for Gradle:

implementation 'org.springframework.boot:spring-boot-starter-security'

Step 2: Default Behavior

Once the dependency is added, Spring Boot auto-configures basic security:

  • All endpoints are secured by default.
  • A login form is available at /login.
  • A default in-memory user with a generated password is created.

On application startup, a password will be printed in the logs:

Using generated security password: 9d5b6142-XXXX-XXXX

You can use this to log in with the default user user.


6. Default Behavior and Auto-Configuration

When Spring Security is included:

  • All HTTP endpoints require authentication.
  • A login page is auto-generated at /login.
  • HTTP Basic and Form-based authentication are enabled.
  • CSRF protection is enabled.
  • Static resources (like CSS, JS) are allowed by default.

You can customize this behavior using a configuration class:

@Configuration
public class SecurityConfig {

@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests()
.requestMatchers("/public/**").permitAll()
.anyRequest().authenticated()
.and()
.formLogin();
return http.build();
}
}

7. Summary

Spring Security is a full-featured, highly customizable framework for securing Java applications. Its plug-and-play integration with Spring Boot makes it easy to set up authentication and authorization for your REST APIs or web applications.

Key Points:

  • It provides robust security features including CSRF, headers, sessions, and method-level access control.
  • Security is applied through a filter chain that intercepts and processes every request.
  • Once integrated, all endpoints are protected by default until explicitly configured.

In upcoming modules, we will cover:

  • Custom user details and authentication providers
  • JWT-based security
  • Role-based access control
  • Method-level and endpoint-level security
  • Integration with Spring Boot APIs

This foundational understanding is essential as we dive deeper into securing real-world applications using Spring Security.