Spring security 如何使用Spring安全性和OAuth2保护Apache Camel rest端点
我正在开发配置了SSO/OAuth2安全性的Spring引导应用程序。 身份验证对我的rest控制器很有效,现在我需要用rest端点保护我的Apache Camel路由 据我所知,有几种方法可以做到这一点:Spring security 如何使用Spring安全性和OAuth2保护Apache Camel rest端点,spring-security,spring-boot,apache-camel,Spring Security,Spring Boot,Apache Camel,我正在开发配置了SSO/OAuth2安全性的Spring引导应用程序。 身份验证对我的rest控制器很有效,现在我需要用rest端点保护我的Apache Camel路由 据我所知,有几种方法可以做到这一点: 通过将身份验证处理器添加到我的路由 通过将策略(SpringSecurityAuthorizationPolicy)添加到我的路由 端点的“按处理程序”选项 我正试图通过向rest端点添加新的身份验证处理器来实现这一点,但我遇到了以下异常: org.springframework.secur
@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");
}
}
@配置
公共类SecurityConfig扩展了WebSecurity配置适配器{
受保护的无效配置(HttpSecurity http)引发异常{
http.csrf().disable().authorizeRequests().anyRequest().permitAll();
}
@配置
@EnableResourceServer
受保护的静态类ResourceServerConfiguration扩展了ResourceServerConfigurerAdapter{
@值(${oauth2.token.endpoint}”)
私有字符串标记端点;
@豆子
公共资源服务器令牌服务令牌服务(){
RemoteTokenServices tokenServices=新的RemoteTokenServices();
tokenServices.setClientId(“clientId”);
tokenServices.setClientSecret(“clientSecret”);
setCheckTokenEndpointUrl(tokenEndpoint);
退货服务;
}
@凌驾
public void configure(HttpSecurity http)引发异常{
http.authorizeRequests().anyRequest().authorized();
}
}
}
@配置
公共类EmbeddedServerRoute{
@豆子
公共RoutesBuilder embeddedServer(){
返回新的RouteBuilder(){
@凌驾
public void configure()引发异常{
restConfiguration().component(“jetty”).port(“8081”).bindingMode(RestBindingMode.json);
}
};
}
}
@组成部分
公共类RestTestRoute扩展了RouteBuilder{
@自动连线
专用授权处理器;
@凌驾
public void configure()引发异常{
from(“rest:get:/test”).process(authProcessor).to(“mock:end”).end();
}
}
@组成部分
公共类AuthProcessor实现处理器{
@自动连线
私人AuthenticationManager AuthenticationManager;
私有TokenExtractor TokenExtractor=新的BealerTokenExtractor();
私有身份验证DetailsSource AuthenticationDetailsSource=新的OAuth2AuthenticationDetailsSource();
@凌驾
公共作废进程(Exchange)引发异常{
HttpServletRequest=exchange.getIn().getBody(HttpServletRequest.class);
主题=新主题();
身份验证auth=getAuth(请求);
subject.getPrincipals().add(auth);
exchange.getIn().setHeader(exchange.AUTHENTICATION,subject);
}
私有身份验证getAuth(HttpServletRequest请求)引发OAuth2Exception{
身份验证=空;
试一试{
身份验证=tokenExtractor.extract(请求);
if(身份验证!=null){
setAttribute(OAuth2AuthenticationDetails.ACCESS_TOKEN_VALUE,authentication.getPrincipal());
if(AbstractAuthenticationToken的身份验证实例){
AbstractAuthenticationToken需要详细信息=(AbstractAuthenticationToken)身份验证;
needsDetails.setDetails(authenticationDetailsSource.buildDetails(请求));
}
返回authenticationManager.authenticate(身份验证);
}
}捕获(例外e){
抛出新的OAuth2Exception(例如getMessage());
}
抛出新的OAuth2Exception(“未授权查看资源”);
}
}
作为最终解决方案,我决定使用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());
}
@Bean
公共ServletRegistrationBean ServletRegistrationBean(){
SpringServerServlet=新的SpringServerServlet();
ServletRegistrationBean regBean=新的ServletRegistrationBean(serverServlet,“/camel/*”);
Map params=新的HashMap();
params.put(“org.restlet.component”、“restlecomponent”);
setInitParameters(参数);
返回regBean;
}
@豆子
公共组件restlecomponent(){
返回新组件();
}
@豆子
公共RestletComponent restletComponentService(){
返回新的restleComponent(restleComponent());
}