在JNLP中继续浏览器会话

时间:2013-05-01 05:37:50

标签: java session jnlp java-web-start

我们在Tomcat6上启用了基本身份验证。用户在浏览器中进行身份验证,然后启动JNLP以在Java Web Start中启动应用程序。在启动时,java web start尝试从服务器下载jar文件,但它没有使用已经过浏览器验证的同一会话。基于论坛,我试图通过使用sid属性在JNLP中传递会话ID,并在URL中附加。环境受到限制,因此每个请求都需要进行身份验证,我们不能说要排除对未经过身份验证的jar文件的请求。下面是我的JSP创建JNLP文件,任何人都可以请求帮助我们如何继续相同的会话下载已经被浏览器验证的jar。

<% response.setContentType("application/x-java-jnlp-file"); %>
<%= "<?xml version=\"1.0\" encoding=\"utf-8\"?>" %>
<!-- JNLP File for SimpleTableDemo -->
<%
String baseURL = request.getRequestURL().toString().replace(request.getRequestURI(), request.getContextPath());
%>
<jnlp codebase="<%=baseURL%>">

    <information>
        <title>Simple Table Demo Application</title>
        <vendor>Try</vendor>
        <description>SimpleTableDemo</description>
        <description kind="short">An application that demonstrates a simple table.</description>
    </information>

    <resources>
        <j2se version="1.6+" />
        <property name="sid" value="<%=request.getSession().getId()%>" />
        <property name="serviceHost" value="<%=request.getServerName()%>"/>
        <property name="servicePort" value="<%=request.getServerPort()%>"/> 
        <jar href="AuthenticateJNLPJars.jar;JSESSIONID=<%=request.getSession().getId()%>" />
    </resources>

    <application-desc main-class="SimpleTableDemo" >
    </application-desc>
</jnlp>

4 个答案:

答案 0 :(得分:3)

我现在有(一些)答案......

我意识到这个问题已经有一年了,但由于这是谷歌在搜索此问题时的第一个结果,我认为完成它是一个好主意。

您提供的jnlp代码存在一个问题,但首先,您必须检查是否将cookie添加到网址实际上是否有用.....这取决于您的应用部署配置。

我不知道Tomcat是怎么回事......我正在使用weblogic,在其中你必须在weblogic.xml中检查以下属性

 <session-descriptor>
      <url-rewriting-enabled>true</url-rewriting-enabled>
 </session-descriptor>

这意味着,如果可用,weblogic将从URL获取会话ID(使用您在代码中使用的相同格式)

如果它是假的,那么这个解决方案将不起作用,你将不得不在每个请求中发送一个带有会话ID的cookie ....如果你找到了一个方法,那就请回复....会帮助我很多。

现在,如果url-rewriting-enable为true,那么一旦你在脚本中修复了以下问题,这种方法就会起作用。

问题在于,一旦java web start从浏览器获取jnlp,它将再次从服务器下载它,因此您必须确保将会话ID添加到该请求中。你通过修改这样的初始标签来做到这一点:

<jnlp spec="1.0+" codebase="<%=baseURL%>" href="<%=NAME_OF_JNLP%>;JSESSIONID=<%=SESSION_ID%>"> 

就是这样,代码应该有用......

顺便说一句,您添加的属性:

<property name="sid" value="<%=request.getSession().getId()%>" />
<property name="serviceHost" value="<%=request.getServerName()%>"/>
<property name="servicePort" value="<%=request.getServerPort()%>"/> 

与此无关,您可以删除它们,代码仍然有效。

答案 1 :(得分:2)

(我没有足够的权限来添加评论,因此我将此作为单独的答案。)

Argod写道:

  

问题在于,一旦java web start从浏览器获取jnlp,它将再次从服务器下载它,因此您必须确保将会话ID添加到该请求中。你通过修改这样的初始标签来做到这一点:

<jnlp spec="1.0+" codebase="<%=baseURL%>" href="<%=NAME_OF_JNLP%>;JSESSIONID=<%=SESSION_ID%>">

Argod,当您向 jnlp 元素添加 href 属性时,实际上让JWS再次从服务器下载jnlp文件。

结帐Unofficial Java Web Start/JNLP FAQ。以下是它的说法:

  

一个技巧是确保不在servlet发送回Web Start的JNLP文件中包含href属性。这将告诉Web Start禁用对JNLP文件的更新检查,并且Web Start不会将每个新的JNLP文件视为应用程序更新 - 仅更新的jar文件。

我刚刚在本地检查了这个。使用 href 属性,jnlp文件实际上会被下载三次,并且jar文件会被下载一次。请参阅我的Tomcat日志:

127.0.0.1 ... "GET /my-servlet/jws/myjws.jnlp;JSESSIONID=58080491243456B6A653682FA0A3A738 HTTP/1.1" 200 741
127.0.0.1 ... "GET /my-servlet/jws/myjws.jnlp;JSESSIONID=58080491243456B6A653682FA0A3A738 HTTP/1.1" 200 741
127.0.0.1 ... "GET /my-servlet/jws/myjws.jnlp;JSESSIONID=342082FEA657D765699EADAF5486E9A7 HTTP/1.1" 200 741
127.0.0.1 ... "GET /my-servlet/jws/myjws.jar;JSESSIONID=342082FEA657D765699EADAF5486E9A7 HTTP/1.1" 200 7555

注意最后如何分配新的JSESSIONID,这很糟糕。另一方面,没有 href 属性,jnlp文件下载一次,jar文件下载一次,JSESSIONID被保留:

127.0.0.1 ... "GET /my-servlet/jws/myjws.jnlp;JSESSIONID=58080491243456B6A653682FA0A3A738 HTTP/1.1" 200 672
127.0.0.1 ... "GET /my-servlet/jws/myjws.jar;JSESSIONID=58080491243456B6A653682FA0A3A738 HTTP/1.1" 200 7555

另一个值得关注的问题是,像“sid”,“serviceHost”,“servicePort”这样的prorerty名称(如使用的OP)将被JWS拒绝。

<property name="sid" value="<%=request.getSession().getId()%>" />
<property name="serviceHost" value="<%=request.getServerName()%>"/>
<property name="servicePort" value="<%=request.getServerPort()%>"/>

再次查看Unofficial Java Web Start/JNLP FAQ。以下是它的说法:

  

如果属性为“trusted”,则只能在XML启动文件中设置不受信任/未签名的应用程序的属性。目前受信任的属性包括:

     
      
  • javaws的。*
  •   
  • JNLP。*
  •   
  • javax.swing.defaultlf
  •   
  • sun.java2d.noddraw
  •   
     

换句话说,如果你想用javaws将你自己的属性传递给你的应用前缀,例如,使用javaws.myproperty而不是myproperty。

这同样适用于受信任/签名的JWS应用程序。

答案 2 :(得分:1)

因为您使用JSP创建JNPL,所以您可以使用某个安全令牌或会话ID向您的applet传递参数,然后您的applet必须在来自服务器的请求信息时传递该值。

检查一下: Generate JNLP dynamically

答案 3 :(得分:0)

你真的很接近!,但你的安全层需要更多组件。

密钥是baseURL变量,创建指向servlet的URL,而不是响应applet所需的文件,并向其附加安全令牌或票证。像这样:

/codebaseServlet/ABC123123

使codebaseServlet提取并验证安全令牌并使用请求的文件进行响应。 现在可以随意实现您的安全性。您可以使安全令牌在一段时间内有效,或者在用户会话存在时,验证请求即将到来的IP表单等。

检查: http://docs.oracle.com/javase/6/docs/technotes/guides/jweb/applet/codebase_determination.html