spring security+swagger3 access default path( http://localhost: Port / swagger UI /) appears 404

springboot vue3 redis MySQL spring security swagger3 front and back end separation items.

redis and rabbitMQ

Redis:
Redis is a multi utility tool. It is a key value NoSQL database that can be used as a cache. It is very active in development and maintenance. Although it is a key value database storage system, it supports MQ functions, message queuing (redis supports publish / subscribe locally), and any short-term data in the application, Therefore, it can be used as a lightweight queue service.

rely on

 <!--redis rely on-->
        <dependency>
            <groupId>org.springframework.session</groupId>
            <artifactId>spring-session-data-redis</artifactId>
            <version>${spring.boot.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
            <version>${spring.boot.version}</version>
        </dependency>

RabbitMQ:
RabbitMQ is a kind of message middleware that implements AMQP (Advanced message queuing protocol). It originated from the financial system and is used to store and forward messages in distributed systems. It performs well in terms of ease of use, scalability and high availability. Message middleware is mainly used for decoupling between components. The sender of a message does not need to know the existence of the message consumer, and vice versa.

spring security

The core functions of spring security mainly include authentication, authorization and attack protection.

rely on

<!--security verification-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
            <version>${spring.boot.version}</version>
        </dependency>

swagger3

For projects with front-end and back-end separation, the existence of interface documents is very important. Swagger is a tool for automatically generating interface documents. In the environment of changing requirements, the efficiency of manually writing documents is too low. Compared with swagger 2, the new version of swagger 3 has fewer configurations and is more convenient to use.

rely on

<!-- Swagger3 rely on -->
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-boot-starter</artifactId>
            <version>3.0.0</version>
        </dependency>

How to deal with error reporting

First, pay attention to the back-end port when accessing. Don't make a mistake. Then check whether it is a configuration error

Configuration of swagger3

Firstly, the configuration of swagger3 is normal, and the project will not make mistakes because of the configuration of swagger3, so let's look at other configurations next

package com.mindskip.xzs.configuration.spring.swagger;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.bind.annotation.ResponseBody;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.oas.annotations.EnableOpenApi;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;

import java.util.ArrayList;
//Open OpenApi
@EnableOpenApi
@Configuration
public class SwaggerConfig {

    public Docket docket(){
        Docket docket = new Docket(DocumentationType.OAS_30);
        docket.apiInfo(apiInfo())
                .select()
                .apis(RequestHandlerSelectors.basePackage("com.mindskip.xzs.controller"))
                .paths(PathSelectors.any()).build();
        return docket;
    }

    private ApiInfo apiInfo(){
        Contact contact = new Contact("author mxy", "author http://www.xxx.com","example@qq.com");
        ApiInfo apiInfo = new ApiInfo(
                "Swagger3 Interface documentation",
                "SpringBoot integration Swagger3 Generate interface document!",
                "1.0.0",
                "termsOfServiceUrl",
                contact,
                "Here is license",
                "Here is licenseUrl",
                new ArrayList());
        return apiInfo;
    }

}

Configuration of webmvc

webmvc and spring security can be configured for cross domain and interception, so pay attention to the comments I added to release swagger3 resources.

package com.mindskip.xzs.configuration.spring.mvc;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.*;

import java.util.List;

@Configuration
public class WebMvcConfiguration extends WebMvcConfigurationSupport {
    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        /**
         * After the separation, the cross domain security configuration fails after SpringBoot+SpringSecurity allows Swagger access
         */
        registry.addViewController("/swagger-ui/")
                .setViewName("forward:/swagger-ui/index.html");

        registry.addRedirectViewController("/", "/student/index.html");
        registry.addRedirectViewController("/student", "/student/index.html");
        registry.addRedirectViewController("/admin", "/admin/index.html");
    }

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/**")
                .addResourceLocations("classpath:/static/")
                .setCachePeriod(31556926);
        /**
         * The interface document generated by the swagger used in the project also has security permission verification. In order to facilitate the back-end test, the interface test directly accesses swagger;
         * However, if security does not release swagger, swagger cannot be accessed locally. At the same time, the front end needs to access the back-end interface, which also has cross domain problems;
         * Security When swagger access is not granted, an error will be reported when requesting the interface with swagger:
         */
        registry.addResourceHandler("/swagger-ui/**")
                .addResourceLocations("classpath:/META-INF/resources/webjars/springfox-swagger-ui/")
                .resourceChain(false);
    }
    @Override
    public void addCorsMappings(CorsRegistry registry) {

        registry.addMapping("/**")
                .allowCredentials(true)
                .allowedMethods("*")
                .allowedOrigins("*")
                .allowedHeaders("*");
        super.addCorsMappings(registry);
    }
}

spring security configuration

Also pay attention to the notes and release swagger3

package com.mindskip.xzs.configuration.spring.security;

import com.mindskip.xzs.configuration.property.CookieConfig;
import com.mindskip.xzs.configuration.property.SystemConfig;
import com.mindskip.xzs.domain.enums.RoleEnum;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
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.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;

import java.util.Collections;
import java.util.List;


/**
 * spring security Authorized authentication
 */

@Configuration
@EnableWebSecurity
public class SecurityConfigurer {

    @Configuration
    public static class FormLoginWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {

        private final SystemConfig systemConfig;
        private final LoginAuthenticationEntryPoint restAuthenticationEntryPoint;
        private final RestAuthenticationProvider restAuthenticationProvider;
        private final RestDetailsServiceImpl formDetailsService;
        private final RestAuthenticationSuccessHandler restAuthenticationSuccessHandler;
        private final RestAuthenticationFailureHandler restAuthenticationFailureHandler;
        private final RestLogoutSuccessHandler restLogoutSuccessHandler;
        private final RestAccessDeniedHandler restAccessDeniedHandler;

        @Autowired
        public FormLoginWebSecurityConfigurerAdapter(SystemConfig systemConfig, LoginAuthenticationEntryPoint restAuthenticationEntryPoint, RestAuthenticationProvider restAuthenticationProvider, RestDetailsServiceImpl formDetailsService, RestAuthenticationSuccessHandler restAuthenticationSuccessHandler, RestAuthenticationFailureHandler restAuthenticationFailureHandler, RestLogoutSuccessHandler restLogoutSuccessHandler, RestAccessDeniedHandler restAccessDeniedHandler) {
            this.systemConfig = systemConfig;
            this.restAuthenticationEntryPoint = restAuthenticationEntryPoint;
            this.restAuthenticationProvider = restAuthenticationProvider;
            this.formDetailsService = formDetailsService;
            this.restAuthenticationSuccessHandler = restAuthenticationSuccessHandler;
            this.restAuthenticationFailureHandler = restAuthenticationFailureHandler;
            this.restLogoutSuccessHandler = restLogoutSuccessHandler;
            this.restAccessDeniedHandler = restAccessDeniedHandler;
        }

        /**
         * @param http http
         */
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.headers().frameOptions().disable();

            List<String> securityIgnoreUrls = systemConfig.getSecurityIgnoreUrls();
            String[] ignores = new String[securityIgnoreUrls.size()];
            
            http
                    .addFilterAt(authenticationFilter(), UsernamePasswordAuthenticationFilter.class)
                    .exceptionHandling().authenticationEntryPoint(restAuthenticationEntryPoint)
                    .and().authenticationProvider(restAuthenticationProvider)
                    .authorizeRequests()
                    .antMatchers(securityIgnoreUrls.toArray(ignores)).permitAll()
                    .antMatchers("/api/admin/**").hasRole(RoleEnum.ADMIN.getName())
                    .antMatchers("/api/student/**").hasRole(RoleEnum.STUDENT.getName())
                    // Add this line of code to release swagger3 resources. The specific need has not been verified
                    .antMatchers("/v3/**").permitAll()
                    .anyRequest().permitAll()
                    .and().exceptionHandling().accessDeniedHandler(restAccessDeniedHandler)
                    .and().formLogin().successHandler(restAuthenticationSuccessHandler).failureHandler(restAuthenticationFailureHandler)
                    .and().logout().logoutUrl("/api/user/logout").logoutSuccessHandler(restLogoutSuccessHandler).invalidateHttpSession(true)
                    .and().rememberMe().key(CookieConfig.getName()).tokenValiditySeconds(CookieConfig.getInterval()).userDetailsService(formDetailsService)
                  
                    .and().csrf().disable()
                    .cors(); 
            }

        /**
         * swagger3 bypass
         */
        @Override
        public void configure(WebSecurity web) throws Exception {
            web.ignoring().antMatchers("/swagger-ui/**", "/swagger-resources/**", "/v3/**");

        }

        @Bean
        public CorsConfigurationSource corsConfigurationSource() {
            
            final CorsConfiguration configuration = new CorsConfiguration();
            configuration.setMaxAge(3600L);
           
            configuration.setAllowedOrigins(Collections.singletonList("*"));
            configuration.setAllowedMethods(Collections.singletonList("*"));
            configuration.setAllowCredentials(true);
            configuration.setAllowedHeaders(Collections.singletonList("*")); 
            final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
            source.registerCorsConfiguration("/api/**", configuration);
          
            return source;
        }


        @Bean
        public RestLoginAuthenticationFilter authenticationFilter() throws Exception {
            RestLoginAuthenticationFilter authenticationFilter = new RestLoginAuthenticationFilter();
            authenticationFilter.setAuthenticationSuccessHandler(restAuthenticationSuccessHandler);
            authenticationFilter.setAuthenticationFailureHandler(restAuthenticationFailureHandler);
            authenticationFilter.setAuthenticationManager(authenticationManagerBean());
            authenticationFilter.setUserDetailsService(formDetailsService);
            return authenticationFilter;
        }


    }
}

After configuration, add comments in the controller, and then access the path http://localhost: Port / swagger UI / index.html

@Api: used on the requested class to indicate the description of the class

tags="The function of this class can be described in UI Comments seen on the interface"
value="This parameter is meaningless, in UI It can also be seen on the interface, so it does not need to be configured"

@ApiOperation: used on the requested method to describe the purpose and function of the method

value="Explain the purpose and function of the method"
notes="Remarks on the method"

@ApiImplicitParams: used on the requested method to represent a set of parameter descriptions

@ApiImplicitParam: Used in@ApiImplicitParams Annotation, specifying various aspects of a request parameter
    name: Parameter name
    value: Chinese character description and interpretation of parameters
    required: Whether the parameter must be passed
    paramType: Where are the parameters placed
        · header --> Acquisition of request parameters:@RequestHeader
        · query --> Acquisition of request parameters:@RequestParam
        · path(be used for restful Interface)--> Acquisition of request parameters:@PathVariable
        · div((not commonly used)
        · form((not commonly used)   
    dataType: Parameter type, default String,Other values dataType="Integer"     
    defaultValue: Default values for parameters

@ApiResponses: used in the method of a request to represent a set of responses

@ApiResponse: Used in@ApiResponses It is generally used to express the response information of an error
    code: Number, e.g. 400
    message: Information, e.g"Request parameters are not filled in"
    response: The class that threw the exception

@ApiModel: used on the response class to represent information that returns response data
(this is generally used in the scenario of @ RequestBody when creating a post, and the request parameters cannot be described with the @ ApiImplicitParam annotation.)
@ApiModelProperty: used on the property to describe the property of the response class

Tags: Java Spring Boot Vue Vue.js Spring Security

Posted on Sat, 20 Nov 2021 14:03:35 -0500 by Cut