- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有一组在Tomcat上运行的Java Applet程序。这些程序跟踪非正式的高尔夫“锦标赛”事件,包括友好的球员比赛。
尽管程序的细节并不重要,但是代码集包含了30,000多个源代码行。我选择Java作为实现语言,以实现可移植性并避免维护问题。我使用Tomcat部署应用程序,并使用javascript调用小程序。我所有的小程序都使用参数,例如事件名称, class 名称和播放日期。
不幸的是,Java和浏览器的更改现在已导致我的应用程序出现维护问题。第一个问题是java添加了对jar文件进行签名的要求。第二个问题是,首先是Chrome,现在是Firefox,已经删除了对NPAPI插件的支持,这实际上从html中删除了Java Applet的支持。
JNLP(Java Web Start)是新的替换。这两个问题都很难解决,因为没有清晰的分步文档详细说明了实际需要执行的操作。
将小程序迁移到JNLP的方法可能有所不同,甚至更好,但是此处描述的过程可以正常工作。但是,在描述它们时,我必须假设您已经知道如何创建Java Web应用程序,因为不需要更新您尚不具备的内容。
我在Windows Cygwin环境中使用Tomcat。我的示例mkJavaKey脚本明确使用了该环境,但是所有Java和javascript代码都是可移植的。 Tomcat使用web.xml定义如何调用Servlet。如果您使用其他部署方法,则我的web.xml文件至少应作为起点。
最佳答案
为什么需要签署jar文件?
我无法回答问题的这一部分。但是,对于任何非平凡的应用程序,您将至少需要完成该过程以对jar文件自签名,即使这种自签名也没有提供真正的额外安全性。任何人都可以使用Java开发工具包中提供的工具对应用程序进行自签名。自签名证书可以很好地进行开发工作,但是每次运行应用程序时都必须单击“风险接受”复选框。
好的,我的应用程序很简单,我需要签名我的jar文件。怎么办?
快速答案:这是一个两步过程。您首先使用keytool程序创建必要的凭据,然后使用jarsigner工具对jar文件进行签名。您只需要偶尔创建一次凭据,但需要对每个部署的jar文件进行签名。
要创建这些凭据(自签名证书),请使用:
$JAVA_HOME/bin/keytool -genkeypair -keyalg RSA -keysize 2048 -alias mydomain -validity 1825
.keystore
的证书,有效期为五年。您必须响应其提示,而我使用“password”作为密码。由于我仅将此证书用于自签名jar文件,因此安全性不是大问题。有效性参数指定证书有效的时间(天)。
applet.jar
,请使用:
$JAVA_HOME/bin/jarsigner -tsa http://timestamp.digicert.com -storepass password applet.jar mydomain
-storepass
后的“密码”与您与keytool一起使用的密码匹配,“mydomain”与keytool的
-alias
参数匹配。您将需要指定-tsa(时间戳认证机构)参数,并且
http://timestamp.digicert.com是(或至少曾经是)一个公开可用的。我不确定TSA到底是做什么的,或者为什么需要它,但是jarsigner不满意它,不会默认它,也不会直接记录如何找到它。
#!/bin/bash
#
# Title-
# mkJavaKey
#
# Function-
# Create a new key using $JAVA_HOME/bin/keytool
#
# Usage-
# mkJavaKey ## CYGWIN ONLY ##
# (This is required when jarsigner complains about an expired key.)
# NOTE: This *REMOVES* and *REPLACES* your existing .keystore file!
#
#######
##########################################################################
# Environment check
if [ -z "$JAVA_HOME" ] ; then
. setupJAVA ## (This personal script sets JAVA_HOME)
if [ -z "$JAVA_HOME" ] ; then
echo "JAVA_HOME environment variable missing"
exit 1
fi
fi
if [ -z "$HOMEPATH" ] ; then
echo "HOMEPATH environment variable missing"
echo "Try export HOMEPATH=\Users\myname"
exit 1
fi
home_path=`cygpath --path --unix C:$HOMEPATH`
PGM=$JAVA_HOME/bin/keytool
if [ ! -x "$PGM" ] ; then
echo "$PGM not executable"
exit 1
fi
##########################################################################
# Create a new .keystore
set -x
rm -Rf $home_path/.keystore
$PGM -genkeypair -keyalg RSA -keysize 2048 -alias mydomain -validity 1825
exit $?
JAVA_HOME
环境变量。对于Linux,请使用
$HOME
而不是
$HOMEPATH
并跳过
cygpath
部分。这些在Cygwin环境中在Linux和Windows文件名格式之间转换。
.PHONY: golfer.install
golfer.install: test golfer
: (Not relevant to discussion)
cp -p $(OBJDIR)/usr/fne/golfer/Applet/applet.jar $(DEPLOYDIR)/webapps/golfer/.
jarsigner -tsa http://timestamp.digicert.com -storepass password "$(shell cygpath --path --windows "$(DEPLOYDIR)/webapps/golfer/applet.jar")" mydomain
: (Not relevant to discussion)
$(OBDIR)
和
$(DEPLOYDIR)
变量与此讨论无关。它们是在我的基于Makefile的构建环境中设置的目录路径。
<applet>
标记将不起作用。两者都不会部署Java.runApplet()。我不会深入说明为什么放弃NPAPI支持,只是要使现有应用程序运行所需做的事情。
//------------------------------------------------------------------------
//
// Title-
// applet.js
//
// Purpose-
// Common applet javascript.
//
// Last change date-
// 2010/10/19
//
//------------------------------------------------------------------------
var out; // Output document
//------------------------------------------------------------------------
// appHead
//
// Generate html header for application.
//------------------------------------------------------------------------
function appHead(title,cname,height,width)
{
var todoWindow= window.open('','','');
out= todoWindow.document;
out.write('<html>');
out.write('<head><title>' + title + '</title></head>');
out.write('<body>\n');
out.write('<applet code="' + cname + '.class"');
out.write(' codebase="./"')
out.write(' archive="applet.jar,jars/common.jar"');
out.write(' width="' + width + '" height="' + height + '">\n');
}
//------------------------------------------------------------------------
// appParm
//
// Add parameter information
//------------------------------------------------------------------------
function appParm(name, value)
{
out.write(' <param-name="' + name + '" value="' + value + '"/>\n');
}
//------------------------------------------------------------------------
// appTail
//
// Generate html trailer information.
//------------------------------------------------------------------------
function appTail()
{
out.write('Your browser is completely ignoring the <APPLET> tag!\n');
out.write('</applet>');
out.write('<form>');
out.write('<input type="button" value="Done" onclick="window.close()">');
out.write('</form>');
out.write('</body>');
out.write('</html>');
out.close();
out= null;
}
//------------------------------------------------------------------------
// cardEvents
//
// Display scorecard for selected date.
//------------------------------------------------------------------------
function cardEvents(eventsID, obj)
{
if( obj.selectedIndex == 0 )
{
alert("No date selected");
return;
}
appHead('Score card', 'EventsCard', '100%', '100%');
appParm('events-nick', eventsID);
appParm('events-date', obj[obj.selectedIndex].value);
appTail();
reset();
}
window.open()
语句也将始终添加
<html>
和
<body>
部分。我也尝试过
document.open("application/x-java-jnlp-file")
。即使指定了mime-type,仍然存在不需要的html和body部分。
//------------------------------------------------------------------------
//
// Title-
// applet.js
//
// Purpose-
// Common applet javascript.
//
// Last change date-
// 2017/03/15
//
//------------------------------------------------------------------------
var out; // Output URL
//------------------------------------------------------------------------
// appHead
//
// Generate application URL header.
//------------------------------------------------------------------------
function appHead(title,cname,height,width)
{
out= cname + ',' + title;
}
//------------------------------------------------------------------------
// appParm
//
// Generate html parameter information.
//------------------------------------------------------------------------
function appParm(name, value)
{
out= out + ',' + name + '=' + value;
}
//------------------------------------------------------------------------
// appTail
//
// Generate html trailer information.
//------------------------------------------------------------------------
function appTail()
{
var specs= 'menubar=yes,toolbar=yes';
window.open('Applet.jnlp?' + out, '_self', specs);
}
//------------------------------------------------------------------------
// cardEvents
//
// Display scorecard for selected date.
//------------------------------------------------------------------------
function cardEvents(eventsID, obj)
{
// (UNCHANGED!)
}
Applet.jnlp,className,description,parm=value,parm=value,...
形式的URL。
//------------------------------------------------------------------------
//
// Method-
// AppletServlet.doGet
//
// Purpose-
// Called for each HTTP GET request.
//
//------------------------------------------------------------------------
public void
doGet( // Handle HTTP "GET" request
HttpServletRequest req, // Request information
HttpServletResponse res) // Response information
throws ServletException, IOException
{
String q= req.getQueryString();
if( debug ) log("doGet("+q+")");
res.setContentType("text/html");
query(req, res);
}
//------------------------------------------------------------------------
//
// Method-
// AppletServlet.putError
//
// Purpose-
// Generate error response.
//
//------------------------------------------------------------------------
public void
putError( // Generate error response
PrintWriter out, // The response writer
String msg) // The error message
{ out.println("<HTML>");
out.println("<HEAD><TITLE>" + msg + "</TITLE></HEAD>");
out.println("<BODY>");
out.println("<H1 align=\"center\">" + msg + "</H1>");
out.println("</BODY>");
out.println("</HTML>");
}
//------------------------------------------------------------------------
//
// Method-
// AppletServlet.query
//
// Purpose-
// Handle a query.
//
//------------------------------------------------------------------------
protected void
query( // Handle a query
HttpServletRequest req, // Request information
HttpServletResponse res) // Response information
throws ServletException, IOException
{
String q= req.getQueryString();
if( debug ) log("query("+q+")");
PrintWriter out = res.getWriter();
String BOGUS= "<br> Malformed request: query: '" + q + "'";
//=====================================================================
// Applet.jnlp?classname,title,parm=value,parm=value,...
int index= q.indexOf(',');
if( index < 0 || index == (q.length() - 1) )
{
putError(out, BOGUS);
return;
}
String invoke= q.substring(0, index);
q= q.substring(index+1);
index= q.indexOf(',');
if( index < 0 )
index= q.length();
String title= q.substring(0, index);
title= java.net.URLDecoder.decode(title, "UTF-8");
// Parameter extraction
Vector<String> param= new Vector<String>();
if( index < q.length() )
{
q= q.substring(index+1);
for(;;)
{
index= q.indexOf(',');
if( index < 0 )
index= q.length();
String s= q.substring(0, index);
int x= s.indexOf('=');
if( x < 0 )
{
putError(out, BOGUS);
return;
}
param.add(s);
if( index >= q.length() )
break;
q= q.substring(index+1);
}
}
//---------------------------------------------------------------------
// We now have enough information to generate the response
//---------------------------------------------------------------------
res.setContentType("application/x-java-jnlp-file");
out.println("<?xml version='1.0' encoding='utf-8'?>");
out.println("<jnlp spec='1.0+' codebase='http://localhost:8080/golfer'>");
out.println(" <information>");
out.println(" <title>" + title + "</title>");
out.println(" <vendor>My Name</vendor>");
out.println(" <description>" + title + "</description>");
out.println(" </information>");
out.println(" <security><all-permissions/></security>");
out.println(" <resources>");
out.println(" <j2se version='1.7+'/>");
out.println(" <jar href='applet.jar'/>");
out.println(" <jar href='jars/common.jar'/>");
out.println(" </resources>");
out.println(" <applet-desc main-class='" + invoke + "' name='" + title + "'" +
" height='90%' width='98%'>");
// Insert applet parameters
for(int i= 0; i<param.size(); i++)
{
String s= param.elementAt(i);
int x= s.indexOf('=');
String n= s.substring(0,x);
String v= s.substring(x+1);
out.println(" <param name='" + n+ "' value='" + v + "'/>");
}
out.println(" </applet-desc>");
out.println("</jnlp>");
}
debug
是我的“启用调试”标志,并且
log()
将调试消息写入stdout。在此新代码版本中,高度和宽度未作为参数传递,而是硬编码。事实证明,在HTML版本中,“100%”始终用作高度和宽度,并且效果很好。由于某些(我不知道)的原因,当使用高度和宽度为100%的.jnlp代码调用时,我的applet窗口在底部被截断,可能在右侧被截断。我使用这些新的高度和宽度参数来解决此格式问题。
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE web-app
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
<servlet>
<servlet-name>Applet</servlet-name>
<servlet-class>usr.fne.golfer.AppletServlet</servlet-class>
<init-param>
<param-name>property-path</param-name>
<param-value>profile</param-value>
</init-param>
<init-param>
<param-name>property-file</param-name>
<param-value>golfer.pro</param-value>
</init-param>
<load-on-startup>30</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Applet</servlet-name>
<url-pattern>/Applet.jnlp</url-pattern>
</servlet-mapping>
: (Other Servlets unchanged)
</web-app>
.jnlp
文件调用Java(TM)Web Start Launcher。在Windows中,您的JWS Launcher是
C:\Program Files\java\jre*\bin\javaws.exe
(使用最新的jre文件夹。)此外,如果您使用Chrome,则下载目录将包含生成的Applet.jnlp文件。您需要不时清理它们。
关于java - 如何升级Tomcat Java Applet以使用JNLP?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43074225/
如果 jnlp 是用 xml 编写的,那么我们是否可以拥有扩展名为 .xml 且没有 jnlp 的任何 taf 的 jnlp 文件?哪个 javascript 方法负责启动沙箱?可能是 createW
我按照此处的步骤操作,并使用选项通过 Web 启动启动从属代理来配置节点。当我在主服务器上保存时,它要求我按预期从浏览器或从服务器启动代理。 https://wiki.jenkins-ci.org/d
这是启动应用程序后弹出错误中显示的 JNLP 文件。我知道问题出在哪里 - 第 21 行没有斜杠。但是这个文件很久以前就被更改了,我将其上传到服务器并刷新了所有内容,但它总是向我显示这个旧文件。
我有一个 1/2 年前运行的小程序。现在我需要“重新激活”它,但由于未知原因它不再工作。以下是规范: 基于 JNLP 的 NG Applet Tomcat 7 JRE 1.7.0_25 Firefox
有没有办法获取下引用的JAR文件在 Java WebStart 的 .jnlp 文件中?我认为 JNLP API 可以提供帮助,但没有找到任何方法。有什么想法吗? 示例: [...]
我正在使用构建文件来编译我的项目。我收到 package javax.jnlp does not exist 错误。我的 java 文件没有任何错误。我已将 javaws.jar 添加到我的项目构建路
我有一个使用 Java webstart 技术的项目。我决定将 Java 版本从 8 升级到 9。但是,我在编译时遇到以下错误: error: package javax.jnlp is not vi
我已经为 Java Web 启动应用程序设置了 Tomcat。现在我在静态 html 页面上提供 .JNLP 文件下载(服务器仅供内部使用)。但是当我点击一个文件而不是下载它时,它会打开并在浏览器中显
如何以编程方式找到 JNLP 文件的路径?我正在使用 Java Web Start 生成 JNLP 文件。我知道您可以手动在资源的 Java 缓存查看器中找到名称为 launch.jnlp 的 JNL
我的计算机操作系统是 Linux-Debian 9 (stretch),我正在运行 Netbeans 8.2 当我想在 Netbeans 上运行任何 JavaFX 项目时,它显示以下错误...“Net
我正在开发一个使用网络摄像头的 JavaFX 应用程序。为了能够访问相机,我被迫使用 opencv 库和 javacv,后者使用 native opencv 共享库。现在我希望 native dll
我尝试重现一个自 Java 7 以来就被破坏的 Java Web Starter 应用程序。它以前工作过。所有 Jar 文件均已签名。 我尝试从 jnlp 文件中获取资源标签的信息。 我使用 Syst
我正在通过Web Start在Mac OS X Leopard上运行Java 32位应用程序。我需要确保VM以32位模式加载。如何在JNLP中做到这一点? 最佳答案 我发布后就找到了答案。在“资源”标
我从未使用过 JNLP,并且我没有运行任何 Web/war 服务器,因此我将从头开始安装它: 使用哪个? 玻璃鱼 Tomcat Apache jetty 另一个? 我想知道已经使用 JNLP 的人是否
我正在尝试弄清楚如何包含对外部数据文件(文本形式)的引用,我希望通过 Web Start (JNLP) 与我的应用程序一起分发该文件。筛选 JNLP 结构的文档,我发现您可以包含对 JAR、nativ
我有一个 Swing 应用程序,我开始使用 JNLP。当我开始使用 JNLP 时,UI 未完全加载。就像只加载顶部任务栏一样,但是当单击任务栏中的按钮(用于连接到数据库)时,整个应用程序会正确加载。就
我需要在浏览器中启动 JNLP 应用程序,而不是在提供 url 并打开它时单独下载。下面是我的 jnlp 文件: Jnlp Testing xxx
所以我已经能够使用 .jnlp 成功启动我的 Java 应用程序。所有 jar 都已正确签名。 但是,当它要求用户运行该应用程序时,它会说 (未验证)我的软件 在供应商部分。 如何删除“未验证”消息。
我已经创建了一个桌面应用程序,因此我计划通过项目文件夹中的 dist.zip 来分发该软件。当我从 netbeans 运行该程序时,一切正常。当我打开 launch.jnlp 文件时,框架将打开,但它
我正在通过 jnlp 启动应用程序,我需要从服务器(Tomcat)读取数据库配置。是否可以连接到主机地址,或者我可以在 jnlp 启动应用程序之前读取属性文件吗? 最佳答案 Is it possibl
我是一名优秀的程序员,十分优秀!