当前位置: 首页 > 知识库问答 >
问题:

使用ReactJS应用程序击中endpoint时出现Keycloak保护的Spring Boot应用程序CORS错误

於英朗
2023-03-14

我有一个ReactJS和Java Spring Boot应用程序,它们都受到KeyCloak11.0.2的保护。

Keycloak在8083端口,ReactJS在3000端口,Spring App在8085端口。如果我尝试使用下面提供的配置,我不能击中我的endpoint,我得到CORS错误。

火狐:

Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://localhost:8083/auth/realms/sorcerer_realm/protocol/openid-connect/auth?response_type=code&client_id=event_sorcerer&redirect_uri=http%3A%2F%2Flocalhost%3A8085%2Fsso%2Flogin&state=f52216b1-c235-4328-a2f9-d8448c3bf886&login=true&scope=openid. (Reason: CORS request did not succeed).
Access to XMLHttpRequest at 'http://localhost:8083/auth/realms/sorcerer_realm/protocol/openid-connect/auth?response_type=code&client_id=event_sorcerer&redirect_uri=http%3A%2F%2Flocalhost%3A8085%2Fsso%2Flogin&state=f57ffa9f-9679-4476-aa03-af86c3abb3c2&login=true&scope=openid' (redirected from 'http://localhost:8085/api/worker/create/product') from origin 'http://localhost:3000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.


xhr.js:184 GET http://localhost:8083/auth/realms/sorcerer_realm/protocol/openid-connect/auth?response_type=code&client_id=event_sorcerer&redirect_uri=http%3A%2F%2Flocalhost%3A8085%2Fsso%2Flogin&state=f57ffa9f-9679-4476-aa03-af86c3abb3c2&login=true&scope=openid net::ERR_FAILED
@KeycloakConfiguration
public class SecurityConfiguration extends KeycloakWebSecurityConfigurerAdapter {

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder authBuilder) throws Exception {
        final KeycloakAuthenticationProvider authProvider = keycloakAuthenticationProvider();
        
        authProvider.setGrantedAuthoritiesMapper(new SimpleAuthorityMapper());
        authBuilder.authenticationProvider(authProvider);
    }
    
    
    /**
     * Call superclass configure method and set the Keycloak configuration
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        super.configure(http);
        
        http
            .csrf().disable()
            .cors()
            .and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
            .and().anonymous()
            //.and().authorizeRequests().antMatchers("/**").permitAll()         //Uncomment for requests to be allowed!
            .and().authorizeRequests().antMatchers("/api/admin/**").hasRole("ADMIN")
            .and().authorizeRequests().antMatchers("/api/manager/**").hasAnyRole("MANAGER")
            .and().authorizeRequests().antMatchers("/api/worker/**").hasRole("WORKER")
            .anyRequest().authenticated();
    }

    /**
     * Setup Auth Strategy. Don't add prefixes and suffixes to role strings
     */
    @Override
    protected SessionAuthenticationStrategy sessionAuthenticationStrategy() {
        return new RegisterSessionAuthenticationStrategy(new SessionRegistryImpl());
    }
    
    /**
     * Don't use keycloak.json. Instead, use application.yml properties.
     * @return
     */
    @Bean
    public KeycloakSpringBootConfigResolver KeycloakConfigResolver() {
        return new KeycloakSpringBootConfigResolver();
    }
}
spring:
  jersey:
    type: filter


security: 
    oauth2: 
      resourceserver: 
        jwt: 
          issuer-uri: http://localhost:8083/auth/realms/sorcerer_realm/protocol/openid-connect/token
          jwk-set-uri: http://localhost:8083/auth/realms/sorcerer_realm/protocol/openid-connect/certs 


keycloak:
  realm: sorcerer_realm
  auth-server-url: http://localhost:8083/auth/
  ssl-required: external
  resource: event_sorcerer
  verify-token-audience: true
  credentials:
    secret-jwt:
      secret: d84611c9-af79-423b-b12c-bfa7fec23e85
  use-resource-role-mappings: true
  confidential-port: 0
const keycloakConfig = {
    "clientId": "event_sorcerer_frontend",
    "realm": "sorcerer_realm",
    "auth-server-url": "http://localhost:8083/auth/",
    "url": "http://localhost:8083/auth",
    "ssl-required": "external",
    "resource": "event_sorcerer",
    "public-client": true,
    "verify-token-audience": true,
    "use-resource-role-mappings": true,
    "confidential-port": 0
};

const keycloak = new Keycloak(keycloakConfig);

const initKeycloak = (onSuccessCallback, onFailureCallback) => {
    let success = false;

    timeoutWrapper(() => {
        if(!success){
            onFailureCallback();
        }
    });

    keycloak.init({
        onLoad: 'check-sso',
        silentCheckSsoRedirectUri: window.location.origin + '/silent-check-sso.html',
        pkceMethod: 'S256',

    }).then((isAuthenticated) => {
        success = true;
        if(isAuthenticated) {
            onSuccessCallback();
        } else {
            login();
        }
    });
}
export const Request = {
    configureAxiosDefault: () => {
        axios.defaults.baseURL = axiosDefaultConfiguration.baseUrl;
    },

    create: (data, endpoint, callback, errorCallback, finalCallback) => {
        axios.post(serverEndpoint + endpoint, {
            data: data,
            headers: {
                Authorization: `Bearer ${UserService.getToken()}`
            }
        })
        .then(response => Utility.isEmpty(callback) ?  defaultCallback(response) : callback(response))
        .catch(response => Utility.isEmpty(errorCallback) ? defaultErrorCallback(response) : errorCallback(response))
        .finally(response => {
            if(!Utility.isEmpty(finalCallback)) {
                finalCallback(response);
            }
        });
    },
}

以下是我的前端Keycloak配置。后端是相同的,只是访问类型是机密的,根/基url不同(不是3000而是8085):

以下是我的CORS配置bean:

@Configuration
public class CORSConfiguration {
    /**
     * Setup CORS
     * @return
     */
    @Bean
    public CorsConfigurationSource corsConfigurationSource() {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        CorsConfiguration config = new CorsConfiguration();
        
        config.setAllowCredentials(true);
        config.setAllowedOrigins(Arrays.asList("http://localhost:3000"));
        config.setAllowedMethods(Arrays.asList(CorsConfiguration.ALL));
        config.setAllowedHeaders(Arrays.asList(CorsConfiguration.ALL));
        config.setAllowCredentials(true);
        source.registerCorsConfiguration("/**", config);
        
        return source;
    }
}

最后,这是我的终点。URL解析为API/worker/create/product

@RestController
@RequestMapping(ControllerEndpointsPrefix.WORKER + "/create")
public class CreationController {
    @Autowired
    private UserAgregate userAgregate;

    @PostMapping("/product")
    public boolean createProduct(@RequestBody CreateProductCommand command) {
        return true;
    }
}

共有1个答案

孟振
2023-03-14

我已经设法解决了这个问题。问题不在服务器端,而在客户端

configureAxiosDefault: () => {
    axios.defaults.baseURL = axiosDefaultConfiguration.baseUrl;
    axios.defaults.headers.Authorization = `Bearer ${UserService.getToken()}`
},

create: (data, endpoint, callback, errorCallback, finalCallback) => {
        axios.post(serverEndpoint + endpoint, data)
        .then(response => Utility.isEmpty(callback) ?  defaultCallback(response) : callback(response))
        .catch(response => Utility.isEmpty(errorCallback) ? defaultErrorCallback(response) : errorCallback(response))
        .finally(response => {
            if(!Utility.isEmpty(finalCallback)) {
                finalCallback(response);
            }
        });
    },

服务器无法处理令牌,因为我将它作为JSON对象属性发送。这些变化使一切正常。

所以,CORS根本不是问题。问题是请求没有包含授权标头。

 类似资料:
  • 有人可以帮助我解决以下问题吗? 场景。我有一个运行在Azure虚拟机上的Windows服务。服务接收文件,以某种方式修改它们(我们假设它给Word文件添加了自定义属性)并使用MIP SDK用template ID保护它们。 问题。失败,但有以下异常: 出现一个或多个错误。ServiceDiscoveryHelper::GetServiceDetails-无法计算域:许可证域、标识和云endpoin

  • 我正在尝试使用我的ReactJs应用程序在Docker中运行(不使用express)来发出post/put/patch/delete请求,但我的请求被CORS阻止了。我的后端是一个Spring Boot服务,也运行在Docker中。 错误: 当我尝试直接打开它(通过URL)时,不会被识别。路由到它(通过NavBar)工作良好。 编辑:也许我的Spring配置错了?我使用的是这个全局示例,它可以很好

  • null 脚本'C:\src\flutter\packages\flutter_tools\gradle\flutter.gradle'行:838 出了什么问题: 任务“:app:CompileFlutterBuildreLease”执行失败。 null null 应用程序:Build.Gradle

  • 问题内容: 我已经使用基于标准的基于wildfly的Keycloak适配器的Keycloak保护了企业应用程序。我面临的问题是,其余的Web服务在被调用时需要知道当前登录的用户名。如何从Keycloak获取登录的用户信息? 我尝试使用,等等。但是没有一个能够提供所需的详细信息。 问题答案: 您从安全上下文中获取所有用户信息。 例: 为了传播安全上下文,您必须具有如下配置的安全域: JBoss /

  • 当我连续发布数据时,我会在C#应用程序上得到发布超时错误,一旦我重新启动应用程序,它会工作几个小时。[注意:由于php需要时间完成任务,所以新的请求都在等待中,它创建队列,等待时间超过2分钟,im出现超时错误]。 我们的两台服务器都使用了最大50%的CPU和RAM使用量 我检查了两个C#代码和PHP代码都工作良好,没有任何问题或bug 提前致谢哥们儿:)

  • 除了上面的命令之外,我还尝试了 “sudo pm2 start npm--branch_env=stage node_env=production port=80 node appserverstart.js” 请救命! ----错误详细信息---- AppServerStart.js -----附加信息----服务器:CentOS Linux version 7 core,npm版本:6.4.1