使用Spring Security保护REST服务

总览

最近,我正在一个使用REST服务层与客户端应用程序(GWT应用程序)进行通信的项目中。 因此,我花了很多时间来弄清楚如何使用Spring Security保护REST服务。 本文介绍了我找到的解决方案,并已实现。 我希望此解决方案将对某人有所帮助,并节省大量宝贵的时间。

解决方案

在普通的Web应用程序中,每当访问安全资源时,Spring Security都会检查当前用户的安全上下文,并决定将其转发到登录页面(如果用户未通过身份验证),或将其转发到未经授权的资源。页面(如果他没有所需的权限)。

在我们的场景中,这是不同的,因为我们没有要转发的页面,我们需要调整和覆盖Spring Security以仅使用HTTP协议状态进行通信,下面我列出了使Spring Security发挥最大作用的工作:

  • 身份验证将通过普通形式的登录名进行管理,唯一的区别是响应将以JSON以及HTTP状态(可通过代码200(如果通过验证)或代码401(如果身份验证失败))进行;
  • 重写AuthenticationFailureHandler以返回代码401 UNAUTHORIZED;
  • 重写AuthenticationSuccessHandler以返回代码20 OK,HTTP响应的主体包含当前已认证用户的JSON数据;
  • 重写AuthenticationEntryPoint以始终返回代码401 UNAUTHORIZED。 这将覆盖Spring Security的默认行为,该行为是在用户不符合安全要求的情况下将用户转发到登录页面,因为在REST上我们没有任何登录页面;
  • 覆盖LogoutSuccessHandler以返回代码20 OK;

就像由Spring Security保护的普通Web应用程序一样,在访问受保护的服务之前,必须首先通过向登录URL提交密码和用户名来进行身份验证。

注意:以下解决方案要求Spring Security的最低版本为3.2。

覆盖AuthenticationEntryPoint

该类扩展了org.springframework.security.web.AuthenticationEntryPoint,并且仅实现了一种方法,该方法会在未经授权的情况下发送响应错误(带有401状态代码)。

@Component
public class HttpAuthenticationEntryPoint implements AuthenticationEntryPoint {@Overridepublic void commence(HttpServletRequest request, HttpServletResponse response,AuthenticationException authException) throws IOException {response.sendError(HttpServletResponse.SC_UNAUTHORIZED, authException.getMessage());}
}

重写AuthenticationSuccessHandler

AuthenticationSuccessHandler负责成功认证后的操作,默认情况下它将重定向到URL,但在我们的情况下,我们希望它发送带有数据的HTTP响应。

@Component
public class AuthSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler {private static final Logger LOGGER = LoggerFactory.getLogger(AuthSuccessHandler.class);private final ObjectMapper mapper;@AutowiredAuthSuccessHandler(MappingJackson2HttpMessageConverter messageConverter) {this.mapper = messageConverter.getObjectMapper();}@Overridepublic void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,Authentication authentication) throws IOException, ServletException {response.setStatus(HttpServletResponse.SC_OK);NuvolaUserDetails userDetails = (NuvolaUserDetails) authentication.getPrincipal();User user = userDetails.getUser();userDetails.setUser(user);LOGGER.info(userDetails.getUsername() + " got is connected ");PrintWriter writer = response.getWriter();mapper.writeValue(writer, user);writer.flush();}
}

重写AuthenticationFailureHandler

AuthenticationFaillureHandler负责身份验证失败后的处理方法,默认情况下它将重定向到登录页面URL,但是在我们的情况下,我们只希望它发送带有401 UNAUTHORIZED代码的HTTP响应。

@Component
public class AuthFailureHandler extends SimpleUrlAuthenticationFailureHandler {@Overridepublic void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,AuthenticationException exception) throws IOException, ServletException {response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);PrintWriter writer = response.getWriter();writer.write(exception.getMessage());writer.flush();}
}

覆盖LogoutSuccessHandler

LogoutSuccessHandler决定用户成功注销后的操作,默认情况下它将重定向到登录页面URL,因为我们没有重写它以返回带有20 OK代码的HTTP响应。

@Component
public class HttpLogoutSuccessHandler implements LogoutSuccessHandler {@Overridepublic void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication)throws IOException {response.setStatus(HttpServletResponse.SC_OK);response.getWriter().flush();}
}

Spring安全配置

这是最后一步,将所有工作放在一起,我更喜欢使用新的方式来配置Spring Security,它使用Java而不是XML,但是您可以轻松地将此配置适应XML。

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {private static final String LOGIN_PATH = ApiPaths.ROOT + ApiPaths.User.ROOT + ApiPaths.User.LOGIN;@Autowiredprivate NuvolaUserDetailsService userDetailsService;@Autowiredprivate HttpAuthenticationEntryPoint authenticationEntryPoint;@Autowiredprivate AuthSuccessHandler authSuccessHandler;@Autowiredprivate AuthFailureHandler authFailureHandler;@Autowiredprivate HttpLogoutSuccessHandler logoutSuccessHandler;@Bean@Overridepublic AuthenticationManager authenticationManagerBean() throws Exception {return super.authenticationManagerBean();}@Bean@Overridepublic UserDetailsService userDetailsServiceBean() throws Exception {return super.userDetailsServiceBean();}@Beanpublic AuthenticationProvider authenticationProvider() {DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider();authenticationProvider.setUserDetailsService(userDetailsService);authenticationProvider.setPasswordEncoder(new ShaPasswordEncoder());return authenticationProvider;}@Overrideprotected void configure(AuthenticationManagerBuilder auth) throws Exception {auth.authenticationProvider(authenticationProvider());}@Overrideprotected AuthenticationManager authenticationManager() throws Exception {return super.authenticationManager();}@Overrideprotected void configure(HttpSecurity http) throws Exception {http.csrf().disable().authenticationProvider(authenticationProvider()).exceptionHandling().authenticationEntryPoint(authenticationEntryPoint).and().formLogin().permitAll().loginProcessingUrl(LOGIN_PATH).usernameParameter(USERNAME).passwordParameter(PASSWORD).successHandler(authSuccessHandler).failureHandler(authFailureHandler).and().logout().permitAll().logoutRequestMatcher(new AntPathRequestMatcher(LOGIN_PATH, "DELETE")).logoutSuccessHandler(logoutSuccessHandler).and().sessionManagement().maximumSessions(1);http.authorizeRequests().anyRequest().authenticated();}
}

这是总体配置的一个潜行高峰,我在本文中附加了一个Github存储库,其中包含示例项目https://github.com/imrabti/gwtp-spring-security 。

我希望这可以帮助一些努力寻找解决方案的开发人员,请随时提出任何问题,或发布任何可以使该解决方案更好的增强功能。

翻译自: https://www.javacodegeeks.com/2014/09/secure-rest-services-using-spring-security.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/361801.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

http请求post,返回excel文件,并接收

1.post的方法里要加responseType: arraybuffer参数,不然下载的excel会乱码 2.使用{type: "application/vnd.ms-excel"}的写法,可以保存为xls格式的excel文件(兼容老版本)。而使用“application/vnd.openxmlformats-off…

linux图形开发工具

请见:http://hi.baidu.com/jjzhang166/blog/item/b8dfb6ecd5fc6e2d62d09f9e.html 转载于:https://www.cnblogs.com/vilyLei/archive/2011/12/12/2284869.html

具有Overlord的WildFly 8.1中的API管理

昨天,我简要介绍了霸王项目家族。 今天该试驾了。 API管理子项目两天前发布了1.0.0.Alpha1,并根据18个月的路线图介绍了第一组功能。 APIMan到底是什么? 它是一个API管理系统,可以嵌入现有框架或应用程序中,甚至可以作…

设计模式学习笔记-代理模式

1. 概述 为其它对象提供一种代理以控制对这个对象的访问。 解决的问题:如果直接访问对象比较困难,或直接访问会给使用者或系统带来一系列问题。这样对于客户端(调用者)来说,就不需要直接与真实对象进行交互&#xff0c…

Tomcat配置自签名https

从JDK中找到keytool.exe,随便复制到一个方便的目录,在命令行中进入这个目录。 第一步:为服务器生成证书 tomcat.keystore,名字就是域名,其他的看着写。 keytool -genkey -v -alias tomcat -keyalg RSA -validity 3650…

MFC学习之路之多媒体 --(1) DirectShow

可以说整个Windows的多媒体编程都是以DirectShow为基础,那好,来吧,我们直接看DirectShow的一段基础代码。 bool Mp3::Load(LPCWSTR szFile) {Cleanup();ready false;if (SUCCEEDED(CoCreateInstance( CLSID_FilterGraph,NULL,CLSCTX_INPROC_…

使用反射处理Java批注

在上一篇有关Java注释的文章中,我概述了一个最近的用例,并为您提供了一些自定义注释的示例以及如何使用它们。 在本文中,我将更进一步,并为您提供一些自定义注释的示例,以及如何使用Java Reflection API处理这些自定义…

Excel 2007 Open XML文件结构(2)

Excel 2007 Open XML文件结构&#xff08;2&#xff09; 在以上文件中&#xff0c;根据<sheet>元素中r:id属性的值可得到工作表数据的XML文件。例如&#xff0c;在workbook.xml文件中名为工作表1的工作表的r:id属性为rld1&#xff0c;在以上文件中根据ID找到以下代码&…

Vue.js最佳实践

Vue.js最佳实践 第一招&#xff1a;化繁为简的Watchers 场景还原&#xff1a; created(){this.fetchPostList() },watch: {searchInputValue(){this.fetchPostList()} } 组件创建的时候我们获取一次列表&#xff0c;同时监听input框&#xff0c;每当发生变化的时候重新获取一…

Api demo源码学习(8)--App/Activity/QuickContactsDemo --获取系统联系人信息

本节通过Content Provider机制获取系统中的联系人信息&#xff0c;注意这个Anctivity直接继承的是ListActivity&#xff0c;所以不再需要setContentView函数来加载布局文件了&#xff08;我自己新建一个项目来跑这个anctivity时在这里卡了半天&#xff09;。 在AndroidManifest…

游戏大厅 从基础开始(6)--绕回来细说聊天室(中)之女仆编年史1

上一篇我们大致的了解了几种聊天室的行为模式 最简单明了的推模式 几乎不需要任何多余的语言来描述它的实现 这一篇我们看看如何实现拉模式更有效。 本图清晰的表现了"拉"模式聊天室的行为。 并发多用户向数据池写数据 并发多用户从数据池读书据 数据最好以时间为…

开发自上而下的Web服务项目

这是从Alessio Soldano编辑的Advanced JAX-WS Web Services手册中摘录的示例章节。 第一章介绍了自底向上创建Web服务端点的方法。 它允许非常快地将现有bean作为Web Service端点公开&#xff1a;在大多数情况下&#xff0c;将类转换为端点只需在代码中添加少量注释即可。 但…

React中ref的使用方法

React中ref的使用方法 在react典型的数据流中&#xff0c; props传递是父子组件交互的唯一方式&#xff1b;通过传递一个新的 props值来使子组件重新 re-render,从而达到父子组件通信。当然&#xff0c;就像react官网所描述的一样&#xff0c;在react典型的数据量之外&#xff…

mediawiki自动生成sitemap

Mediawiki 1.17.0提供了generateSitemap.php生成sitemap文件&#xff0c;可不必再使用扩展。 每次调用generateSitemap.php&#xff0c;生成全部sitemap。一般是通过定时任务(Linux下是cron)调用&#xff0c;定时生成。 generateSitemap.php命令示例&#xff1a; php /wiki/mai…

垃圾收集:提高吞吐量

这篇文章的灵感来自于在内存管理术语中的“ Pig in the Python ”定义。 显然&#xff0c;该术语用于解释GC反复促进大对象世代相传的情况。 据推测&#xff0c;这样做的效果类似于Python吞下整个猎物&#xff0c;只是在消化过程中被固定住了。 在接下来的24小时里&#xff0c…

Scss基础用法

Scss基础用法 一、注释用法&#xff1a; &#xff08;1&#xff09;//comment&#xff1a;该注释只是在.scss源文件中有&#xff0c;编译后的css文件中没有。 &#xff08;2&#xff09;/! /&#xff1a;重要注释&#xff0c;任何style的css文件中都会有&#xff0c;一般放置…

(Joomla)字符串截取

在用joomla进行开发的时候&#xff0c;需要用到国外的资源&#xff0c;一些module&#xff0c;组件&#xff0c;插件之类的&#xff0c;但是我们会发现&#xff0c;在字符串这个方法都需要进行修改。因为PHP的substr方法只是针对于非中文字符串有效&#xff0c;所以要使用另外一…

Pyechart:30分钟学会pyecharts数据可视化

30分钟学会pyecharts数据可视化 小红&#xff1a;你先跟我说说什么是pyecharts吧。 小明&#xff1a;Echarts 是一个由百度开源的数据可视化javascript库&#xff0c;凭借着良好的交互性&#xff0c;精巧的图表设计&#xff0c;得到了众多开发者的认可。而 Python 是一门富有表…

Spring @Configuration – RabbitMQ连接

我一直在转换必须使用Spring Configuration机制配置到RabbitMQ的连接的应用程序-最初&#xff0c;我使用xml bean定义文件来描述配置。 这是我的原始配置&#xff1a; <beans ...;><context:property-placeholder/><rabbit:connection-factory id"rabbit…

大叔手记(12):我的一次面试经历(谈大叔如何应对面试官)

本文目的 写本文的目的&#xff0c;大叔不是为了装逼&#xff08;虽然说话的口气有时候也确实有点装逼&#xff0c;性格导致的&#xff0c;咳。。。我得改&#xff09;&#xff0c;其实大叔在公司也只是小罗罗&#xff0c;本文的目的主要是为了向大家展示如何通过各种软技能应对…