Spring Boot + Swagger 3(OpenAPI) + Web Security(2023) Example| CodeUsingJava


































Spring Boot With Swagger3 with Web Security Example

In this tutorial we will be implementing Web Security example using Swagger.
We have discussed the introduction of Swagger in our previous article.
It is also possible to configure Swagger3 along with Spring security. Here, we will configure Spring Security in our previous application.
In this example, we will see the working of all API's when the security is enabled in the Swagger Ui.
  • Project Structure

    This will be the standard directory layout for maven project structure-
    Spring Boot Maven Project structure
    We need to start by creating a Maven pom.xml(Project Object Model) file. The pom.xml file contains the project configuration details.
    To configure the Swagger, we need to add the dependency for Open Api specification in our program.
    	<?xml version="1.0" encoding="UTF-8"?>
    	<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    		xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    		<modelVersion>4.0.0</modelVersion>
    		<parent>
    			<groupId>org.springframework.boot</groupId>
    			<artifactId>spring-boot-starter-parent</artifactId>
    			<version>2.5.1</version>
    			<relativePath/> <!-- lookup parent from repository -->
    		</parent>
    		<groupId>com.codeusingjava</groupId>
    		<artifactId>SpringwithSwagger</artifactId>
    		<version>0.0.1-SNAPSHOT</version>
    		<name>SpringSecuritywithSwagger</name>
    		<description>Spring boot wit Swaggar</description>
    		<properties>
    			<java.version>1.8</java.version>
    		</properties>
    		<dependencies>
    			<dependency>
    				<groupId>org.springframework.boot</groupId>
    				<artifactId>spring-boot-starter-data-jpa</artifactId>
    			</dependency>
    			<dependency>
    				<groupId>org.springframework.boot</groupId>
    				<artifactId>spring-boot-starter-web</artifactId>
    			</dependency>
    			<dependency>
    				<groupId>org.projectlombok</groupId>
    				<artifactId>lombok</artifactId>
    				<optional>true</optional>
    			</dependency>
    	
    			<dependency>
    				<groupId>org.springdoc</groupId>
    				<artifactId>springdoc-openapi-ui</artifactId>
    				<version>1.4.3</version>
    			</dependency>  
    
    			<dependency>
    				<groupId>org.springframework.boot</groupId>
    				<artifactId>spring-boot-starter-security</artifactId>
    			</dependency>
    	
    			<dependency>
    				<groupId>com.h2database</groupId>
    				<artifactId>h2</artifactId>
    				<scope>runtime</scope>
    			</dependency>
    			<dependency>
    				<groupId>org.springframework.boot</groupId>
    				<artifactId>spring-boot-starter-test</artifactId>
    				<scope>test</scope>
    				<exclusions>
    					<exclusion>
    						<groupId>org.junit.vintage</groupId>
    						<artifactId>junit-vintage-engine</artifactId>
    					</exclusion>
    				</exclusions>
    			</dependency>
    		</dependencies>
    	
    		<build>
    			<plugins>
    				<plugin>
    					<groupId>org.springframework.boot</groupId>
    					<artifactId>spring-boot-maven-plugin</artifactId>
    				</plugin>
    			</plugins>
    		</build>
    	
    	</project>
    	
    
    Create the model class for the participants-
    	package com.codeusingjava.model;
    
    	import lombok.*;
    	
    	import javax.persistence.*;
    	
    	@Entity
    	@Data
    	public class Participants {
    	
    		@Id
    		@GeneratedValue(strategy = GenerationType.AUTO)
    		private long id;
    	
    		@Column
    		private String name;
    	
    		@Column
    		private String clas;
    	
    		@Column
    		private String catagory;
    	
    	
    	}
    	
    The repository class for the participants is as follows-
    package com.codeusingjava.repo;
    
    import org.springframework.data.jpa.repository.JpaRepository;
    import org.springframework.stereotype.Service;
    
    import com.codeusingjava.model.Participants;
    
    @Service
    public interface ParticipantRepo extends JpaRepository<Participants,Long> {
    }
    
    The configuration class for the Web Security Configuration is as follows-
    The @EnableWebSecurity is used to configure Spring Security in our application.
    The url for the Swagger must be configured to be permitted by all the users.
    We have used BCryptPasswordEncoder to encode the password and used inMemoryAuthentication to store user credentials. The password stored is 123. The description of these terms can be seen in previous SpringWebSecurity article.
    Various Security Schemes can be provided by the OpenApi. We can define several components like Scheme, type , header etc. in our application.
    
    package com.codeusingjava.config;
    
    import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
    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.configuration.WebSecurityConfigurerAdapter;
    
    import io.swagger.v3.oas.annotations.enums.SecuritySchemeIn;
    import io.swagger.v3.oas.annotations.enums.SecuritySchemeType;
    import io.swagger.v3.oas.annotations.security.SecurityScheme;
    
    
    @EnableWebSecurity   
    @SecurityScheme(name="codeusingjava", scheme="basic", type=SecuritySchemeType.HTTP, in=SecuritySchemeIn.HEADER)
    public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
    
    	
    	@Override
    	protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    		auth.inMemoryAuthentication()
    		.withUser("nj")
    		.password("{bcrypt}$2a$10$BagghBQvnxcVuhHyXc9g9.fM6s109FakmyF4tPAoOMRkjqKsg1xl.") //123
    		.authorities("ADMIN");
    	}
    
    	@Override
    	protected void configure(HttpSecurity http) throws Exception {
    		http.authorizeRequests()
    		
    		.antMatchers("/swagger-ui/**","/v3/api-docs/**").permitAll()
    		.anyRequest().authenticated()
    		.and().httpBasic();
    		http.csrf().disable();
    	}
    }
    
    
    The Controller class for the participants is as follows-
    Here all the endpoints are defined in the application.
    The @Operation is used to describes the functioning of the endpoints.
    The @ApiResponse can be used to display the response that can be possible.
    We need to configure the SecurityRequirement where we define the security schema to the mappings where we want to configure the security. If we want to apply on all the mapping, we can use it at the method level if we want to apply to only particular methods.
    package com.codeusingjava.controller;
    
    
    import io.swagger.v3.oas.annotations.Operation;
    import io.swagger.v3.oas.annotations.media.Content;
    import io.swagger.v3.oas.annotations.responses.ApiResponse;
    import io.swagger.v3.oas.annotations.responses.ApiResponses;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.http.HttpStatus;
    import org.springframework.web.bind.annotation.*;
    
    import com.codeusingjava.model.Participants;
    import com.codeusingjava.repo.ParticipantRepo;
    
    import java.util.List;
    
    @RestController
    @RequestMapping("/annualday")
    @SecurityRequirement(name="codeusingjava")
    public class ParticipantController {
    
        @Autowired
        private ParticipantRepo participantsRepository;
    
        @Operation(summary = "This is to fetch All the Participantss stored in Db")
        @ApiResponses(value = {
                @ApiResponse(responseCode = "200",
                description = "Details of All the Participants",
                content = {@Content(mediaType = "application/json")}),
                @ApiResponse(responseCode = "404",
                description = "Page not found",
                content = @Content)
        })
        @GetMapping("/Participants/")
        public List<Participants> allParticipantss() {
            return participantsRepository.findAll();
        }
    
        @Operation(summary = "This is to add  the Participants in the database")
        @ApiResponses(value = {
                @ApiResponse(responseCode = "200",
                description = " Participant details saved in database",
                content = {@Content(mediaType = "application/json")}),
                @ApiResponse(responseCode = "404",
                description = " Page Not Found",
                content = @Content)
        })
        @PostMapping("/Participants/")
        @ResponseStatus(HttpStatus.CREATED)
        public Participants create(@RequestBody Participants Participants)
        {
            return participantsRepository.save(Participants);
        }
    
        @Operation(summary = "This is to delete  the Participants in the database")
        @ApiResponses(value = {
                @ApiResponse(responseCode = "200",
                description = " Participant deleted from the database",
                content = {@Content(mediaType = "application/json")}),
                @ApiResponse(responseCode = "404",
                description = " Page Not Found",
                content = @Content)
        })
        @DeleteMapping("/Participants/{id}")
        public void delete(@PathVariable long id)
        {
            participantsRepository.findById(id);
           
            participantsRepository.deleteById(id);
        }
        @Operation(summary = "This is to udate  the Participants in the database")
        @ApiResponses(value = {
                @ApiResponse(responseCode = "200",
                description = " Participant details updated in database",
                content = {@Content(mediaType = "application/json")}),
                @ApiResponse(responseCode = "404",
                description = " Page Not Found",
                content = @Content)
        })
        @PutMapping("/Participants/{id}")
        public Participants updateParticipants(@RequestBody Participants Participants, @PathVariable Long id) {
    
            participantsRepository.findById(id);
                  
            return participantsRepository.save(Participants);
        }
    
        @Operation(summary = "This is to get  the details of particular  Participants in the database")
        @ApiResponses(value = {
                @ApiResponse(responseCode = "200",
                description = " Participant details fetched from database",
                content = {@Content(mediaType = "application/json")}),
                @ApiResponse(responseCode = "404",
                description = " Page Not Found",
                content = @Content)
        })
        @GetMapping("/Participants/{id}")
        public Participants find(@PathVariable Long id) {
            return participantsRepository.findById(id).get();
                  
        }
    
    
    }
    
    The main class for the Application is as follows-
    With the help of OpenAPIDefinition, general information can be configured in the application.
    Here, I have configured title for the application.
    package com.codeusingjava;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    
    import io.swagger.v3.oas.annotations.OpenAPIDefinition;
    import io.swagger.v3.oas.annotations.info.Info;
    
    @SpringBootApplication
    @OpenAPIDefinition(info=@Info(title="Annual Day Participants"))
    public class SpringwithSwaggerApplication {
    
    	public static void main(String[] args) {
    		SpringApplication.run(SpringwithSwaggerApplication.class, args);
    	}
    
    }
    	
If we now run the application we get the output as follows-
When we click on http://localhost:8080/ui.html, we get the following as our output.
All the description of the endpoints as well as title is displayed clearly.
We can see the Authorisation header. This can be seen by the security schema configured n our application.
A popup would be displayed when the user clicks on execute button to execute the endpoint.
Output of Swagger

The endpoints when run in Insomnia client gives the output as follows-
First the user needs to authenticate himself then he can accesss the mapping.
post Output of Swagger

The spring security can also be configured in the following manner by clicking on the following icon-
Lock icon of Swagger
The login page would be coming as follows-
security of Swagger
After login , the screen would be as follows-
After login  of Swagger