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

KeyCloak(Spring引导)不验证RESTendpoint

谭成业
2023-03-14

我正在尝试使用开源用户管理服务,比如KeyClope。构建一个angularJs应用程序,该应用程序将向由KeyClope保护的RESTendpoint发送HTTP请求。我在后端使用spring boot。我能够调用endpoint并得到结果,这应该是不可能的,因为它会阻止来自未经授权来源的请求。

这是我遵循的两个链接

  1. 带角和Spring靴的钥匙斗篷

2.Github链接到KeyClope示例

由用户将调用的RESTendpoint组成的控制器。

@RequestMapping(value = "/api/getSample")
public test welcome() {
    return new test("sample");
}

@RequestMapping(value = "/check/test")
public test welcome2() {
    return new test("test");
}

使用CORS的Spring boot应用程序

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

    @Bean
    public FilterRegistrationBean corsFilter() {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        CorsConfiguration config = new CorsConfiguration();
        config.setAllowCredentials(true);
        config.addAllowedOrigin("*");
        config.addAllowedHeader("*");
        config.addAllowedMethod("*");
        source.registerCorsConfiguration("/api/*", config);

        FilterRegistrationBean bean = new FilterRegistrationBean(new CorsFilter(source));
        bean.setOrder(0);
        return bean;
    }
}

应用程序属性文件

server.port = 8090

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 = 111-1111-111-111
keycloak.use-resource-role-mappings = true
keycloak.cors= true

keycloak.securityConstraints[0].securityCollections[0].name = spring secured api
keycloak.securityConstraints[0].securityCollections[0].authRoles[0] = user
keycloak.securityConstraints[0].securityCollections[0].patterns[0] = /api

keycloak.securityConstraints[0].securityCollections[1].name = insecure stuff
keycloak.securityConstraints[0].securityCollections[1].authRoles[0] = user
keycloak.securityConstraints[0].securityCollections[1].patterns[0] = /check

有两个测试用例

>

  • 在没有登录的情况下进行REST调用。在这种情况下,我能够得到结果。这不应该是这样的,我应该被阻止(得到401错误)。

    登录时进行REST调用。我可以调用api/getSample,这是正确的行为。但是当我调用检查/测试时,我得到了XMLHttpRequest无法加载http://localhost:8090/check/test.对预检请求的响应没有通过改造权限检查:请求的资源上没有“访问控制允许源”标头。因此不允许访问源“http://localhost:9000”。响应有HTTP状态代码403。

  • 共有2个答案

    程景胜
    2023-03-14

    您还没有在pom.xml.中添加Spring Boot KeyCloak适配器依赖项

    对于2。您还没有为 /check配置CORS(仅为 /api)

     <dependency>
          <groupId>org.keycloak</groupId>
          <artifactId>keycloak-spring-boot-adapter</artifactId>
          <version>${keycloak.version}</version>
      </dependency>
    
    颛孙晗昱
    2023-03-14

    1)

    我不知道你的测试看起来怎么样,但是也许系统认为你还在登录?你可以尝试删除你的cookie,以确保没有保存访问令牌。

    另一个选项可能是Spring Boot无法识别KeyClope适配器,因此无法确保访问安全。您主要通过添加keydape-Spring Boot适配器keydape-tomcat8-Adapter依赖项来配置适配器(此处有更多详细信息)。

    2)

    看起来CORS配置不正确。您可以考虑这个实现的配置(这里有更多的细节):

    @Bean
    FilterRegistrationBean corsFilter(
            @Value("${tagit.origin:http://localhost:9000}") String origin) {
        return new FilterRegistrationBean(new Filter() {
            public void doFilter(ServletRequest req, ServletResponse res,
                                 FilterChain chain) throws IOException, ServletException {
                HttpServletRequest request = (HttpServletRequest) req;
                HttpServletResponse response = (HttpServletResponse) res;
                String method = request.getMethod();
                // this origin value could just as easily have come from a database
                response.setHeader("Access-Control-Allow-Origin", origin);
                response.setHeader("Access-Control-Allow-Methods",
                        "POST,GET,PUT,DELETE");
                response.setHeader("Access-Control-Max-Age", Long.toString(60 * 60));
                response.setHeader("Access-Control-Allow-Credentials", "true");
                response.setHeader(
                        "Access-Control-Allow-Headers",
                        "Origin,Accept,X-Requested-With,Content-Type,Access-Control-Request-Method,Access-Control-Request-Headers,Authorization");
                if ("OPTIONS".equals(method)) {
                    response.setStatus(HttpStatus.OK.value());
                }
                else {
                    chain.doFilter(req, res);
                }
            }
    
            public void init(FilterConfig filterConfig) {
            }
    
            public void destroy() {
            }
        });
    }
    
     类似资料:
    • 我有一个配置了Spring安全性的Spring启动应用程序。我已将登录请求重定向到我在 python 服务器上运行前端的 。现在,当我尝试将登录名发布到我的 springboot 应用程序时,它不起作用。即使我从邮递员那里尝试,它也说 错误。我怎样才能让它工作。如果我将其作为 html 放在同一个项目中,而不是从 python 服务器或邮递员中,它就可以从 /login 工作。有什么区别。 “消息

    • 我想对post请求主体密钥-值对中的一个进行身份验证,但我想在拦截器/过滤器的帮助下进行同样的验证。我该怎么做?

    • 我有一个令牌,它将从一个服务传递到我的Rest服务。我想使用Spring security根据公钥验证令牌(它托管在不同的服务器上)。我已经定义了安全配置类,它扩展了KeyDopperWebSecurity配置适配器,并且实现了httpSecurity和AuthenticationManager构建器。 我正在使用OncePerRequestFilter并从请求中获取承载令牌。 @组件公共类Jwt

    • 如何为两个数字的范围设置验证。我想将第一个数字的最大值设置为第二个数字的值,将第二个数字的最小值设置为第一个numb的值。这是我的js代码: 和超文本标记语言: 请帮忙谢谢

    • 是否可以声明性地在类的字段上指定验证约束,以便其中一些约束只适用于某些层(或者被某些层忽略)? 其中是JSR 303 anotation REST API层 此处不存在 null

    • JDK:1.80_131 Tomcat:8.0.27.0 Hibernate验证程序:6.0.7。最终下载的所有依赖项:Hibernate Validator 6 代码在,例外情况如下: 看起来使用了错误的jar文件,但我不知道是哪一个。