Cannot send Authorization Bearer Token using Springfox

后端 未结 7 833
无人及你
无人及你 2021-02-08 05:59

I\'m having trouble understanding why \"Authorization: Bearer __\" is not being sent in my api using Springfox 2.5.0. I have the following configuration:

private         


        
相关标签:
7条回答
  • 2021-02-08 06:07

    I am using 2.8.0 versions and below swagger configuration works for me. I mentioned in comments, everything was working fine for me for version 2.7.0 but then I upgraded to 2.8.0 and jwt token stopped being sent in request header. I am on Spring Boot version - 1.5.2.RELEASE .

    Note that I wanted an UI where JWT token could be manually entered by user is format - Bearer ... and token should go in Authorization request header. Its not automatically integrated with OAuth server.

    import java.time.LocalDate;
    import java.util.Arrays;
    import java.util.List;
    
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.http.ResponseEntity;
    import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
    import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
    
    import springfox.documentation.builders.ApiInfoBuilder;
    import springfox.documentation.builders.PathSelectors;
    import springfox.documentation.builders.RequestHandlerSelectors;
    import springfox.documentation.service.ApiInfo;
    import springfox.documentation.service.ApiKey;
    import springfox.documentation.service.AuthorizationScope;
    import springfox.documentation.service.SecurityReference;
    import springfox.documentation.spi.DocumentationType;
    import springfox.documentation.spi.service.contexts.SecurityContext;
    import springfox.documentation.spring.web.plugins.Docket;
    import springfox.documentation.swagger.web.SecurityConfiguration;
    import springfox.documentation.swagger.web.SecurityConfigurationBuilder;
    import springfox.documentation.swagger2.annotations.EnableSwagger2;
    
    import com.google.common.base.Predicates;
    import com.google.common.collect.Lists;
    
    @Configuration
    @EnableSwagger2
    public class SwaggerConfig extends WebMvcConfigurerAdapter {
    
        @SuppressWarnings("unchecked")
        @Bean
        public Docket swaggerPlugin() {
        return new Docket(DocumentationType.SWAGGER_2)
            .select()
            .paths(PathSelectors.any())
            .apis(Predicates.or(RequestHandlerSelectors
                .basePackage("**controller package 1**"),
                RequestHandlerSelectors
                    .basePackage("**controller package 2**")))
            .build().directModelSubstitute(LocalDate.class, String.class)
            .genericModelSubstitutes(ResponseEntity.class)
            .apiInfo(apiInfo())
            .securitySchemes(Lists.newArrayList(apiKey()))
            .securityContexts(Arrays.asList(securityContext()));
        }
    
        private ApiInfo apiInfo() {
        return new ApiInfoBuilder().title("**Comment**")
            .description("**Comment**")
            .termsOfServiceUrl("**Comment**")
            .contact("**Comment**")
            .license("Apache License Version 2.0")
            .licenseUrl("**Comment**").version("0.0.1")
            .build();
        }
    
        @Bean
        public SecurityConfiguration security() {
        return SecurityConfigurationBuilder.builder().scopeSeparator(",")
            .additionalQueryStringParams(null)
            .useBasicAuthenticationWithAccessCodeGrant(false).build();
        }
    
        @Override
        public void addResourceHandlers(final ResourceHandlerRegistry registry) {
        registry.addResourceHandler("swagger-ui.html").addResourceLocations(
            "classpath:/META-INF/resources/");
        registry.addResourceHandler("/webjars/**").addResourceLocations(
            "classpath:/META-INF/resources/webjars/");
        }
    
        private ApiKey apiKey() {
        return new ApiKey("apiKey", "Authorization", "header");
        }
    
        private SecurityContext securityContext() {
        return SecurityContext.builder().securityReferences(defaultAuth())
            .forPaths(PathSelectors.any()).build();
        }
    
        private List<SecurityReference> defaultAuth() {
        AuthorizationScope authorizationScope = new AuthorizationScope(
            "global", "accessEverything");
        AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
        authorizationScopes[0] = authorizationScope;
        return Arrays.asList(new SecurityReference("apiKey",
            authorizationScopes));
        }
    
    }
    

    Reference - this github issue answer by JotaroJewstar

    0 讨论(0)
  • 2021-02-08 06:10

    The below solution worked for me in swagger 2.8.0 version.

    Add the below code in your Docket configuration

    @Bean
        public Docket api() {
            return new Docket(DocumentationType.SWAGGER_2)
                    .securitySchemes(Collections.singletonList(new ApiKey("JWT", "Authorization", "header")))
                    .securityContexts(Collections.singletonList(
                            SecurityContext.builder()
                                    .securityReferences(
                                            Collections.singletonList(SecurityReference.builder()
                                                    .reference("JWT")
                                                    .scopes(new AuthorizationScope[0])
                                                    .build()
                                            )
                                    )
                                    .build())
                    )
                    .select()
                    .apis(RequestHandlerSelectors
                            .basePackage("com.test.controller"))
                    .paths(PathSelectors.regex("/.*"))
                    .build().apiInfo(apiEndPointsInfo());
        }
    

    In the text box after clicking Authorize button in the swagger UI, type Bearer "XXXXXXXX(Token)"

    0 讨论(0)
  • 2021-02-08 06:12

    A simple workaround is to type Bearer than paste the token after it. You will end up with a text box that contains:

    Bearer <token>
    

    I wish there was a more automated way. But for now, it appears as though what goes in the text box simple get's pasted into the value section of a given header entry. I suppose the reason the prefix Bearer does not get injected automatically is because then Swagger would be quite opinionated about which sort of authentication its users used!

    @Configuration
    @EnableSwagger2
    class SwaggerConfig {
    
        @Bean
        Docket api() {
    
            return new Docket(DocumentationType.SWAGGER_2)
                    .select()
                    .apis(RequestHandlerSelectors.any())
                    .paths(Predicates.not(PathSelectors.regex("/error.*")))
                    .build()
                    .securitySchemes(securitySchemes())
        }
    
        private static ArrayList<? extends SecurityScheme> securitySchemes() {
    
            return [new ApiKey("Bearer", "Authorization", "header")]
        }
    }
    

    The REST endpoint method:

    @GetMapping("/count")
    @ApiOperation(value = "Count the number of entities associated with resource name. This operation does not requires any role." , authorizations = [@Authorization(value = "Bearer")])
    def count() {
    
        count(service)
    }
    

    The curl command before logging in:

    curl -X GET "http://localhost:8080/category/count" -H "accept: */*"
    

    Response:

    {
      "timestamp": "2018-10-29T15:13:02.388+0000",
      "status": 401,
      "error": "Unauthorized",
      "message": "Unauthorized",
      "path": "/category/count"
    }
    

    The curl command after logging in:

    curl -X GET "http://localhost:8080/category/count" -H "accept: */*" -H "Authorization: Bearer eyJhbGciOiJIUzUxMiJ9..."
    

    Response:

    {
      "message": "There are 0 entities",
      "count": 0
    }
    

    Note: My code is in Groovy, I am sure you can translate if you are using standard Java.

    0 讨论(0)
  • 2021-02-08 06:19

    I used springfox-swagger2 version-2.9.2 with below configuration and it works fine to pass JWT token via swagger-ui.

    private ApiKey apiKey() {    
        return new ApiKey("apiKey", Authorization, "header"); 
    }
    
    @Bean
    public Docket api() {
        return new Docket(DocumentationType.SWAGGER_2).select()
           .apis(RequestHandlerSelectors.basePackage("com.mycompany.dept.controller"))
           .paths(PathSelectors.any())
           .build().apiInfo(metaData()).securitySchemes(Lists.newArrayList(apiKey()));
    }
    

    And in controller we need to use @ApiOperation (value = "Get dummy by id.", authorizations = { @Authorization(value="apiKey") })

    Please refer to https://github.com/springfox/springfox/issues/2194

    0 讨论(0)
  • 2021-02-08 06:26

    The solution that worked for me with swagger versión 2.9.2 is the following:

    package com.example.springsocial;
    
    import java.util.Arrays;
    import java.util.Collections;
    import java.util.List;
    
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.security.core.annotation.AuthenticationPrincipal;
    import com.google.common.base.Predicates;
    import com.google.common.collect.Lists;
    
    import springfox.documentation.builders.PathSelectors;
    import springfox.documentation.builders.RequestHandlerSelectors;
    import springfox.documentation.service.ApiKey;
    import springfox.documentation.service.AuthorizationScope;
    import springfox.documentation.service.SecurityReference;
    import springfox.documentation.spi.DocumentationType;
    import springfox.documentation.spi.service.contexts.SecurityContext;
    import springfox.documentation.spring.web.plugins.Docket;
    import springfox.documentation.swagger2.annotations.EnableSwagger2;
    
    @Configuration
    @EnableSwagger2
    public class SwaggerConfiguration   {
    
        @Bean
        public Docket docket() {
            return new Docket(DocumentationType.SWAGGER_2)
                        .ignoredParameterTypes(AuthenticationPrincipal.class)
                        .select()
                        .apis(Predicates.not(RequestHandlerSelectors.basePackage("org.springframework.boot")))
                        .paths(PathSelectors.any()).build()
                        .securitySchemes(Lists.newArrayList(apiKey()))
                        .securityContexts(Arrays.asList(securityContext()));
    
        }
    
        private ApiKey apiKey() {
            return new ApiKey("apiKey", "Authorization", "header");
        }
    
        private SecurityContext securityContext() {
            return SecurityContext.builder().securityReferences(defaultAuth())
                .forPaths(PathSelectors.any()).build();
        }
    
        private List<SecurityReference> defaultAuth() {
            AuthorizationScope authorizationScope = new AuthorizationScope(
                "global", "accessEverything");
            AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
            authorizationScopes[0] = authorizationScope;
            return Arrays.asList(new SecurityReference("apiKey",
                authorizationScopes));
            }
    }
    

    POM.XML

    <!-- SWAGGER  -->
            <dependency>
                <groupId>io.springfox</groupId>
                <artifactId>springfox-swagger2</artifactId>
                <version>2.9.2</version>
            </dependency>
            <dependency>
                <groupId>io.springfox</groupId>
                <artifactId>springfox-swagger-ui</artifactId>
                <version>2.9.2</version>
            </dependency>
            <dependency>
                <groupId>io.springfox</groupId>
                <artifactId>springfox-bean-validators</artifactId>
                <version>2.9.2</version>
            </dependency>
    

    SecurityConfig.JAVA

    package com.example.springsocial.config;
    
    import com.example.springsocial.security.*;
    import com.example.springsocial.security.oauth2.CustomOAuth2UserService;
    import com.example.springsocial.security.oauth2.HttpCookieOAuth2AuthorizationRequestRepository;
    import com.example.springsocial.security.oauth2.OAuth2AuthenticationFailureHandler;
    import com.example.springsocial.security.oauth2.OAuth2AuthenticationSuccessHandler;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.security.authentication.AuthenticationManager;
    import org.springframework.security.config.BeanIds;
    import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
    import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
    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.crypto.password.PasswordEncoder;
    import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
    
    @Configuration
    @EnableWebSecurity
    @EnableGlobalMethodSecurity(
            securedEnabled = true,
            jsr250Enabled = true,
            prePostEnabled = true
    )
    public class SecurityConfig extends WebSecurityConfigurerAdapter {
    
        @Autowired
        private CustomUserDetailsService customUserDetailsService;
    
        @Autowired
        private CustomOAuth2UserService customOAuth2UserService;
    
        @Autowired
        private OAuth2AuthenticationSuccessHandler oAuth2AuthenticationSuccessHandler;
    
        @Autowired
        private OAuth2AuthenticationFailureHandler oAuth2AuthenticationFailureHandler;
    
        @Autowired
        private HttpCookieOAuth2AuthorizationRequestRepository httpCookieOAuth2AuthorizationRequestRepository;
    
        @Bean
        public TokenAuthenticationFilter tokenAuthenticationFilter() {
            return new TokenAuthenticationFilter();
        }
    
        /*
          By default, Spring OAuth2 uses HttpSessionOAuth2AuthorizationRequestRepository to save
          the authorization request. But, since our service is stateless, we can't save it in
          the session. We'll save the request in a Base64 encoded cookie instead.
        */
        @Bean
        public HttpCookieOAuth2AuthorizationRequestRepository cookieAuthorizationRequestRepository() {
            return new HttpCookieOAuth2AuthorizationRequestRepository();
        }
    
        @Override
        public void configure(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception {
            authenticationManagerBuilder
                    .userDetailsService(customUserDetailsService)
                    .passwordEncoder(passwordEncoder());
        }
    
        @Bean
        public PasswordEncoder passwordEncoder() {
            return new BCryptPasswordEncoder();
        }
    
    
        @Bean(BeanIds.AUTHENTICATION_MANAGER)
        @Override
        public AuthenticationManager authenticationManagerBean() throws Exception {
            return super.authenticationManagerBean();
        }
    
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http
                    .cors()
                        .and()
                    .sessionManagement()
                        .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                        .and()
                    .csrf()
                        .disable()
                    .formLogin()
                        .disable()
                    .httpBasic()
                        .disable()
                    .exceptionHandling()
                        .authenticationEntryPoint(new RestAuthenticationEntryPoint())
                        .and()
                    .authorizeRequests()
                        .antMatchers("/",
                            "/error",
                            "/favicon.ico",
                            "/**/*.png",
                            "/**/*.gif",
                            "/**/*.svg",
                            "/**/*.jpg",
                            "/**/*.html",
                            "/**/*.css",
                            "/**/*.js",
                            // swagger
                            "/swagger-ui.html**", "/swagger-resources/**",
                            "/v2/api-docs**", "/webjars/**"
                             )
                            .permitAll()
                        .antMatchers("/auth/**", "/oauth2/**")
                            .permitAll()
                        .anyRequest()
                            .authenticated()
                        .and()
                    .oauth2Login()
                        .authorizationEndpoint()
                            .baseUri("/oauth2/authorize")
                            .authorizationRequestRepository(cookieAuthorizationRequestRepository())
                            .and()
                        .redirectionEndpoint()
                            .baseUri("/oauth2/callback/*")
                            .and()
                        .userInfoEndpoint()
                            .userService(customOAuth2UserService)
                            .and()
                        .successHandler(oAuth2AuthenticationSuccessHandler)
                        .failureHandler(oAuth2AuthenticationFailureHandler);
    
            // Add our custom Token based authentication filter
            http.addFilterBefore(tokenAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
        }
    
        @Override
        public void configure(WebSecurity web) throws Exception {
            web.ignoring().antMatchers("/common/**", "/v2/api-docs", "/configuration/ui", "/swagger-resources",
                    "/configuration/security", "/swagger-ui.html", "/webjars/**");
        }
    
    }
    
    0 讨论(0)
  • 2021-02-08 06:27

    I am using latest version of springfox(right now it's 3.0.0), and you can use specific bearer auth with HttpAuthenticationScheme instead of ApiKey:

    HttpAuthenticationScheme
        .JWT_BEARER_BUILDER
        .name("JWT")
        .build()
    
    0 讨论(0)
提交回复
热议问题