spring-security - 如何使用 Spring Security 和 OAuth2 保护 Apache Camel rest 端点

标签 spring-security spring-boot apache-camel

我正在使用配置了 SSO/OAuth2 安全性的 Spring Boot 应用程序。
身份验证适用于我的休息 Controller ,现在我需要使用休息端点保护我的 Apache Camel 路由。

据我了解,有几种方法可以做到:

  • 通过将身份验证处理器添加到我的路线
  • 通过向我的路线添加策略 (SpringSecurityAuthorizationPolicy)
  • 通过处理程序选项到 jetty端点

  • 我试图通过向我的休息端点添加新的身份验证处理器来做到这一点,但我坚持这个异常(exception):

    org.springframework.security.oauth2.common.exceptions.OAuth2Exception: No AuthenticationProvider found for org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken



    在调试期间我看到 org.springframework.security.authentication.ProviderManager.getProviders() 仅包含一个提供程序 匿名身份验证提供者 所以可能我必须注册适当的提供者...

    有人可以帮我找到解决这个问题的正确方法吗?
    @Configuration
    public class SecurityConfig extends WebSecurityConfigurerAdapter {
    
      protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable().authorizeRequests().anyRequest().permitAll();
      }
    
      @Configuration
      @EnableResourceServer
      protected static class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {
    
        @Value("${oauth2.token.endpoint}")
        private String tokenEndpoint;
    
        @Bean
        public ResourceServerTokenServices tokenService() {
          RemoteTokenServices tokenServices = new RemoteTokenServices();
          tokenServices.setClientId("clientId");
          tokenServices.setClientSecret("clientSecret");
          tokenServices.setCheckTokenEndpointUrl(tokenEndpoint);
          return tokenServices;
        }
    
        @Override
        public void configure(HttpSecurity http) throws Exception {
          http.authorizeRequests().anyRequest().authenticated();
        }
      }
    
    }
    
    @Configuration
    public class EmbeddedServerRoute {
      @Bean
      public RoutesBuilder embeddedServer() {
        return new RouteBuilder() {
          @Override
          public void configure() throws Exception {
            restConfiguration().component("jetty").port("8081").bindingMode(RestBindingMode.json);
          }
        };
      }
    }
    
    
    @Component
    public class RestTestRoute extends RouteBuilder {
    
      @Autowired
      private AuthProcessor authProcessor;
    
      @Override
      public void configure() throws Exception {
        from("rest:get:/test").process(authProcessor).to("mock:end").end();
      }
    }
    
    
    @Component
    public class AuthProcessor implements Processor {
    
      @Autowired
      private AuthenticationManager authenticationManager;
    
      private TokenExtractor tokenExtractor = new BearerTokenExtractor();
    
      private AuthenticationDetailsSource<HttpServletRequest, ?> authenticationDetailsSource = new OAuth2AuthenticationDetailsSource();
    
      @Override
      public void process(Exchange exchange) throws Exception {
        HttpServletRequest request = exchange.getIn().getBody(HttpServletRequest.class);
        Subject subject = new Subject();
        Authentication auth = getAuth(request);
        subject.getPrincipals().add(auth);
        exchange.getIn().setHeader(Exchange.AUTHENTICATION, subject);
      }
    
      private Authentication getAuth(HttpServletRequest request) throws OAuth2Exception {
        Authentication authentication = null;
        try {
          authentication = tokenExtractor.extract(request);
          if (authentication != null) {
            request.setAttribute(OAuth2AuthenticationDetails.ACCESS_TOKEN_VALUE, authentication.getPrincipal());
    
            if (authentication instanceof AbstractAuthenticationToken) {
              AbstractAuthenticationToken needsDetails = (AbstractAuthenticationToken) authentication;
              needsDetails.setDetails(authenticationDetailsSource.buildDetails(request));
            }
            return authenticationManager.authenticate(authentication);
          }
        } catch (Exception e) {
          throw new OAuth2Exception(e.getMessage());
        }
        throw new OAuth2Exception("Not Authorized to view resource");
      }
    
    }
    

    最佳答案

    作为最终解决方案,我决定使用 Spring Boot 嵌入式 servlet 容器而不是 Apache Camel rest 组件。所以它可以很容易地被 Spring Security 保护。这可以通过创建额外的 bean 来完成:

      @Bean
      public ServletRegistrationBean servletRegistrationBean() {
        SpringServerServlet serverServlet = new SpringServerServlet();
        ServletRegistrationBean regBean = new ServletRegistrationBean(serverServlet, "/camel/*");
        Map<String, String> params = new HashMap<>();
        params.put("org.restlet.component", "restletComponent");
        regBean.setInitParameters(params);
        return regBean;
      }
    
      @Bean
      public Component restletComponent() {
        return new Component();
      }
    
      @Bean
      public RestletComponent restletComponentService() {
        return new RestletComponent(restletComponent());
      }
    

    关于spring-security - 如何使用 Spring Security 和 OAuth2 保护 Apache Camel rest 端点,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38638480/

    相关文章:

    SpringBoot 使用高级休息客户端进行简单的分段文件上传(Chrome)

    java - Spring Boot JPA/JDBC 批处理 findById 有效,但 findOneByX 不起作用

    json - 如何捕获/显示后端返回的异常

    java - 使用带有嵌入式 Jetty 的 Spring-Boot 在 Camel rest-component 上配置 SSL

    java - 获取特定用户的所有权限

    java - 同一项目中的 Spring Boot Basic Authentication 和 OAuth2?

    html - 使用 "if"条件的 thymeleaf 的 Spring 安全性

    spring-boot - Spring Boot 3 BeanCreationException : Error creating bean with name authorizationEndpoint - ClassNotFoundException: javax. servlet.ServletException

    java - ActiveMQ 上的重复消息

    java - 如何让Intellij自动解析自定义bean?