Java AJAX webapp安全性

时间:2009-11-30 17:26:45

标签: java ajax security java-ee login

我正在尝试创建一个简单的AJAX Java webapp。

我想使用Servlet容器提供的容器管理安全性,但是经过调查后我觉得它不会像我想要的那样工作。基本上我希望能够在主页面上有一个登录提示,而无需用户导航到登录表单。

作为一个例子,想象一个简单的留言板应用程序和想要发布新消息的用户直接将文本输入到屏幕上的表单中,当按下提交按钮时我希望能够制作一个ajax调用以确定用户是否已登录,如果没有,那么我想在同一页面上显示登录div,以允许用户登录而无需导航到单独的登录页面。

servlet容器提供的基于表单的登录似乎是基于这样的假设:用户将在尝试访问“安全”的内容时被重定向到单独的登录页面,这不是什么我想要发生。

所以我想我想知道的是,是否有一种标准方法允许用户使用容器管理安全性或某些第三方库在单页ajax应用程序中登录?我将看一下Spring安全性,但乍一看它似乎与标准安全性有同样的问题。

编辑:发现这非常有用,认为它可能是我的解决方案的基础http://www.jroller.com/sjivan/entry/ajax_based_login_using_aceci

4 个答案:

答案 0 :(得分:0)

我过去曾使用过Spring Security,虽然我没有专门用它来做这件事,但我记得它非常可插拔。虽然如果用户未经身份验证要采取的经典操作是重定向到登录表单页面,您可以使用提供的几个类中的一个来改变这种情况下的行为,或者很容易编写自己的,这将为您做任何事情想要(在这种情况下,通过它的外观返回一个适当的AJAX响应)。

由于遗留原因,我最终必须实施的逻辑非常糟糕,我仍然能够毫无困难地完成它。我不怀疑你是否可以让Spring Security在这方面工作(如果他们已经为你的要求提供了特定的课程,我也不会感到惊讶。)

答案 1 :(得分:0)

嘿Mike,我正在通过相同的过程 - 试图找出将Spring Security,Apache Shiro等安全软件包集成到ajax世界的最佳实践。

据我所知,到目前为止,在一天结束时(无论您使用哪个安全包来实现授权和身份验证),您为检查用户是否经过身份验证而进行的ajax调用都必须调用一个servlet,它呈现一个响应(例如json或xml),然后客户端上的javascript可以处理并做出适当的反应(在线显示登录表单等)。

以下是我理解的流程:

  1. 初始浏览器请求,示例: http://mysite/homepage
  2. 服务器呈现页面(使用任何一个) 过多的java框架 例如,简单的 servlet,jsp,jsf等等)
  3. 呈现的页面包含某种形式 javascript库(gwt,jquery, 原型等)
  4. javascript库生成异步 请求。必须提出此请求 到java servlet所在的url 容器知道用json回应 和/或xml而不是html。例如,http://mysite/ajax/isAuthenticated
  5. 客户端上的javascript侦听 响应。
  6. 客户端上的javascript解析json / xml 响应并显示登录 页面,或继续下一件事。
  7. 服务器端+客户端框架可能有数百种组合来帮助解决这个问题。到目前为止,我已经尝试过grails + prototype,grails + jquery,grails + gwt,简单的servlet + gwt,目前正在研究使用Spring MVC + Gwt。另外,在java世界之外,我刚刚开始阅读Ruby on Rails(据我所知,它基本上是为了使客户端和服务器之间的ajax通信变得容易)。我还没找到真正适合我的那个,所以如果你有运气,请告诉我你的结果!

答案 2 :(得分:0)

发现类似的问题已在Spring安全论坛上得到解答

http://forum.springsource.org/showthread.php?t=80549

不像我希望的那样直截了当,但是一旦你掌握了Spring Security的速度,这看起来是一个很好的建议 - 我现在可以暂时登录并专注于其他功能。 如果我实现解决方案,将在此处更新。

答案 3 :(得分:0)

好的 - 有一个基本的解决方案,我不是说它是最好的,但看起来它会起作用。

它基于Sanjiv Jivan的博客文章

http://www.jroller.com/sjivan/entry/ajax_based_login_using_aceci

编辑:刚刚阅读了该帖子上的评论,看起来可能还有另外一种方法可以做到,也就是帖子已经3年多了,所以如果有更好的解决方案就不会感到惊讶,也许在Spring或J2EE中使用新功能。但是我现在要坚持这个。

他在那里做了很好的记录,所以我只是在这里评论我已经有了一个基本的例子,首先是复制Spring Security示例应用程序,然后按照Sanjiv的描述添加ServletFilter。

当他使用早期版本的Acegi Security(现在称为Spring Security)时,需要进行一两处更改:

url模式现在是“/j_spring_security_check”(不是“/j_acegi_security_check”),我发现我必须添加一个名为“ajax”的输入来使isAjaxRequest方法返回true - 猜测我错过了javascript中的内容。

必须更改过滤器中的一行以检查“login_error”而不是“login_error = 1”,猜测在更新版本的SpringSecurity中发生了变化。即:

               if (redirectURL.indexOf("login_error") == -1) {  

另外,由于我使用的是jquery而不是原型,我使用javascript创建了一个基本的html页面,以便使用jquery进行测试。

此刻粗糙且准备就绪,显示的状态只是“url:/ msgbrd /”或“错误:凭据错误”,但可以轻松整理它。

如果它有帮助,这是我的示例index.html:

    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Insert title here</title>
<script type="text/javascript" src="jquery-1.3.2.js"></script>
<script type="text/javascript" src="jquery.form.js"></script>
<script type="text/javascript">

var loginOptions = { 
beforeSubmit:  postingLogin,  // pre-submit callback 
success:       showResponse,  // post-submit callback 
    type: 'post',
    url: '/msgbrd/j_spring_security_check'  ,
    clearForm: true
}; 


$(document).ready(function(){
    $('#loginForm').ajaxForm( loginOptions );   
        });


function postingLogin() {
    console.log("Login posting: ");

}
function doneLogin() {

    console.log("Login posted ");
}
function showResponse(responseText, statusText)  { 
    $("#statusMessage").empty();
    $("#statusMessage").append( responseText); 
} 

</script>


</head>
<body>
<h1>msgbrd</h1>
<div>
<form id="loginForm" action="" method="POST">
<p><label for="username"> User Name: </label> <input id="username"
    type="text" name="j_username" class="loginText"></p>

<p><input id="ajax" name="ajax" value="ajax"></input></p>
<p><label for="password"> Password: </label> <input id="password"
    type="password" name="j_password" class="loginText"
    onkeydown="loginOnEnter(event);"></p>

<p><label for="remember_me"> <input id="remember_me"
    type="checkbox" name="_acegi_security_remember_me">Remember Me</label>
</p>


<p><input type="submit" value="Go"></input></p>
<p id="statusMessage"></p>
</form>
</div>
</body>
</html>