2015-06-03 6 views
10

Поэтому у меня есть следующий сервер авторизации конденсируется из this example от Дейва SyerStandalone Spring OAuth2 JWT Авторизация сервер + CORS

@SpringBootApplication 
public class AuthserverApplication { 

    public static void main(String[] args) { 
      SpringApplication.run(AuthserverApplication.class, args); 
    } 

    /* added later 
    @Configuration 
    @Order(Ordered.HIGHEST_PRECEDENCE) 
    protected static class MyWebSecurity extends WebSecurityConfigurerAdapter { 

     @Override 
     protected void configure(HttpSecurity http) throws Exception { 
      http //.csrf().disable() 
       .authorizeRequests() 
       .antMatchers(HttpMethod.OPTIONS, "/oauth/token").permitAll(); 
     } 
    }*/ 

    @Configuration 
    @EnableAuthorizationServer 
    protected static class OAuth2AuthorizationConfig extends 
        AuthorizationServerConfigurerAdapter { 

      @Autowired 
      private AuthenticationManager authenticationManager; 

      @Bean 
      public JwtAccessTokenConverter jwtAccessTokenConverter() { 
        JwtAccessTokenConverter converter = new JwtAccessTokenConverter(); 
        KeyPair keyPair = new KeyStoreKeyFactory(
            new ClassPathResource("keystore.jks"), "foobar".toCharArray()) 
            .getKeyPair("test"); 
        converter.setKeyPair(keyPair); 
        return converter; 
      } 

      @Override 
      public void configure(ClientDetailsServiceConfigurer clients) throws Exception { 
        clients.inMemory() 
            .withClient("acme") 
            //.secret("acmesecret") 
            .authorizedGrantTypes(//"authorization_code", "refresh_token", 
                "password").scopes("openid"); 
      } 

      @Override 
      public void configure(AuthorizationServerEndpointsConfigurer endpoints) 
          throws Exception { 
        endpoints.authenticationManager(authenticationManager).accessTokenConverter(
            jwtAccessTokenConverter()); 
      } 

      @Override 
      public void configure(AuthorizationServerSecurityConfigurer oauthServer) 
          throws Exception { 
        oauthServer.tokenKeyAccess("permitAll()").checkTokenAccess(
            "isAuthenticated()"); 
      } 
    } 
} 

когда я запустить его и протестировать его с завитком

curl [email protected]:8110/oauth/token -d grant_type=password -d client_id=acme -d username=user -d password=password 

я получаю JWT как ответ, но как только я попытаюсь получить доступ к AuthServer из моего Frontend (Angular JS на другом порту), я получаю ошибку CORS. Не из-за отсутствия заголовков, а потому, что запрос OPTION отклонен и отсутствует учетные данные.

Request URL:http://localhost:8110/oauth/token 
Request Method:OPTIONS 
Status Code:401 Unauthorized 
WWW-Authenticate:Bearer realm="oauth", error="unauthorized", error_description="Full authentication is required to access this resource" 

Я уже знал, что я должен добавить CorsFilter и дополнительно нашли this post где я использовал фрагмент первого ответа, чтобы получить доступ к опциям запрос /oauth/token без полномочий:

@Order(-1) 
public class MyWebSecurity extends WebSecurityConfigurerAdapter { 
    @Override 
    protected void configure(HttpSecurity http) throws Exception { 
     http 
      .authorizeRequests() 
      .antMatchers(HttpMethod.OPTIONS, "/oauth/token").permitAll(); 
    } 
} 

После этого Я получил с завитком следующее сообщение об ошибке:

{"timestamp":1433370068120,"status":403,"error":"Forbidden","message":"Expected CSRF token not found. Has your session expired?","path":"/oauth/token"} 

Итак, чтобы сделать его простым, я просто добавил http.csrf().disable() к configure метод класса MyWebSecurity, который решает проблему с запросом OPTION, но поэтому запрос POST больше не работает, и я получаю There is no client authentication. Try adding an appropriate authentication filter. (также с завитком).

Я попытался выяснить, должен ли я каким-то образом подключить класс MyWebSecurity и AuthServer, но не повезло. Исходный пример (ссылка в начале) вводит также аутентификационныйManager, но это ничего не изменило для меня.

ответ

64

Нашел причину моей проблемы!

Мне просто нужно было закончить фильтр-цепочку и немедленно вернуть результат, если запрос OPTIONS обрабатывается CorsFilter!

SimpleCorsFilter.java

@Component 
@Order(Ordered.HIGHEST_PRECEDENCE) 
public class SimpleCorsFilter implements Filter { 

    public SimpleCorsFilter() { 
    } 

    @Override 
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { 
     HttpServletResponse response = (HttpServletResponse) res; 
     HttpServletRequest request = (HttpServletRequest) req; 
     response.setHeader("Access-Control-Allow-Origin", "*"); 
     response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE"); 
     response.setHeader("Access-Control-Max-Age", "3600"); 
     response.setHeader("Access-Control-Allow-Headers", "x-requested-with, authorization"); 

     if ("OPTIONS".equalsIgnoreCase(request.getMethod())) { 
      response.setStatus(HttpServletResponse.SC_OK); 
     } else { 
      chain.doFilter(req, res); 
     } 
    } 

    @Override 
    public void init(FilterConfig filterConfig) { 
    } 

    @Override 
    public void destroy() { 
    } 
} 

После того, что я мог игнорировать ОПЦИИ предполетной запрос в моем AuthServer = D

Так Сервер работает как в отрезала выше, и вы можете игнорировать блок комментария с MyWebSecurity класса в начале.

+2

В качестве альтернативы, вы можете использовать 'CorsFilter' обеспечены Spring Framework 4.2+ и Spring ботинке 1.3+, см мой [ответить здесь] (HTTP: // переполнение стека.com/a/31748398/1092077) для более подробной информации. –

+2

@ SébastienDeleuze CorsFilter Spring, по-видимому, выполняется после FilterChain по какой-либо причине и все еще приводит к несанкционированному использованию :( – froginvasion

+1

Вы пытались изменить порядок фильтров, как описано [здесь] (http://stackoverflow.com/a/26147788/1092077)? –

1

ну, вы правы! это решение, и он также работал для меня (я была такая же проблема)

Но позвольте мне sussgest использовать умную реализацию CORS фильтра для Java: http://software.dzhuvinov.com/cors-filter.html

Это очень комплексное решение для Java-приложений.

Собственно, вы можете видеть here как ваша точка решена.

+2

Spring Framework 4.2+ native 'CorsFilter', вероятно, является лучшей альтернативой, [см. этот ответ] (http://stackoverflow.com/a/31748398/1092077) для получения дополнительной информации. –

9

Я нашел решение, используя решение проблемы. Но у меня есть еще один способ описать решение:

@Configuration 
public class WebSecurityGlobalConfig extends WebSecurityConfigurerAdapter { 
     .... 
     @Override 
     public void configure(WebSecurity web) throws Exception { 
     web.ignoring() 
      .antMatchers(HttpMethod.OPTIONS); 
     } 
     ... 
} 
+0

какую версию вы используете? У меня, похоже, нет '.ignoring' в моей версии весенней безопасности. @Cyril – XPLOT1ON

+0

Это было сделано с помощью Spring 1.5.2-Release. Он все еще работает нормально с 1.5.9-Release. – Cyril

Смежные вопросы