Spring Security 3 Ajax登录–访问受保护的资源

我看过一些有关Spring Security 3 Ajax登录的博客,但是我找不到解决如何调用基于Ajax的登录的博客,匿名用户正在Ajax中访问受保护的资源。

问题 – Web应用程序允许匿名访问某些部分,并且某些部分是受保护的资源,需要用户登录。

当匿名用户(通过Http Get / Post)访问受保护的资源时,Spring Security会自动调用登录页面,并在成功通过身份验证后重定向到所需的资源/页面。

但是,如果正在Ajax中访问受保护的资源,则登录页面将无法正确显示(将在页面的一部分上进行设置)。 302代码(重定向到登录页面)将无法在Ajax中正常运行。

请注意,这与启动Ajax登录屏幕不同(例如,当用户按下登录按钮并调用带有用户/密码字段的弹出窗口时)。

那么–我们如何让Spring Security 3通过“常规” HTTP Post(基于FORM的身份验证)和Ajax调用来处理对受保护资源的访问,包括在成功身份验证后重定向到所需资源?

因此,此博客文章包含两个保护层/部分:
1. Spring Security 3标准基于FORM的身份验证
2.配置/扩展Spring Security 3.并且该应用程序还支持Ajax对受保护资源的访问。

关于第1部分-有关此问题的参考很多。 无需详细说明。

关于第2部分–要求以下内容:

1.配置Spring Security 3以启用基于Ajax的登录。
2.将客户端Ajax调用配置为受保护的资源,以处理身份验证请求。
3.重新执行功能以模拟成功登录后自动进行用户原始方法的调用(这在基于FORM的登录中发生)

下图描述了详细的流程,应有助于遵循客户端/服务器通信。

通过Ajax处理受保护的资源访问

让我们讨论一下图:

该流程始于对受保护资源(1)的匿名用户Ajax请求。 在这种情况下,用户希望将商品添加到购物车。

addItem方法是受保护的资源,它通过Spring Security(@pre_authorize(“ SOME_ROLE”))(2)受保护。 这使Spring Secutiry过滤器(3)发送带有HTTP代码302的登录表单(即,重定向到该页面)。

现在,由于这是一个Ajax调用,它将无法很好地处理请求,因此这里涉及到了登录表单,将其放在一边,然后调用基于Ajax的登录(4):

客户端Ajax方法(调用了Ajax addItem方法)检查​​它是基于表单的登录名还是其他任何答复。 如果是基于FORM的登录,它将调用一个对话框模式(5),该模式将尝试登录Ajax。 Spring将处理Ajax登录认证(6)并将适当的消息返回给客户端。 如果消息成功,则客户端将重新执行原始功能,该功能试图访问受保护的资源(例如,本例中的addItem )。

让我们看看它们如何适合我们的代码:
步骤#1,#4 –客户端访问受保护的资源并检查是否需要登录

//JavaScript method - Ajax call to protected resource (#1 in flow diagram)
function addItem(itemId) {    $.ajax({url: '/my_url/order/addItem',type: 'POST',data: ({orderItemId : itemId,...}),               success: function(data) {//construct a callback string if user is not logged in.var cllbck = 'addItem('+itemId +')';//Client check if login required//(#4 in flow diagram)if (verifyAuthentication(data,cllbck)){// in here => access to protected resource was ok// show message to user, "item has been added..."}});}

步骤#2,#3 –是常规的Spring Security配置。 的大量资源 了 那里 。

步骤#4 –客户端检查是否需要登录:

function verifyAuthentication(data, cllBackString){//naive check - I put a string in the login form, so I check for existanceif (isNaN(data) && (data.indexOf("login_hidden_for_ajax")!= -1)){//if got here then data is a loginform => login required//set callback in ajax login form hidden input  $("#my_callback").val(cllBackString); //show ajax login//Get the window height and widthvar winH = $(window).height();var winW = $(window).width();//Set the popup window to center$("#ajaxLogin").css('top',  winH/2-$("#ajaxLogin").height()/2);$("#ajaxLogin").css('left', winW/2-$("#ajaxLogin").width()/2);$("#ajaxLogin").fadeIn(2000); return false;} // data is not a login form => return true to continue with function processingreturn true; 
}

步骤#5,#7 – Ajax登录表单使用以下Ajax登录:

function ajaxLogin(form, suffix){var my_callback = form.my_callback.value; // The original function which accessed the protected resourcevar user_pass = form.j_ajax_password.value;var user_name = form.j_ajax_username.value; //Ajax login - we send credentials to j_spring_security_check (as in form based login$.ajax({url: "/myContextURL/j_spring_security_check",    data: { j_username: user_name , j_password: user_pass }, type: "POST",beforeSend: function (xhr) {xhr.setRequestHeader("X-Ajax-call", "true");},success: function(result) {     //if login is success, hide the login modal and//re-execute the function which called the protected resource//(#7 in the diagram flow)if (result == "ok") {$("#ajax_login_error_"+ suffix).html("");            $('#ajaxLogin').hide();if (my_callback!=null && my_callback!='undefined' && my_callback!=''){eval(my_callback.replace(/_/g,'"'));}return true;}else {        $("#ajax_login_error_"+ suffix).html('<span  class="alert display_b clear_b centeralign">Bad user/password</span>') ;return false;         }},error: function(XMLHttpRequest, textStatus, errorThrown){$("#ajax_login_error_"+ suffix).html("Bad user/password") ;return false; }
});
}

我们需要将Spring设置为支持Ajax登录(#6):

设置Spring Security xml配置:

<beans:beans xmlns:beans="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/security" xsi:schemalocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsdhttp://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.0.3.xsd"><http auto-config="false" use-expressions="true"><intercept-url access="hasRole('ROLE_ADMIN')" pattern="/admin**"><intercept-url filters="none" pattern="/**"><intercept-url access="permitAll" pattern="/signin/**"><form-login authentication-failure-handler-ref="ajaxAuthenticationFailureHandler" authentication-success-handler-ref="ajaxAuthenticationSuccessHandler" login-page="/common/authentication/login"> <logout invalidate-session="true" logout-success-url="/common/authentication/logout"><custom-filter before="LOGOUT_FILTER" ref="logoutFilter"></custom-filter></logout></form-login></intercept-url></intercept-url></intercept-url></http>...
</beans:beans>

定义成功登录的处理程序:

@Component("ajaxAuthenticationSuccessHandler")
public class AjaxAuthenticationSuccessHandler extends SimpleUrlAuthenticationSuccessHandler { public AjaxAuthenticationSuccessHandler() {    }@Overridepublic void onAuthenticationSuccess(HttpServletRequest request,HttpServletResponse response, Authentication authentication)throws IOException, ServletException { HttpSession session = request.getSession();  DefaultSavedRequest defaultSavedRequest = (DefaultSavedRequest) session.getAttribute(WebAttributes.SAVED_REQUEST);//check if login is originated from ajax callif ("true".equals(request.getHeader("X-Ajax-call"))) {try {response.getWriter().print("ok");//return "ok" stringresponse.getWriter().flush();} catch (IOException e) {    //handle exception...}} else {      setAlwaysUseDefaultTargetUrl(false);  ...}}
}

为登录失败定义一个处理程序–与成功相同,但是字符串为“ not-ok”。

我知道这里的某些代码不是最佳做法,所以我想听听您的想法。
如果您能看到改进流程或使其更通用的方法,请发给我。

鸣谢:通过gliffy完成了图表-在线图表工具

参考: Spring security 3 Ajax登录–通过 Gal Levinsky博客博客中的JCG合作伙伴 Gal Levinsky 访问受保护的资源 。


翻译自: https://www.javacodegeeks.com/2012/08/spring-security-3-ajax-login-accessing.html

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

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

相关文章

linux运维选择题,初学Linux练习题

1、将/etc/issue文件中的内容转换为大写后保存至/tmp/issue.out文件中tr ‘a-z’ ‘A-Z’ < /etc/issue > /tmp/issue.out2、将当前系统登录用户的信息转换为大写后保存至/tmp/who.out文件中3、一个linux用户给root发邮件&#xff0c;要求邮件标题为”help”&#xff0c…

[转]Web Api系列教程第2季(OData篇)(二)——使用Web Api创建只读的OData服务

本文转自&#xff1a;http://www.cnblogs.com/fzrain/p/3923727.html 前言 很久没更新了&#xff0c;之前有很多事情&#xff0c;所以拖了很久&#xff0c;非常抱歉。好了&#xff0c;废话不多说&#xff0c;下面开始正题。本篇仍然使用上一季的的项目背景&#xff08;系列地址…

linux idea 快捷键,Linux 下 IDEA 的 Ctrl+Alt+S

前言这是个困扰我一年多的问题&#xff0c;今天终于解决了……起因一年前将主系统换成 Arch Linux 后&#xff0c;其他一切正常就是 IDEA 的打开设置的快捷键 ctrlalts 失效&#xff0c;让我很是头疼。虽然不是很重要&#xff0c;但是对于我这种强迫症来说别提多难受了……我曾…

C语言数字3转变字符 3 程序,大学c语言知识点总结

大学c语言知识点总结C语言的设计目标是提供一种能以简易的方式编译、处理低级存储器、产生少量的机器码以及不需要任何运行环境支持便能运行的编程语言。一起来看看大学c语言知识点总结吧!大学c语言知识点总结1、编译预处理不是C语言的一部分&#xff0c;不再运行时间。C语言编…

接触Jenkins(Hudson)API,第1部分

哪一个-哈德森还是詹金斯&#xff1f; 都。 几个月前&#xff0c;我开始使用Hudson v1.395来从事这个小项目&#xff0c;在出现巨大分歧之后又回到了这个项目。 我以此为契机&#xff0c;看我将来选择永久搬到詹金斯时是否会遇到任何重大问题。 有很多麻烦-最值得注意的是&…

使用javascript模拟常见数据结构(四)

七、树 树是一种非线性的分层的数据结构&#xff0c;在现实生活中比较常见的例子比如家谱和公司的组织架构图&#xff0c;如下所示&#xff1a; 一个树结构存在着一系列的父子结构&#xff0c;并且有着一个根节点&#xff0c;这种结构本质上表明了一对多的关系。 那&#xff0c…

最全Pycharm教程(10)——Pycharm调试器总篇

最全Pycharm教程&#xff08;1&#xff09;——定制外观 最全Pycharm教程&#xff08;2&#xff09;——代码风格 最全Pycharm教程&#xff08;3&#xff09;——代码的调试、执行 最全Pycharm教程&#xff08;4&#xff09;——有关Python解释器的相关配置 最全Pycharm教程&am…

Looper.prepare()和Looper.loop()

什么时候需要 Looper Looper用于封装了android线程中的消息循环&#xff0c;默认情况下一个线程是不存在消息循环&#xff08;message loop&#xff09;的&#xff0c;需要调用Looper.prepare()来给线程创建一个消息循环&#xff0c;调用Looper.loop()来使消息循环起作用&#…

如何查看Ubuntu版本,以及Linux内核版本??

查看Ubuntu版本&#xff1a; 方法一&#xff1a; cat /etc/issue 方法二&#xff1a; sudo lsb_release -a 查看内核版本&#xff1a; uname -r 转载于:https://www.cnblogs.com/tanrong/p/6937749.html

实现chrome扩展启动本地进程 - 补充

实现chrome扩展启动本地进程 - 补充 标签&#xff1a; chrome扩展启动本地程序访问本地磁盘2014-10-17 11:42 6753人阅读 评论(17) 收藏 举报分类&#xff1a;Chrome Plugin版权声明&#xff1a;本文为博主原创文章&#xff0c;未经博主允许不得转载。 示例 主要包含如下部分 c…

单路电压表c语言编程,用AT89C51单片机制作的数字电压表

此数字电压表&#xff0c;利用A/D转换原理将被测模拟量转换成数字量&#xff0c;并通过控制系统用数字方式显示测量结果。本设计采用AT89C51单片机&#xff0c;ADC0809进行模/数转换&#xff0c;能够测量8路0&#xff5e;5V的输入电压值&#xff0c;可用四位LED数码管轮流或单路…

ZK的实际应用:MVVM –加载和渲染数据

先前的文章简要介绍了RIA框架ZK&#xff0c;以及它CSS Selector启发式控制器机制如何通过使在控制器类中引用UI组件的任务变得相对灵活来减轻UI更改所带来的一些负担。 然后&#xff0c;我们在上一篇文章中探讨了ZK中的MVVM模式如何允许单个ViewModel提供不同的视图。 这篇文章…

搭建一个简单的mybatis框架

一、Mybatis介绍 MyBatis是一个支持普通SQL查询&#xff0c;存储过程和高级映射的优秀持久层框架。MyBatis消除了几乎所有的JDBC代码和参数的手工设置以及对结果集的检索封装。MyBatis可以使用简单的XML或注解用于配置和原始映射&#xff0c;将接口和Java的POJO&#xff08;Pla…

c语言空格符 r t,c语言中、\t \r \n 和空格什么意思

具体意思&#xff1a;都是转义字符&#xff0c;空格就是单纯的空格&#xff0c;输入时可以输入空格\t 跳格 \r 回车 \n 换行\\ 反斜杠 \a 警告 \b 退格 \f 换页 \v 垂直跳格 \ddd ddd 是 1、2 或 3 位八进制数字。转义字符串(Escap…

在代理类中引用动态代理

在Stackoverflow中有一个有趣的问题 &#xff0c;关于Spring Bean如何获​​得对由Spring创建的代理的引用以处理事务&#xff0c;Spring AOP&#xff0c;缓存&#xff0c;异步流等。需要对代理的引用&#xff0c;因为如果存在对自身的调用通过代理bean&#xff0c;此调用将完全…

android仿高德地图透明黑字,Android 仿高德地图可拉伸的BottomSheet

原标题&#xff1a;Android 仿高德地图可拉伸的BottomSheet2018安卓巴士开发者大会-上海站你一直期待的安卓技术盛宴即将登场&#xff01;前言最近项目中需要用到高德地图搜索结果后的结果展示的可拉伸控件。而我看到这个效果图&#xff0c;觉得这个就是一个slidingpanel&#…

[ Javascript ] JavaScript中的定时器(Timer) 是怎样工作的!

作为入门者来说。了解JavaScript中timer的工作方式是非常重要的。通常它们的表现行为并非那么地直观&#xff0c;而这是由于它们都处在一个单一线程中。让我们先来看一看三个用来创建以及操作timer的函数。var id setTimeout(fn, delay); - 初始化一个单一的timer&#xff0c…

Android 软键盘自动弹出和关闭

在我们写修改信息或者搜索&#xff0c;修改密码等界面的时候&#xff0c;用户进入这个界面的主要目的就是输入修改/查找 某些信息&#xff0c;为了用户体验应该自动弹出软键盘而不是让用户主动点击输入框才弹出。 1.软键盘的自动弹出 private void showKeyboard(){InputMethodM…

android adb杀死服务,Android app是如何杀掉的

1. adb shell kill -9 pid_of_appAMS定义了AppDeathRecipientAPP 在 attachApplication -> attachApplicationLockedAMS里会注册 App 进程的 BinderDeath通知AppDeathRecipient adr new AppDeathRecipient(app, pid, thread);thread.asBinder().linkToDeath(adr, 0);当App进…

iOS学习笔记39-ReactiveCocoa入门

FRP&#xff0c;全称为Functional Reactive Programming&#xff0c;是一种响应变化的编程范式&#xff0c;最近几年比较火&#xff0c;大概的理解就像这样&#xff1a; 当a的值或者b的值发生变化时&#xff0c;c的值会自动响应a的值或b的值变化的信号&#xff0c;自动更正自己…