jetty嵌入式容器

最近,我遇到了一个非常有趣的问题,我认为这只需要几分钟就可以解决:在Linux中使用Spring Security (当前稳定版本3.2.5 )保护Apache CXF (当前版本3.0.1 )/ JAX-RS REST服务。在嵌入式Jetty容器(当前版本9.2 )中运行的应用程序。 最后,一旦您了解了事物如何协同工作并了解了细微的内在细节,这将变得非常容易。 这篇博客文章将试图揭示这一点。

我们的示例应用程序将公开一个简单的JAX-RS / REST服务来管理人员。 但是,我们不希望所有人都这样做,因此需要HTTP基本身份验证才能访问部署在http:// localhost:8080 / api / rest / people的端点。 让我们看一下PeopleRestService类:

package com.example.rs;import javax.json.Json;
import javax.json.JsonArray;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;@Path( "/people" )
public class PeopleRestService {@Produces( { "application/json" } )@GETpublic JsonArray getPeople() {return Json.createArrayBuilder().add( Json.createObjectBuilder().add( "firstName", "Tom" ).add( "lastName", "Tommyknocker" ).add( "email", "a@b.com" ) ).build();}
}

正如您在上面的代码片段中看到的,没有任何迹象表明该REST服务是安全的,只是几个熟悉的JAX-RS批注。

现在,让我们根据出色的Spring Security文档声明所需的安全配置。 有很多方法可以配置Spring Security,但我们将展示其中两种:使用内存内身份验证和使用用户详细信息服务,两者均基于WebSecurityConfigurerAdapter构建 。 让我们从内存中身份验证开始,因为它是最简单的一种:

package com.example.config;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity( securedEnabled = true )
public class InMemorySecurityConfig extends WebSecurityConfigurerAdapter {@Autowiredpublic void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {auth.inMemoryAuthentication().withUser( "user" ).password( "password" ).roles( "USER" ).and().withUser( "admin" ).password( "password" ).roles( "USER", "ADMIN" );}@Overrideprotected void configure( HttpSecurity http ) throws Exception {http.httpBasic().and().sessionManagement().sessionCreationPolicy( SessionCreationPolicy.STATELESS ).and().authorizeRequests().antMatchers("/**").hasRole( "USER" );}
}

在上面有该段两个用户定义: 用户与角色用户管理员用户的角色,ADMIN。 我们还通过将授权策略设置为仅允许访问角色为USER的用户来保护所有URL( / ** )。 作为应用程序配置的一部分,让我们使用@Import批注将其插入AppConfig类。

package com.example.config;import java.util.Arrays;import javax.ws.rs.ext.RuntimeDelegate;import org.apache.cxf.bus.spring.SpringBus;
import org.apache.cxf.endpoint.Server;
import org.apache.cxf.jaxrs.JAXRSServerFactoryBean;
import org.apache.cxf.jaxrs.provider.jsrjsonp.JsrJsonpProvider;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
import org.springframework.context.annotation.Import;import com.example.rs.JaxRsApiApplication;
import com.example.rs.PeopleRestService;@Configuration
@Import( InMemorySecurityConfig.class )
public class AppConfig { @Bean( destroyMethod = "shutdown" )public SpringBus cxf() {return new SpringBus();}@Bean @DependsOn ( "cxf" )public Server jaxRsServer() {JAXRSServerFactoryBean factory = RuntimeDelegate.getInstance().createEndpoint( jaxRsApiApplication(), JAXRSServerFactoryBean.class );factory.setServiceBeans( Arrays.< Object >asList( peopleRestService() ) );factory.setAddress( factory.getAddress() );factory.setProviders( Arrays.< Object >asList( new JsrJsonpProvider() ) );return factory.create();}@Bean public JaxRsApiApplication jaxRsApiApplication() {return new JaxRsApiApplication();}@Bean public PeopleRestService peopleRestService() {return new PeopleRestService();}
}

到目前为止,除了最有趣的部分,我们还有所有其他部分:运行嵌入式Jetty实例并创建正确的servlet映射,侦听器,传递我们创建的配置的代码。

package com.example;import java.util.EnumSet;import javax.servlet.DispatcherType;import org.apache.cxf.transport.servlet.CXFServlet;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.FilterHolder;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.springframework.web.context.ContextLoaderListener;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.filter.DelegatingFilterProxy;import com.example.config.AppConfig;public class Starter {public static void main( final String[] args ) throws Exception {Server server = new Server( 8080 );// Register and map the dispatcher servletfinal ServletHolder servletHolder = new ServletHolder( new CXFServlet() );final ServletContextHandler context = new ServletContextHandler();   context.setContextPath( "/" );context.addServlet( servletHolder, "/rest/*" );  context.addEventListener( new ContextLoaderListener() );context.setInitParameter( "contextClass", AnnotationConfigWebApplicationContext.class.getName() );context.setInitParameter( "contextConfigLocation", AppConfig.class.getName() );// Add Spring Security Filter by the namecontext.addFilter(new FilterHolder( new DelegatingFilterProxy( "springSecurityFilterChain" ) ), "/*", EnumSet.allOf( DispatcherType.class ));server.setHandler( context );server.start();server.join(); }
}

除了过滤器部分,大多数代码不需要任何说明。 这就是我所说的微妙的固有细节: DelegatingFilterProxy应该配置为过滤器名称,该名称必须恰好是springSecurityFilterChain ,因为Spring Security会为其命名。 这样,我们配置的安全规则将适用于任何JAX-RS服务调用(安全过滤器在Apache CXF Servlet之前执行),需要完全认证。 让我们通过构建和运行项目来快速检查:

mvn clean package
java -jar target/jax-rs-2.0-spring-security-0.0.1-SNAPSHOT.jar

在不提供用户名和密码的情况下发出HTTP GET调用不会成功,并返回HTTP 状态代码401 。

> curl -i http://localhost:8080/rest/api/peopleHTTP/1.1 401 Full authentication is required to access this resource
WWW-Authenticate: Basic realm="Realm"
Cache-Control: must-revalidate,no-cache,no-store
Content-Type: text/html; charset=ISO-8859-1
Content-Length: 339
Server: Jetty(9.2.2.v20140723)

提供的用户名和密码相同的HTTP GET调用返回成功响应(服务器生成一些JSON)。

> curl -i -u user:password http://localhost:8080/rest/api/peopleHTTP/1.1 200 OK
Date: Sun, 28 Sep 2014 20:07:35 GMT
Content-Type: application/json
Content-Length: 65
Server: Jetty(9.2.2.v20140723)[{"firstName":"Tom","lastName":"Tommyknocker","email":"a@b.com"}]

太好了,它就像一个魅力! 事实证明,这确实非常容易。 同样,如前所述,可以使用用户详细信息服务替换内存中的身份验证,这是一个如何完成的示例:

package com.example.config;import java.util.Arrays;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled = true)
public class UserDetailsSecurityConfig extends WebSecurityConfigurerAdapter {@Autowiredpublic void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {auth.userDetailsService( userDetailsService() );}@Beanpublic UserDetailsService userDetailsService() {return new UserDetailsService() {@Overridepublic UserDetails loadUserByUsername( final String username ) throws UsernameNotFoundException {if( username.equals( "admin" ) ) {return new User( username, "password", true, true, true, true,Arrays.asList(new SimpleGrantedAuthority( "ROLE_USER" ),new SimpleGrantedAuthority( "ROLE_ADMIN" )));} else if ( username.equals( "user" ) ) {return new User( username, "password", true, true, true, true,Arrays.asList(new SimpleGrantedAuthority( "ROLE_USER" )));} return null;}};}@Overrideprotected void configure( HttpSecurity http ) throws Exception {http.httpBasic().and().sessionManagement().sessionCreationPolicy( SessionCreationPolicy.STATELESS ).and().authorizeRequests().antMatchers("/**").hasRole( "USER" );}
}

AppConfig类中的@Import(InMemorySecurityConfig.class)替换为@Import( UserDetailsS​​ecurityConfig.class)会得到相同的结果,因为两个安全配置都定义了相同的用户及其角色集。

我希望,此博客文章可以节省您一些时间,并为您提供一个良好的起点,因为Apache CXF和Spring Security在Jetty的保护下相处得很好!

  • 完整的源代码可在GitHub上找到 。

翻译自: https://www.javacodegeeks.com/2014/09/embedded-jetty-and-apache-cxf-secure-rest-services-with-spring-security.html

jetty嵌入式容器

jetty嵌入式容器_嵌入式Jetty和Apache CXF:借助Spring Security来保护REST服务相关推荐

  1. 嵌入式Jetty和Apache CXF:借助Spring Security来保护REST服务

    最近,我遇到了一个非常有趣的问题,我认为这只花了我几分钟就解决了:在Windows Server 2003中使用Spring Security (当前稳定版本3.2.5 )保护Apache CXF ( ...

  2. security框架工作笔记001--- Shiro和Spring Security对比_智慧城市项目中选型用Spring Security

    JAVA技术交流QQ群:170933152 Shiro简介 Apache Shiro是Java的一个安全框架.目前,使用Apache Shiro的人越来越多,因为它相当简单,对比Spring Secu ...

  3. 使用Apache cxf 和Spring在Tomcat下发布Webservice指南

    转载 http://blog.csdn.net/zhangzhaokun/article/details/4750021 最近学习了如何使用apache cxf和Spring发布webservice, ...

  4. 学python与嵌入式操作系统_嵌入式操作系统那么多,哪一个适合你?

    原标题:嵌入式操作系统那么多,哪一个适合你? 物联网.人工智能的发展都离不开嵌入式系统,而嵌入式操作系统又是其中不容忽视的重要部分,工程师对其要求也由过去的简单易用上升到既要简单易用又安全可靠.嵌入式 ...

  5. Apache Shiro和Spring Security的详细对比

    参考资料: 1)Apache Shiro Apache Shiro:http://shiro.apache.org/ 在Web项目中应用 Apache Shiro:http://www.ibm.com ...

  6. BCrypt加密怎么存入数据库_松哥手把手带你入门 Spring Security,别再问密码怎么解密了...

    因为之前有小伙伴在松哥群里讨论如何给微人事的密码解密,我看到聊天记录后就惊呆了. 无论如何我也得写一篇文章,带大家入门 Spring Security!当我们在一个项目中引入 Spring Secur ...

  7. linux嵌入式物联网_嵌入式Linux如何加速物联网发展

    linux嵌入式物联网 您会发现,构建IoT生态系统组件的最快方法是使用嵌入式Linux,无论您是从一开始就扩充现有设备还是设计新设备或系统. 嵌入式Linux与台式机Linux共享相同的源代码库,但 ...

  8. 如何通过网络将文件传输到嵌入式设备_嵌入式系统 Boot Loader技术内幕,带你完全了解Boot Loader...

    一个嵌入式 Linux 系统从软件的角度看通常可以分为四个层次:1. 引导加载程序.包括固化在固件(firmware)中的 boot 代码(可选),和 Boot Loader 两大部分.2. Linu ...

  9. 一个完整的嵌入式程序_嵌入式入门-从STM32CudeMX、FreeRtos、Proteu仿真开始

    系统 嵌入式是什么呢? 嵌入式开发就是指在嵌入式操作系统下进行开发,常用的嵌入式操作系统有FreeRtos,ucos,linux,android等.与单片机开发最大的不同就是裸跑与跑系统的区别.嵌入式 ...

最新文章

  1. bilibili有电脑版吗_虚充制冷剂、谎称电脑版故障...空调维修的这些套路,你 中招了吗...
  2. 解决:SyntaxError: Non-ASCII character ‘\xe8‘ in file 1.py on line 4, but no encoding declared;
  3. 一文看懂:搭建活动分析体系
  4. jit编译_意外分配– JIT编译抖动
  5. android初步ui线程案例,android – 它是一个bug还是一个功能?在某些情况下,可以从未在UI线程上运行的任务访问UI线程...
  6. 在哪里定义_定义市场的关键字:找出它们在哪里使用,以便您可以抢占该市场...
  7. weiapi2.2 HelpPage自动生成接口说明文档和接口测试功能
  8. CoreData的用法
  9. IIS6同一IP部署多域名证书(部署指南)
  10. 微信小程序教程、微信小程序开发资源下载汇总
  11. 怎么登录微信公众号-微信公众号使用教程2
  12. 2021各厂免费云服务器申请攻略(阿里云/腾讯云/华为云)
  13. 解决margin坍塌
  14. 鸿运当头凤梨花怎么养 凤梨花养殖方法及注意事项
  15. 国信安web安全——文件上传漏洞
  16. 惊心动魄修复U盘【另附U盘量产工具】(显示文件格式为RAW 需要格式化)
  17. 产品经理到底是做什么的?|️ 什么是产品经理?
  18. poi向excel插入图片demo
  19. PostGIS 快速入门
  20. InvalidKeyException: Illegal key size异常解决方案

热门文章

  1. jzoj1610(初中)-导弹【最大匹配,最短路,二分答案】
  2. ssl提高组国庆模拟赛【2018.10.5】
  3. 【动态规划】机器分配 (ssl 1639)
  4. codeforces gym-101741 Cover the Paths LCA、离线询问
  5. Dubbo(二)之SpringBoot nacos集成
  6. 汇编语言(二十六)之自然数求和
  7. Java读取properties配置文件时,中文乱码解决方法
  8. JDK8新特性之方法引用
  9. csdn颜色字体的改变
  10. 谁说表单只能发get和post请求了?