봄 부팅 OAuth를 항상 리디렉션에 HTTP (IBM 클라우드 CF + 봄 부팅 2)

에릭 스완슨 :

IBM 클라우드 CF 자바 Buildpack에 봄 부팅 OAuth를 사용 2 ...

https://github.com/ericis/oauth-cf-https-issue

* 나는 아래의 모든 조합을 시도했다.

으로 이 구성, 응용 프로그램은 OAuth를 리디렉션 전략에 전송 리디렉션의 무한 루프에 갇혀있다 http다음이 구성에 보냅니다 https.

http.requiresChannel().anyRequest().requiresSecure()

없이 이 구성, 사용자가 HTTP를 통해 로그인 할 수 있습니다 (바람직하지 않은).

전체 설정 :

http.
  requiresChannel().anyRequest().requiresSecure().
  authorizeRequests().
    // allow access to...
    antMatchers("favicon.ico", "/login", "/loginFailure", "/oauth2/authorization/ghe")
    .permitAll().anyRequest().authenticated().and().oauth2Login().
    // Codify "spring.security.oauth2.client.registration/.provider"
    clientRegistrationRepository(this.clientRegistrationRepository()).
    // setup OAuth2 client service to use clientRegistrationRepository
    authorizedClientService(this.authorizedClientService()).
    successHandler(this.successHandler()).
    // customize login pages
    loginPage("/login").failureUrl("/loginFailure").
    userInfoEndpoint().
      // customize the principal
      userService(this.userService());

나는 또한 시도했다 :

  1. 사용에 서버 구성 https

    server:
      useForwardHeaders: true
      tomcat:
        protocolHeader: x-forwarded-proto
    
  2. 서블릿 필터

    import java.io.IOException;
    
    import javax.servlet.Filter;
    import javax.servlet.FilterChain;
    import javax.servlet.FilterConfig;
    import javax.servlet.ServletException;
    import javax.servlet.ServletRequest;
    import javax.servlet.ServletResponse;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.stereotype.Component;
    
    @Component
    public class HttpToHttpsFilter implements Filter {
    
      private static final Logger log = LoggerFactory.getLogger(HttpToHttpsFilter.class);
    
      private static final String HTTP = "http";
      private static final String SCHEME_HTTP = "http://";
      private static final String SCHEME_HTTPS = "https://";
      private static final String LOCAL_ID = "0:0:0:0:0:0:0:1";
      private static final String LOCALHOST = "localhost";
    
      @Value("${local.ip}")
      private String localIp;
    
      public HttpToHttpsFilter() {
        // Sonar
      }
    
      @Override
      public void doFilter(final ServletRequest req, final ServletResponse res, final FilterChain chain)
          throws IOException, ServletException {
    
        final HttpServletRequest request = (HttpServletRequest) req;
    
        final HttpServletResponse response = (HttpServletResponse) res;
    
        // http, not localhost, not localhost ipv6, not local IP
        if (HTTP.equals(request.getScheme()) && 
            !LOCALHOST.equals(request.getRemoteHost()) && 
            !LOCAL_ID.equals(request.getRemoteHost()) && 
            (this.localIp != null && !this.localIp.equals(request.getRemoteHost()))) {
    
          final String query = request.getQueryString();
    
          String oldLocation = request.getRequestURL().toString();
    
          if (query != null) {
            oldLocation += "?" + query;
          }
    
          final String newLocation = oldLocation.replaceFirst(SCHEME_HTTP, SCHEME_HTTPS);
    
          try {
    
            log.info("HTTP redirect from {} to {} ", oldLocation, newLocation);
    
            response.sendRedirect(newLocation);
    
          } catch (IOException e) {
            log.error("Cannot redirect to {} {} ", newLocation, e);
          }
        } else {
          chain.doFilter(req, res);
        }
      }
    
      @Override
      public void destroy() {
        // Sonar
      }
    
      @Override
      public void init(FilterConfig arg0) throws ServletException {
        // Sonar
      }
    }
    

종속성

dependencies {

    //
    // BASICS

    // health and monitoring
    // compile('org.springframework.boot:spring-boot-starter-actuator')

    // security
    compile('org.springframework.boot:spring-boot-starter-security')

    // configuration
    compile('org.springframework.boot:spring-boot-configuration-processor')

  //
  // WEB

  // web
  compile('org.springframework.boot:spring-boot-starter-web')

  // thymeleaf view render
  compile('org.springframework.boot:spring-boot-starter-thymeleaf')

  // thymeleaf security extras
  compile('org.thymeleaf.extras:thymeleaf-extras-springsecurity4')

  //
  // OAUTH

  // OAuth client
  compile('org.springframework.security:spring-security-oauth2-client')

  // OAuth lib
  compile('org.springframework.security:spring-security-oauth2-jose')

  // OAuth config
  compile('org.springframework.security.oauth.boot:spring-security-oauth2-autoconfigure:2.0.0.RELEASE')

  //
  // CLOUD

  // cloud connectors (e.g. vcaps)
  compile('org.springframework.boot:spring-boot-starter-cloud-connectors')

    //
    // TOOLS

    runtime('org.springframework.boot:spring-boot-devtools')

    //
    // TEST

    // test
    testCompile('org.springframework.boot:spring-boot-starter-test')

    // security test
    testCompile('org.springframework.security:spring-security-test')
}
에릭 스완슨 :

이 해결되었습니다. 이 관련된 문제에 대한 세부 사항은에서 찾을 수 있습니다 https://github.com/spring-projects/spring-security/issues/5535#issuecomment-407413944

지금 노력하고 예제 프로젝트 : https://github.com/ericis/oauth-cf-https-issue

짧은 대답 :

응용 프로그램은 명시 적 프록시 헤더를 인식하도록 구성해야합니다. 나는 구성을 시도했지만 궁극적으로의 인스턴스를 사용해야했다 ForwardedHeaderFilter봄에 비교적 최근에 추가 된 클래스를.

@Bean
FilterRegistrationBean<ForwardedHeaderFilter> forwardedHeaderFilter() {

    final FilterRegistrationBean<ForwardedHeaderFilter> filterRegistrationBean = new FilterRegistrationBean<ForwardedHeaderFilter>();

    filterRegistrationBean.setFilter(new ForwardedHeaderFilter());
    filterRegistrationBean.setOrder(Ordered.HIGHEST_PRECEDENCE);

    return filterRegistrationBean;
}

추천

출처http://43.154.161.224:23101/article/api/json?id=182949&siteId=1