8
respostas

Swagger nao funciona

Ola professor, sera que poderia me ajudar. eu fiz sua configuracao conforme a sua, mae meu swagger nao aparece minha api. Eu ate consigo ver a pagina /swagger-ui.html porem a api nao consta e tenho a mensagem: No operations defined in spec!

no log eu tenho o erro: * s.b.a.e.w.s.WebMvcEndpointHandlerMapping : Looking up handler method for path / 2019-08-05 11:14:42.593 DEBUG 11928 --- [nio-8085-exec-1] s.b.a.e.w.s.WebMvcEndpointHandlerMapping : Did not find handler method for [/] 2019-08-05 11:14:42.593 DEBUG 11928 --- [nio-8085-exec-1] a.e.w.s.ControllerEndpointHandlerMapping : Looking up handler method for path / 2019-08-05 11:14:42.594 DEBUG 11928 --- [nio-8085-exec-1] a.e.w.s.ControllerEndpointHandlerMapping : Did not find handler method for [/] 2019-08-05 11:14:42.595 DEBUG 11928 --- [nio-8085-exec-1] o.s.b.w.s.f.OrderedRequestContextFilter : Bound request context to thread: org.apache.catalina.connector.RequestFacade@39e3ccd4 2019-08-05 11:14:42.597 DEBUG 11928 --- [nio-8085-exec-1] o.s.b.a.audit.listener.AuditListener : AuditEvent [timestamp=2019-08-05T10:14:42.596Z, principal=anonymousUser, type=AUTHORIZATION_FAILURE, data={details=org.springframework.security.web.authentication.WebAuthenticationDetails@fffe9938: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: EE951CAAB6EF51BC2C72DEC2C0E9E7C6, type=org.springframework.security.access.AccessDeniedException, message=Access is denied}] 2019-08-05 11:14:42.597 DEBUG 11928 --- [nio-8085-exec-1] o.s.b.w.s.f.OrderedRequestContextFilter : Cleared thread-bound request context: org.apache.catalina.connector.RequestFacade@39e3ccd4 2019-08-05 11:14:42.598 DEBUG 11928 --- [nio-8085-exec-1] s.b.a.e.w.s.WebMvcEndpointHandlerMapping : Looking up handler method for path /error*

8 respostas

Oi Gilberto,

Posta aqui o código da sua classe SecurityConfigurations e também da sua classe SwaggerConfigurations.

package br.com.cadmea.spring.config;

import br.com.cadmea.model.orm.UserSystem;
import br.com.cadmea.spring.rest.ServicePath;
import com.google.common.base.Predicate;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.ParameterBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.schema.ModelRef;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

import javax.annotation.PostConstruct;
import java.util.Arrays;

import static com.google.common.base.Predicates.or;
import static springfox.documentation.builders.PathSelectors.regex;

@Slf4j
@Configuration
@EnableSwagger2
@Profile("development")
public class SwaggerConfig {

  @Value("${spring.profiles.active}")
  private String profile;

  @Value("${custom.swagger.package}")
  private String packageSwagger;

  @PostConstruct
  public void init() {
    log.info(" Swagger Config profile:" + this.profile);
  }

  @Bean
  public Docket postsApi() {
    return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo()).select()
        .apis(RequestHandlerSelectors.basePackage(this.packageSwagger))
        .paths(PathSelectors.ant("/**")).build()
        .ignoredParameterTypes(UserSystem.class).globalOperationParameters(
            Arrays.asList(new ParameterBuilder().name("Authorization")
                .description("Header para token JWT")
                .modelRef(new ModelRef("string")).parameterType("header")
                .required(false).build()));
  }

  private Predicate<String> postPaths() {
    return or(regex(ServicePath.PUBLIC_ROOT_PATH + ".*"),
        regex(ServicePath.PRIVATE_ROOT_PATH + ".*"));
  }

  private ApiInfo apiInfo() {
    return new ApiInfoBuilder().title("Cadmea System")
        .description("Cadmea Rest Services Documentation")
        .termsOfServiceUrl("http://gilbertosantos.com/cadmea/terms")
        .contact("contato@gilbertosantos.com")
        .license("Gilberto Santos License")
        .licenseUrl("contato@gilbertosantos.com").version("1.0").build();
  }
}
package br.com.cadmea.spring.config;

import br.com.cadmea.spring.beans.TokenService;
import br.com.cadmea.spring.beans.UserDetailsSrv;
import br.com.cadmea.spring.dao.UserSystemRepository;
import br.com.cadmea.spring.rest.ServicePath;
import br.com.cadmea.spring.security.JWTAuthorizationFilter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.security.authentication.AuthenticationManager;
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.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import javax.annotation.PostConstruct;
import javax.servlet.http.HttpServletResponse;

@Slf4j
@Configuration
@EnableWebSecurity
//@EnableGlobalMethodSecurity(prePostEnabled = true)
@Import({ UserDetailsSrv.class, TokenService.class })
public class SecurityConfig extends WebSecurityConfigurerAdapter {

  @Value("${spring.profiles.active}")
  private String profile;

  @Value("${cadmea.users.roles:ADMIN}")
  private String ROLES;

  @Autowired
  private UserDetailsSrv userService;

  @Autowired
  private TokenService tokenService;

  @Autowired
  private UserSystemRepository userSystemRepository;

  @PostConstruct
  public void init() {
    log.info(" security config profile:" + this.profile);
  }

  @Bean
  @Override
  public AuthenticationManager authenticationManager() throws Exception {
    return super.authenticationManager();
  }

  /**
   * define what's going to be ingored
   *
   * @param web
   * @throws Exception
   */
  @Override
  public void configure(final WebSecurity web) throws Exception {
    web.ignoring().antMatchers(publicEndPoints());
  }

  /**
   * define the security algorithmo for password
   *
   * @param auth
   * @throws Exception
   */
  @Override
  protected void configure(final AuthenticationManagerBuilder auth)
      throws Exception {
    auth.userDetailsService(this.userService)
        .passwordEncoder(new BCryptPasswordEncoder());
  }

  /**
   * define what's going to be acceptable for security
   *
   * @param http
   * @throws Exception
   */
  @Override
  protected void configure(final HttpSecurity http) throws Exception {
    http.csrf().disable();

    http.sessionManagement()
        .sessionCreationPolicy(SessionCreationPolicy.STATELESS);

    http.authorizeRequests().antMatchers(publicEndPoints()).permitAll();

    http.authorizeRequests().antMatchers(privateEndpoints())
        .hasAnyAuthority(this.ROLES.split(","));

    http.authorizeRequests().anyRequest().authenticated();

    http.addFilterBefore(new JWTAuthorizationFilter(this.tokenService,
        this.userSystemRepository), UsernamePasswordAuthenticationFilter.class);
  }

  /**
   * @return
   */
  private String[] privateEndpoints() {
    return new String[] { ServicePath.PRIVATE_ROOT_PATH + ServicePath.ALL };
  }

  /**
   * @return
   */
  private String[] publicEndPoints() {
    return new String[] { (ServicePath.PUBLIC_ROOT_PATH + ServicePath.ALL),
        ServicePath.LOGIN_PATH, ServicePath.LOGOUT_PATH, "/error/**",
        "/h2-console/**", "/resources/**", "/v2/rest-docs", "/v2/api-docs",
        "/swagger-resources/configuration", "/swagger-resources", "/**.html",
        "/webjars/**", "/login", "/csrf", "/" };
  }

  @Bean
  public AuthenticationEntryPoint unauthorizedEntryPoint() {
    return (request, response, authException) -> response
        .sendError(HttpServletResponse.SC_UNAUTHORIZED,
            "not authorized by cadmea system");
  }

}

Oi Gilberto,

Pelo código acredito que o problema possa ser no valor dessa variável na sua classe SwaggerConfigurations:

@Value("${custom.swagger.package}")
private String packageSwagger;

Confere o valor dela no application.properties e verifica se o pacote está correto de acordo com o pacote onde estão os seus controllers.

já havia testado com string ... o valor deve ser onde estao os controllers ou br.com.cadmea.rest ou pode ser a raiz de tudo br.com.cadmea precisa usar * ?

Pode ser o diretório raiz, de preferência o mesmo onde está a classe main ForumApplication.

Prof. a solucao foi colocar

@ComponentScan({ "br.com.cadmea.web" }) 

na minha class ForumApplication eu nao entendo bem o por que, voce usa apenas o

@SpringBootConfiguration

Oi Gilberto,

Só precisa dessa anotação se suas classes estiverem em pacotes que não sejam subpacotes da classe ForumApplication.

Por padrão o Spring Boot carrega apenas as classes do mesmo pacote onde está a classe main e de seus subpacotes.

Quer mergulhar em tecnologia e aprendizagem?

Receba a newsletter que o nosso CEO escreve pessoalmente, com insights do mercado de trabalho, ciência e desenvolvimento de software