代码之家  ›  专栏  ›  技术社区  ›  puelo

spring+graphql-可选授权

  •  1
  • puelo  · 技术社区  · 8 年前

    我正在使用 Spring Boot Starter GraphQL Java Tools 在我的Spring应用程序中使用graphql。只要我授权graphql端点,它就与我的授权过滤器一起工作得很好。现在我想向公众开放某些突变或疑问(因此不需要授权),这就是我绊倒的地方。如何打开graphql端点,但仍然能够使用 @PreAuthorize

    这是我的配置:

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        log.debug("configureHttpSecurity");
    
        // Only authorize the request if it is NOT in the permitAllEndpoints AND matches API_ROOT_URL OR
        // MESSAGING_ROOT_URL
        List<RequestMatcher> requestMatchers = new ArrayList<>();
        requestMatchers.add(new SkipPathRequestMatcher(permitAllEndpointList, API_ROOT_URL));
        requestMatchers.add(new AntPathRequestMatcher(MESSAGING_ROOT_URL));
        OrRequestMatcher apiMatcher = new OrRequestMatcher(requestMatchers);
    
        http.csrf().disable()
                    .sessionManagement()
                    .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
                    .authorizeRequests()
                    .antMatchers(permitAllEndpointList.toArray(new String[0]))
                    .permitAll()
                .and()
                    .authorizeRequests()
                    .antMatchers(API_ROOT_URL, MESSAGING_ROOT_URL)
                    .authenticated()
                .and()
                    .addFilterBefore(new CustomCorsFilter(),
                            UsernamePasswordAuthenticationFilter.class)
                    .addFilterBefore(new AuthenticationFilter(authenticationManager()),
                            UsernamePasswordAuthenticationFilter.class)
                    .addFilterBefore(new AuthorizationFilter(apiMatcher),
                            UsernamePasswordAuthenticationFilter.class);
    }
    

    这个 apiMatcher 是打开某些REST端点。 这是我的 AuthorizationFilter :

    @Override
    public Authentication attemptAuthentication(HttpServletRequest httpServletRequest,
                                                HttpServletResponse httpServletResponse)
            throws AuthenticationException, IOException, ServletException {
        try {
            String authorization = httpServletRequest.getHeader("Authorization");
            if (authorization != null && authorization.startsWith("Bearer ")) {
                return getAuthentication(authorization.replace("Bearer ", ""));
            }
        } catch (ExecutionException e) {
            httpServletResponse.sendError(HttpServletResponse.SC_FORBIDDEN,"The provided token was either not valid or is already expired!");
            return null;
        } catch (IOException | InterruptedException e) {
            httpServletResponse.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,"There was a problem verifying the supplied token!");
            return null;
        }
        httpServletResponse.sendError(HttpServletResponse.SC_FORBIDDEN, "Unauthorized");
        return null;
    }
    

    如果我在结束时不发送错误 attemptAuthentication 我可以访问不应该打开的REST端点。另外,如果我只允许graphql端点,那么不会发生任何授权,因此 @预授权 即使我提供了有效的JWT,也会失败。 可能是我的方法已经错了。如果是这样的话,请告诉我。

    1 回复  |  直到 8 年前
        1
  •  0
  •   puelo    8 年前

    我通过使用两个安全配置解决了这个问题。一个用于我的RESTAPI,它强制认证/授权。另一个有一个可选的授权过滤器,它只在令牌存在时使用它。 现在唯一的缺点是,所有的查询和变异在默认情况下都向公众开放,并且需要 @PreAuthorize 要关闭的注释。