2016-12-14 107 views
9

我正在使用keycloak來確保我的休息服務。我指的是給出的教程here。我創造了休息和前端。現在,當我在後端添加keycloak時,當我的前端進行api調用時,出現CORS錯誤。keycloak CORS過濾器彈簧靴

春季啓動

Application.java文件看起來是我打電話

@RestController 
public class SampleController {  
    @RequestMapping(value ="/api/getSample",method=RequestMethod.GET) 
    public string home() { 
     return new string("demo"); 
    }   
} 
在application.properties文件看起來像

keycloak.realm = demo 
keycloak.auth-server-url = http://localhost:8080/auth 
keycloak.ssl-required = external 
keycloak.resource = tutorial-backend 
keycloak.bearer-only = true 
keycloak.credentials.secret = 123123-1231231-123123-1231 
keycloak.cors = true 
keycloak.securityConstraints[0].securityCollections[0].name = spring secured api 
keycloak.securityConstraints[0].securityCollections[0].authRoles[0] = admin 
keycloak.securityConstraints[0].securityCollections[0].authRoles[1] = user 
keycloak.securityConstraints[0].securityCollections[0].patterns[0] = /api/* 

樣本REST API像

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

    @Bean 
    public WebMvcConfigurer corsConfiguration() { 
     return new WebMvcConfigurerAdapter() { 
      @Override 
      public void addCorsMappings(CorsRegistry registry) { 
       registry.addMapping("/api/*") 
         .allowedMethods(HttpMethod.GET.toString(), HttpMethod.POST.toString(), 
           HttpMethod.PUT.toString(), HttpMethod.DELETE.toString(), HttpMethod.OPTIONS.toString()) 
         .allowedOrigins("*"); 
      } 
     }; 
    } 
} 

的keycloak性質

前端keycloak.json屬性包括

{ 
    "realm": "demo", 
    "auth-server-url": "http://localhost:8080/auth", 
    "ssl-required": "external", 
    "resource": "tutorial-frontend", 
    "public-client": true 
} 

的CORS錯誤,我得到

XMLHttpRequest cannot load http://localhost:8090/api/getSample. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:9000' is therefore not allowed access. The response had HTTP status code 401. 
+1

你可能更喜歡問一個具體的問題。否則,您可能會得到對您而言無效的解決方案。 – Alexander

+0

你能提供整個堆棧跟蹤嗎? –

+0

服務器端沒有錯誤。因此沒有堆棧跟蹤。當我的angularJS應用程序讓剩下的電話打到客戶端時出錯,我在瀏覽器控制檯 – krs8888

回答

0

當你的客戶端發送認證頭,你不能使用 allowedOrigins( 「*」)。您必須配置特定的原始URL。

+1

這是行不通的。我將allowedOrigins從我的客戶端運行的位置更改爲URL。在我的項目中,它運行在localhost:9000上。即使改變後,我仍然得到錯誤 – krs8888

2

嘗試像我的例子一樣創建您的CORS bean。我最近經歷了同樣的事情(讓CORS工作),這是一場噩夢,因爲SpringBoot CORS支持目前不像MVC CORS那樣強壯或直接。

@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; 
} 

這是我將它設置爲接受任何來源的應用範圍,但如果你改變了幾個參數,你應該能夠複製你想要什麼。即。如果您只想添加您提到的方法,請鏈接一些addAllowedMethod()。允許的來源將是相同的,然後您的addMapping("/api/*")將成爲source.registerCorsConfiguration("/api/*", config);

編輯:

Spring Data Rest and Cors

看看這個。塞巴斯蒂安在春季的工程團隊,所以這與你要獲得正式答案一樣好。

+0

@ krs8888讓我知道這是否適合你。 –

+0

確定我會讓你知道,當我嘗試一次,我從下週假期回來 – krs8888

+0

更改我的豆,你已發佈的東西沒有工作。我覺得生病嘗試使用彈簧MVC和不使用彈簧啓動 – krs8888

1

我沒有權限訪問代碼示例,但根據您所包含的代碼配置,看起來像缺少配置會導致Spring排除CORS標頭。 J. West的迴應類似於我在Spring和CORS中遇到的最近的問題,但是我會告誡你注意一下spring實例引用哪個實現,因爲有兩個。 Spring SecuritySpring MVC Annotations。這兩個實現都是相互獨立工作的,不能組合。

當您按原樣使用基於過濾器的方法(甚至是淡化)時,關鍵是將允許憑據設置爲true,以便瀏覽器通過域發送身份驗證標頭。我還建議使用上面提出的完整的代碼方法,因爲這將允許您創建更多可配置的Web應用程序,以通過屬性注入或服務註冊表跨多個域或環境部署。

+0

註釋的好點。我編輯了我的答案,以包含一個類似Spring問題的工程師所關注的問題的鏈接。如果你有同樣的問題,我猜你在某個時候遇到了它。 –

1

Access-Control-Allow-Origin報頭應該由服務器應用程序設置,請求報頭中提供的Origin請求向服務器應用程序提供。通常,瀏覽器在請求中設置Origin標頭,只要它們檢測到正在發起的跨源請求。並且他們希望Access-Control-Allow-Origin標題響應於允許它。

現在,對於keycloak,我掙扎於同樣的問題。看看this,似乎keycloak不會在錯誤響應的情況下添加標頭Access-Control-Allow-Origin。但是,對於我來說,即使在成功響應的情況下,也不會在響應中添加此標頭。

調查了代碼並添加了斷點,我注意到即使傳遞並且因此CORS未添加訪問控制響應標頭,客戶端對象的webOrigin也沒有從Origin標頭獲得填充。

我能得到它的工作僅由CORS建立呼叫之前添加以下代碼行:

client.addWebOrigin(headers.getRequestHeader("Origin").get(0)); 

前:

Cors.add(request, Response.ok(res, MediaType.APPLICATION_JSON_TYPE)).auth().allowedOrigins(client).allowedMethods("POST").exposedHeaders(Cors.ACCESS_CONTROL_ALLOW_METHODS).build(); 

一旦我建這個變化的代碼,啓動服務器,我開始獲得三個訪問控制響應標頭:

Access-Control-Expose-Headers: Access-Control-Allow-Methods 
Access-Control-Allow-Origin: http://localhost:9000 
Access-Control-Allow-Credentials: true 

我是使用客戶端憑證授予類型;因此我只在buildClientCredentialsGrantTokenEndpoint.java#L473處添加它。

我仍然需要做更多的代碼潛水才能確定它是一個成功響應的錯誤,並且找到一個更好的地方在keycloak代碼中設置客戶端對象(比如客戶端對象正在建造)

歡迎您試試看。

更新:
我把它拿回來。我使用根URL作爲http://localhost:9000(這是我的前端應用程序端口)重新註冊了我的客戶端,並且我開始獲得正確的訪問控制響應標頭。希望這可以幫助你。