2017-04-20 5 views
3

私は、auth2認証とreactjsで春のブート1.5以上のセキュリティを行っています。安心して使えるhttpクライアントを使ったhttp呼び出しの場合認証は完全に機能しており、リソースサーバーからデータに正常にアクセスしています。問題は、ログアウトコードが動作していないと私は、コンソール上で、このエラーを取得しています:スプリングセキュリティ+ oauth2 + reactjs +安心なhttpクライアント

POST http://localhost:8080/logout 403()

エラー:「禁断」 メッセージ:「無効なCSRFトークン 『NULL』の要求に発見されましたパラメータ '_csrf' またはヘッダ 'X-XSRF-TOKEN'。

私も自分のコードを共有しています。

1)ReactJsコード

handleLogout = (e) => { 
    client({ 
      method: 'POST', 
      path: '/logout', 
      headers: { 
       'Accept': 'application/json', 
       'Content-Type': 'application/json' 
      }}).then(response => { 
       console.log(response); 
    }); 
    } 

2)安らかHTTPクライアント

'use strict'; 

// client is custom code that configures rest.js to include support for HAL, URI Templates, 
// and other things. It also sets the default Accept request header to application/hal+json. 

// get the rest client 
var rest = require('rest'); 

// provides default values for the request object. default values can be provided for the method, path, params, headers, entity 
// If the value does not exist in the request already than the default value utilized 
var defaultRequest = require('rest/interceptor/defaultRequest'); 

// Converts request and response entities using MIME converter registry 
// Converters are looked up by the Content-Type header value. Content types without a converter default to plain text. 
var mime = require('rest/interceptor/mime'); 

// define the request URI by expanding the path as a URI template 
var uriTemplateInterceptor = require('./uriTemplateInterceptor'); 

// Marks the response as an error based on the status code 
// The errorCode interceptor will mark a request in error if the status code is equal or greater than the configured value. 
var errorCode = require('rest/interceptor/errorCode'); 
var csrf = require('rest/interceptor/csrf'); 
// A registry of converters for MIME types is provided. Each time a request or response entity needs to be encoded or 
// decoded, the 'Content-Type' is used to lookup a converter from the registry. 
// The converter is then used to serialize/deserialize the entity across the wire. 
var baseRegistry = require('rest/mime/registry'); 
var registry = baseRegistry.child(); 
registry.register('text/uri-list', require('./uriListConverter')); 
registry.register('application/hal+json', require('rest/mime/type/application/hal')); 

// wrap all the above interceptors in rest client 
// default interceptor provide Accept header value 'application/hal+json' if there is not accept header in request 
module.exports = rest 
     .wrap(mime, { registry: registry }) 
     .wrap(uriTemplateInterceptor) 
     .wrap(errorCode) 
     .wrap(csrf) 
     .wrap(defaultRequest, { headers: { 'Accept': 'application/hal+json' }}); 

3)クライアントアプリケーションのapplication.yml

debug: true 

spring: 
    aop: 
    proxy-target-class: true 


security: 
    user: 
    password: none 
    oauth2: 
    client: 
     access-token-uri: http://localhost:9999/uaa/oauth/token 
     user-authorization-uri: http://localhost:9999/uaa/oauth/authorize 
     client-id: acme 
     client-secret: acmesecret 
    resource: 
     user-info-uri: http://localhost:9999/uaa/user 
     jwt: 
     key-value: | 
      -----BEGIN PUBLIC KEY----- 
      MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAgnBn+WU3i6KarB6gYlg40ckBiWmtVEpYkggvHxow74T19oDyO2VRqyY9oaJ/cvnlsZgTOYAUjTECjL8Ww7F7NJZpxMPFviqbx/ZeIEoOvd7DOqK3P5RBtLsV5A8tjtfqYw/Th4YEmzY/XkxjHH+KMyhmkPO+/tp3eGmcMDJgH+LwA6yhDgCI4ztLqJYY73gX0pEDTPwVmo6g1+MW8x6Ctry3AWBZyULGt+I82xv+snqEriF4uzO6CP2ixPCnMfF1k4dqnRZ/V98hnSLclfMkchEnfKYg1CWgD+oCJo+kBuCiMqmeQBFFw908OyFKxL7Yw0KEkkySxpa4Ndu978yxEwIDAQAB 
      -----END PUBLIC KEY----- 

zuul: 
    routes: 
    resource: 
     path: /resource/** 
     url: http://localhost:9000/resource 
    user: 
     path: /user/** 
     url: http://localhost:9999/uaa/user 

logging: 
    level: 
    org.springframework.security: DEBUG 

4)認証サーバでCorsFilter構成

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

    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) { 

     System.out.println("*********** running doFilter method of CorsFilter of auth-server***********"); 
     HttpServletResponse response = (HttpServletResponse) res; 
     HttpServletRequest request = (HttpServletRequest) req; 
     response.addHeader("Access-Control-Allow-Origin", "*"); 
     response.addHeader("Access-Control-Allow-Methods", "POST, PUT, GET, OPTIONS, DELETE"); 
     response.addHeader("Access-Control-Allow-Headers", "x-auth-token, x-requested-with"); 
     response.addHeader("Access-Control-Max-Age", "3600"); 

     if (request.getMethod()!="OPTIONS") { 
      try { 
       chain.doFilter(req, res); 
      } catch (IOException e) { 
       e.printStackTrace(); 
      } catch (ServletException e) { 
       e.printStackTrace(); 
      } 
     } else { 
     } 
    } 

    public void init(FilterConfig filterConfig) {} 

    public void destroy() {} 

} 

5)認証サーバのAuthrorizationServerConfigurerAdapter

@Configuration 
@EnableAuthorizationServer 
public class OAuth2AuthorizationConfig extends AuthorizationServerConfigurerAdapter { 

    @Autowired 
    private AuthenticationManager authenticationManager; 

    @Bean 
    public @Autowired JwtAccessTokenConverter jwtAccessTokenConverter() throws Exception { 

     System.out.println("*********** running jwtAccessTokenConverter ***********"); 

     // Setting up a JWT token using JwtAccessTokenConverter. 
     JwtAccessTokenConverter converter = new JwtAccessTokenConverter(); 
     // JWT token signing key 
     KeyPair keyPair = new KeyStoreKeyFactory(
       new ClassPathResource("keystore.jks"), "suleman123".toCharArray()) 
       .getKeyPair("resourcekey"); 
     converter.setKeyPair(keyPair); 
     return converter; 
    } 


    @Override 
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception { 

     System.out.println("*********** running configure(ClientDetailsServiceConfigurer clients) ***********"); 

     clients.inMemory() 
       .withClient("acme") // registers a client with client Id 'acme' 
       .secret("acmesecret") // registers a client with password 'acmesecret' 
       .authorizedGrantTypes("authorization_code", "refresh_token", 
         "password") // We registered the client and authorized the “password“, “authorization_code” and “refresh_token” grant types 
       .scopes("openid") // scope to which the client is limited 
       .autoApprove(true); 
    } 

    /** 
    * 
    */ 
    @Override 
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) 
      throws Exception { 

     System.out.println("*********** running configure(AuthorizationServerEndpointsConfigurer endpoints) ***********"); 

     // we choose to inject an existing authentication manager from the spring container 
     // With this step we can share the authentication manager with the Basic authentication filter 
     endpoints.authenticationManager(authenticationManager) 
       .accessTokenConverter(jwtAccessTokenConverter()); 
    } 

    @Override 
    public void configure(AuthorizationServerSecurityConfigurer oauthServer) 
      throws Exception { 

     System.out.println("*********** running configure(AuthorizationServerSecurityConfigurer oauthServer) ***********"); 

     oauthServer.tokenKeyAccess("permitAll()").checkTokenAccess(
       "isAuthenticated()"); 
    } 
} 
+0

前に実行されるように、認証サーバーの私は今、私はクッキーからCSRFトークンを取得するために反応し、クッキーのライブラリを使用し、X-CSとして渡しています、このプロパティを追加しましたrf - 穏やかなhttpクライアントのトークンヘッダー。上記のエラーは消えましたが、今回はコンソールでいくつかのエラーが発生しています。 クロスオリジン要求がブロックされました:同じOriginポリシーでは、http:// localhost:9999/uaa/oauth/authorize?client_id = acme&redirect_uri = http:// localhost:8080/loginでリモートリソースの読み取りを許可していません。 ?logout&response_type = code&state = d6AV3G。 (理由:CORSプリフライトチャンネルが成功しなかった)。 クライアント({ 方法: 'POST'、 パス: 'ログアウト'、 ヘッダ '受け入れる' { : 'アプリケーション/ JSON'、 「のContent – Asif

+0

これが私の現在の安らかなHTTPクライアントログアウトコードです(XSRF-TOKEN ') }})。then(response = "application"、 "XSRF-TOKEN" > { console.log(応答); }); } – Asif

答えて

2

最後にこれが機能しました。私はそれを動作させるために行っている:

1)私がインストールされている私がインポートされている私のreactjsコードでライブラリ

npm install react-cookie --save 

2)「 - クッキーを反応させると、」ライブラリー・クッキーの反応と方法で私はどこ安心してhttpクライアントを使用してログアウト要求を生成する私はクッキーからCsrf-Tokenを取得し、リクエストヘッダとして送信しています。認証サーバの代わりに

handleLogout = (e) => { 

    client({ 
      method: 'POST', 
      path: 'logout', 
      headers: { 
       'Content-Type': 'application/x-www-form-urlencoded;charset=utf8', 
       'X-Requested-With': 'XMLHttpRequest', 
       'X-Csrf-Token': Cookie.load('XSRF-TOKEN') 
      } 
      }).then(response => { 
       this.setState({authenticated: false}); 
       console.log(response); 
    }); 
    } 

3)application.propertiesファイルで、今私は春CORSフィルターコード

@Configuration 
public class CorsFilterConfig { 

    @Bean 
    public FilterRegistrationBean corsFilter() { 
     UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); 
     CorsConfiguration config = new CorsConfiguration(); 
     config.setAllowCredentials(true); 
     config.addAllowedOrigin("*"); 
     config.addAllowedHeader("*"); 
     config.addAllowedMethod("*"); 
     source.registerCorsConfiguration("/**", config); 
     FilterRegistrationBean bean = new FilterRegistrationBean(new CorsFilter(source)); 
     bean.setOrder(0); 
     return bean; 
    } 
} 

4を使用しています、私は私の質問に言及している私のカスタムCORSフィルタクラスを、)を使用して、 CorsFilterがSpringSecurityFilterChain

security.filter-order=50 
関連する問題