“Java”目录存档

使用CRLFFilter过滤HTTP应答头信息名称和值的非法字符防止CRLF注入攻击

2010年11月29日,星期一

使用CRLFFilter过滤http应答中头信息名称和值的非法字符,防止CRLF注入攻击
经过测试Resin的response.addHeader方法也没做header名字和值的检查,因此如果webapp代码写法不当的话,将导致CRLF注入攻击,

例如一个页面从url参数中获取地址燃尽进行跳转,如果url地址存在“%0d%0a”编码表示的CRLF而未被检测过滤(.net.URL解析不会出错,必须用java.net.URI才行),将产生安漏洞。

通过下面的代码可以重现这个Xss漏洞攻击。
jsp代码:
<%
response.addHeader(“X-Locationaaa: http://mqq.im/\r\nX-tesh”,”aaa”);
response.addHeader(“X-Locationbbb: 汉字/\r\nX-teshbbb”,”aaa”);

//下面的goUrl可以从URL的参数中获取,如果url地址存在“%0d%0a”编码表示的CRLF而未被检测过滤(java.net.URL解析不会出错,必须用java.net.URI才行),将产生漏洞。

String goUrl=”http://lizongbo.com/\r\nX-Location: http://618119.com/”;
//goUrl=java.net.URLEncoder.encode(goUrl, “UTF-8″);
response.sendError(403,goUrl);
%>

在Firefox中访问jsp,使用Live HTTP headers 可以看到生成的实际head如下:

HTTP/1.1 403 http://lizongbo.com/
X-Location: http://618119.com/
Server: /4.0.10
X-Locationaaa: http://mqq.im/
X-tesh: aaa
X-Locationbbb: 汉字
X-teshbbb: aaa
Content-Type: text/html; charset=utf-8
Content-Length: 216
Date: Tue, 09 Nov 2010 02:37:48 GMT

因此封装过滤器代码如下:
[code]
package com.lizongbo.web.;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletResponse;

public class CRLFFilter implements Filter {

@Override
public void destroy() {

}

@Override
public void doFilter(ServletRequest req, ServletResponse res,
FilterChain chain) throws IOException, ServletException {
HttpServletResponse response = new CRLFFilterResponseWrapper(
(HttpServletResponse) res);
chain.doFilter(req, response);
}

@Override
public void init(FilterConfig config) throws ServletException {

}

}

[/code]

[code]
package com.lizongbo.web.filter;

import java.io.IOException;
import java.util.Arrays;

import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;

public class CRLFFilterResponseWrapper extends HttpServletResponseWrapper {
/**
* http name 不允许出现的字符
*/
private static final char[] headerName_tspecials = new char[] { '(', ')',
'<', '>', '@', ',', ';', ':', '\\', '\"', '/', '[', ']', '?', '=',
'{', '}' };
static {
Arrays.sort(headerName_tspecials);
}

HttpServletResponse response = null;

public CRLFFilterResponseWrapper(HttpServletResponse response)
throws IOException {
super(response);
this.response = response;
}

@Override
public void addHeader(String name, String value) {
super.addHeader(filterHeaderName(name), filterHeaderValue(value));
}

@Override
public void sendError(int sc, String msg) throws IOException {
super.sendError(sc, filterHeaderValue(msg));
}

@Override
public void sendRedirect(String location) throws IOException {
super.sendRedirect(filterHeaderValue(location));
}

@Override
public void setHeader(String name, String value) {
super.setHeader(filterHeaderName(name), filterHeaderValue(value));
}

@Override
public void setStatus(int sc, String sm) {
super.setStatus(sc, filterHeaderValue(sm));
}

@Override
public void addDateHeader(String name, long date) {
super.addDateHeader(filterHeaderName(name), date);
}

@Override
public void addIntHeader(String name, int value) {
super.addIntHeader(filterHeaderName(name), value);
}

@Override
public void setDateHeader(String name, long date) {
super.setDateHeader(filterHeaderName(name), date);
}

@Override
public void setIntHeader(String name, int value) {
super.setIntHeader(filterHeaderName(name), value);
}
@Override
public void setContentType(String contentType) {
super.setContentType(filterHeaderValue(contentType));
}

/**
*过滤头信息名字中的非法字符,避免CRLF注入攻击

Many HTTP/1.1 header field values consist of words separated by LWS<br/>
or special characters. These special characters MUST be in a quoted<br/>
string to be used within a parameter value.<br/>

token          = 1*<any CHAR except CTLs or tspecials><br/>

tspecials      = "(" | ")" | "<" | ">" | "@"<br/>
| "," | ";" | ":" | "\" | <"><br/>
| "/" | "[" | "]" | "?" | "="<br/>
| "{" | "}" | SP | HT <br/>
CTL            = <any US-ASCII control character<br/>
(octets 0 - 31) and DEL (127)><br/>
SP             = <US-ASCII SP, space (32)><br/>
HT             = <US-ASCII HT, horizontal-tab (9)><br/>

* @param name
* @return
*/
private static String filterHeaderName(String name) {
if (name == null || name.length() < 1) {
return "null";
}
StringBuilder sb = new StringBuilder(name.length());
for (int i = 0; i < name.length(); i++) {
char c = name.charAt(i);
if (c > 32 && c < 127
&& Arrays.binarySearch(headerName_tspecials, c) < 0) {
sb.append(c);
}
}
return sb.toString();
}

/**
*过滤头信息值中的非法字符,避免CRLF注入攻击

* field-value = *( field-content | LWS )<br/>
*
* field-content = <the OCTETs making up the field-value<br/>
* and consisting of either *TEXT or combinations<br/>
* of token, tspecials, and quoted-string><br/>
*
* @param value
* @return
*/
private static String filterHeaderValue(String value) {
if (value == null || value.length() < 1) {
return "null";
}
StringBuilder sb = new StringBuilder(value.length());
for (int i = 0; i < value.length(); i++) {
char c = value.charAt(i);
if (c >= 32 && c < 127) {
sb.append(c);
}
}
return sb.toString();
}

public static void main(String[] args) {
String headName = "aaaa aaa\r\n bbb ";
String headvalue = "cccccccccc\r\n ddd";
System.out.println(headName + "==" + filterHeaderName(headName));
System.out.println(headvalue + "==" + filterHeaderValue(headvalue));
}
}
[/code]

参考链接:

http://www.ietf.org/rfc/rfc2068.txt

http://www.acunetix.com/websitesecurity/crlf-injection.htm

http://comic.sjtu.edu.cn/bbs/view.asp?TID=4118

Tags: , , , ,

根据sitemap.org的schema使用JAXB生成sitemap.xml的读写方法

2010年11月21日,星期日

根据sitemap.org的schema使用JAXB生成sitemap.xml的读写方法

sitemap协议的中文说明在:

http://sitemaps.org/zh_CN/protocol.php

对应的schema在:
的 XML 格式定义: http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd
Sitemap 索引文件格式定义:http://www.sitemaps.org/schemas/sitemap/0.9/siteindex.xsd
向google提交sitemap.xml是在:

https://www.google.com/webmasters/tools/home?hl=zh_CN

向百度提交sitemap.xml是在:http://sitemap.baidu.com/

xsd文件生成java代码的操作步骤如下:
1.下载xsd文件保存到D:\dev\xsds。
2.在JDK的bin目录下运行xjc命令生成java文件:
D:\dev\\1.6.0_22\bin>xjc -d D:\dev\javasrc -p com.lizongbo.web.sitemaps.sitemap D:\dev\xsds\sitemap.xsd
parsing a schema…
compiling a schema…
com\lizongbo\web\sitemaps\sitemap\ObjectFactory.java
com\lizongbo\web\sitemaps\sitemap\TChangeFreq.java
com\lizongbo\web\sitemaps\sitemap\TUrl.java
com\lizongbo\web\sitemaps\sitemap\Urlset.java
com\lizongbo\web\sitemaps\sitemap\package-info.java

D:\dev\Java\jdk1.6.0_22\bin>xjc -d D:\dev\javasrc -p com.lizongbo.web.sitemaps.siteindex D:\dev\xsds\siteindex.xsd
parsing a schema…
compiling a schema…
com\lizongbo\web\sitemaps\siteindex\ObjectFactory.java
com\lizongbo\web\sitemaps\siteindex\Sitemapindex.java
com\lizongbo\web\sitemaps\siteindex\TSitemap.java
com\lizongbo\web\sitemaps\siteindex\package-info.java
3.将java文件都复制到java工程的src目录的对应包中。
4.将xsd文件复制到java工程的com.lizongbo.web.sitemaps包对应的文件夹中。
5.封装工具类SitemapUtil.java,代码如下:
[code]
package com.lizongbo.web.sitemaps;

import java.io.StringReader;
import java.io.StringWriter;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;

import org.xml.sax.SAXException;

import com.lizongbo.web.sitemaps.siteindex.Sitemapindex;
import com.lizongbo.web.sitemaps.siteindex.TSitemap;
import com.lizongbo.web.sitemaps.sitemap.TUrl;
import com.lizongbo.web.sitemaps.sitemap.Urlset;
import com.lizongbo.web.sitemaps.sitemap.ObjectFactory;

/**
* 通过jaxb对sitemap.xml进行生成和解析的工具类
*
* @author lizongbo
*
*/
public class SitemapUtil {
private final static ObjectFactory sitemapFac = new ObjectFactory();
private final static com.lizongbo.web.sitemaps.siteindex.ObjectFactory siteindexFac = new com.lizongbo.web.sitemaps.siteindex.ObjectFactory();
private final static String SITEMAP_SCHEMA_LOCATION = "http://www.sitemaps.org/schemas/sitemap/0.9 "
+ "http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd";
private final static String SITEINDEX_SCHEMA_LOCATION = "http://www.sitemaps.org/schemas/sitemap/0.9 "
+ "http://www.sitemaps.org/schemas/sitemap/0.9/siteindex.xsd";
private final static String DOCTYPE = "<?xml version=\"1.0\" encoding=\"utf-8\"?>";
private final static String ProcessingInstruction = "<?xml-stylesheet type=’text/xsl’ href=’http://618119.com/wp-content/plugins/google-sitemap-generator/sitemap.xsl’ ?>";

public static Sitemapindex createSitemapindex() {
return siteindexFac.createSitemapindex();
}

public static TSitemap createTSitemap() {
return siteindexFac.createTSitemap();
}

public static TUrl createTUrl() {
return sitemapFac.createTUrl();
}

public static Urlset createUrlset() {
return sitemapFac.createUrlset();
}

public static String getSitemapXML(Urlset urlset) throws JAXBException,
SAXException {
JAXBContext jc = JAXBContext
.newInstance("com.lizongbo.web.sitemaps.sitemap");
Marshaller m = jc.createMarshaller();
StringWriter sw = new StringWriter();
sw.append(DOCTYPE).append("\n");
sw.append(ProcessingInstruction).append("\n");
//设置xml文本编码
m.setProperty(Marshaller._ENCODING, "UTF-8");
//设置为格式化输出结果
m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
//设置为只输出xml节点片段
m.setProperty(Marshaller.JAXB_FRAGMENT, Boolean.TRUE);
//指定xsd路径
m.setProperty(Marshaller.JAXB_SCHEMA_LOCATION, SITEMAP_SCHEMA_LOCATION);
SchemaFactory sf = SchemaFactory
.newInstance(javax.xml.XMLConstants.W3C_XML_SCHEMA_NS_URI);
Schema schema = sf.newSchema(SitemapUtil.class
.getResource("sitemap.xsd"));
//绑定Schema进行校验
m.setSchema(schema);
m.marshal(urlset, sw);
return sw.toString();
}

public static Urlset getUrlset(String xml) throws JAXBException,
SAXException {
JAXBContext jc = JAXBContext
.newInstance("com.lizongbo.web.sitemaps.sitemap");
Unmarshaller um = jc.createUnmarshaller();
SchemaFactory sf = SchemaFactory
.newInstance(javax.xml.XMLConstants.W3C_XML_SCHEMA_NS_URI);
Schema schema = sf.newSchema(SitemapUtil.class
.getResource("sitemap.xsd"));
um.setSchema(schema);
return (Urlset) um.unmarshal(new StringReader(xml));
}

public static String getSitemapindexXML(Sitemapindex sitemapindex)
throws JAXBException, SAXException {
JAXBContext jc = JAXBContext
.newInstance("com.lizongbo.web.sitemaps.siteindex");
Marshaller m = jc.createMarshaller();
StringWriter sw = new StringWriter();
sw.append(DOCTYPE).append("\n");
sw.append(ProcessingInstruction).append("\n");
m.setProperty(Marshaller.JAXB_ENCODING, "UTF-8");
m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
m.setProperty(Marshaller.JAXB_FRAGMENT, Boolean.TRUE);
m.setProperty(Marshaller.JAXB_SCHEMA_LOCATION,
SITEINDEX_SCHEMA_LOCATION);
SchemaFactory sf = SchemaFactory
.newInstance(javax.xml.XMLConstants.W3C_XML_SCHEMA_NS_URI);
Schema schema = sf.newSchema(SitemapUtil.class
.getResource("siteindex.xsd"));
m.setSchema(schema);
m.marshal(sitemapindex, sw);
return sw.toString();
}

public static Sitemapindex getSitemapindex(String xml)
throws JAXBException, SAXException {
JAXBContext jc = JAXBContext
.newInstance("com.lizongbo.web.sitemaps.siteindex");
Unmarshaller um = jc.createUnmarshaller();
SchemaFactory sf = SchemaFactory
.newInstance(javax.xml.XMLConstants.W3C_XML_SCHEMA_NS_URI);
Schema schema = sf.newSchema(SitemapUtil.class
.getResource("siteindex.xsd"));
um.setSchema(schema);
return (Sitemapindex) um.unmarshal(new StringReader(xml));
}

public static void main(String[] args) throws JAXBException, SAXException {
Urlset urlset = SitemapUtil.createUrlset();
TUrl url = SitemapUtil.createTUrl();
url.setLoc("http://lizongbo.com");
urlset.getUrl().add(url);
String xml = getSitemapXML(urlset);
System.out.println(xml);
xml = xml.replace("lizongbo", "");
System.out.println(getSitemapXML(getUrlset(xml)));
Sitemapindex sitemapindex = SitemapUtil.createSitemapindex();
TSitemap tSitemap = SitemapUtil.createTSitemap();
tSitemap.setLoc("http://618119.com/sitemap.xml");
sitemapindex.getSitemap().add(tSitemap);
xml = getSitemapindexXML(sitemapindex);
System.out.println(xml);
xml = xml.replace("lizongbo", "google");
System.out.println(getSitemapindexXML(getSitemapindex(xml)));
}
}

[/code]

Tags: , , , , , ,

在Ubuntu 10.04上安装JDK1.6.0_21和编译配置Resin4.0.12

2010年10月24日,星期日

在Ubuntu 10.04上安装JDK1.6.0_21和编译配置Resin4.0.12

1.首先是安装最新版的jdk,先下载JDK 1.6.0_21(来源:http://www.oracle.com/technetwork/java/javase/downloads/index.html):
root@618119.com:/usr/local/app$ wget “http://cds.sun.com/***/jdk-6u21--x64.bin”
这个url里带有会话信息,现在已经无效,JDK的官方下载不提供简洁的下载地址,需要每次到页面区获取下载地址)
2.再将下载到的文件改名:
root@618119.com:/usr/local/app$ mv jdk-6u21-linux-x64.bin\?BundledLineItemUUID\=SSeJ_hCwV9QAAAEroI4AHoII\&OrderID\=gVSJ_hCwmL8AAAErko4AHoII\&ProductID\=xKiJ_hCySHIAAAEpT7wzBGsB\&FileName\=%2Fjdk-6u21-linux-x64.bin   jdk-6u21-linux-x64.bin
3.给安装程序加上可执行权限:
root@618119.com:/usr/local/app$ chmod +x ./jdk-6u21-linux-x64.bin
4.开始安装JDK:
root@618119.com:/usr/local/app$ ./jdk-6u21-linux-x64.bin
(JDK安装好之后,可以通过符号连接建立jdk目录,这样在一行升级jdk版本的时候通过修改符号连接自动切换到新版本jdk:
root@618119.com:/usr/local/app# ln -s ./jdk1.6.0_21/ ./jdk )
5.然后添加环境变量到系统:
编辑 /etc/enviroment增加下面一行:
_HOME=”/usr/local/app/jdk1.6.0_21″
添加后的/etc/environment内容如下:
root@618119.com:/etc# more /etc/environment
PATH=”/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games”
JAVA_HOME=”/usr/local/app/jdk1.6.0_21″
6.再开始下载resin4.0.12(来源:http://www.caucho.com/download/)
root@618119.com:/usr/local/app# wget http://www.caucho.com/download/resin-4.0.12.tar.gz
7.解压安装文件:
root@618119.com:/usr/local/app# tar -zxvf *
7.进入resin目录开始编译安装,安装目录设置为:/usr/local/app/resin
root@618119.com:/usr/local/app# cd resin*
root@618119.com:/usr/local/app/resin-4.0.12# ./configure –prefix=/usr/local/app/resin
root@618119.com:/usr/local/app/resin-4.0.12# make
root@618119.com:/usr/local/app/resin-4.0.12# make install
8.可以看到系统服务脚本已经生成:
root@618119.com:/etc/init.d# more /etc/init.d/resin
9.尝试启动resin 4.0.12,失败了:
root@618119.com:/usr/local/app/resin/# /usr/local/app/resin/bin/resin.sh start启动不了:
启动不了的原因是因为是root登录的。
Resin从4.0版本起,在默认的resin.xml里配置判断条件,如果当前用户名是root,则resin的watchdog监控进程使用www-data这个用户名来启动真正的resin进程。
root@618119.com:/usr/local/app/resin/bin# ./resin.sh start
然后root@618119.com:/usr/local/app/resin/bin# ./resin.sh shutdown
root@618119.com:/usr/local/app/resin/bin# tail ../log/*.log
可以看到出错日志如下:
—————————————————————————–

com.caucho.config.ConfigRuntimeException: java.io.IOException: Cannot create directory: /usr/local/app/resin/resin-data/default
at com.caucho.config.ConfigException.create(ConfigException.java:168)
at com.caucho.server.resin.Resin.configure(Resin.java:1006)
at com.caucho.server.resin.Resin.initMain(Resin.java:983)
at com.caucho.server.resin.Resin.main(Resin.java:1230)
Caused by: java.io.IOException: Cannot create directory: /usr/local/app/resin/resin-data/default
at com.caucho.vfs.FilePath.mkdirs(FilePath.java:489)
at com.caucho.env.service.RootDirectoryService.<init>(RootDirectoryService.java:81)
at com.caucho.server.resin.Resin.configureRoot(Resin.java:1073)
at com.caucho.server.resin.Resin.configure(Resin.java:1001)
… 2 more

—————————————————————————–

[2010/10/18 15:35:45.200] http listening to localhost:6600
[2010/10/18 15:35:45.289]
[2010/10/18 15:35:47.084] Watchdog detected close of Resin[,pid=20430]
exit reason: BAD_CONFIG (exit code=2)
[2010/10/18 15:35:48.814] Watchdog detected close of Resin[,pid=20454]
exit reason: BAD_CONFIG (exit code=2)
[2010/10/18 15:35:50.563] Watchdog detected close of Resin[,pid=20476]
exit reason: BAD_CONFIG (exit code=2)
[2010/10/18 15:35:52.470] Watchdog detected close of Resin[,pid=20508]
exit reason: BAD_CONFIG (exit code=2)

—————————————————————————–

10.解决办法为:注释resin.xml里的第147到150行:
root@618119.com:/usr/local/app/resin/conf# vi ./resin.xml

147 <!–      <resin:if test=”${resin.userName == ‘root’}”>
148         <user-name>www-data</user-name>
149         <group-name>www-data</group-name>
150       </resin:if> –>

11.然后再运行
root@618119.com:/usr/local/app/resin/bin# ./resin.sh start
或者root@618119.com:/usr/local/app/resin/bin# /etc/init.d/resin start
均可正常启动了。

12.再运行下面的命令将resin也添加为系统默认的服务:
root@618119.com:/etc# sudo /usr/sbin/update-rc.d -f resin defaults

13.修改resin配置允许外网访问resin-admin,编辑/usr/local/app/resin/conf/resin.xml,找到
<resin:set var=”resin_admin_external” value=”false”/>
改为:
<resin:set var=”resin_admin_external” value=”true”/>
保存resin.xml,重启resin。
root@618119.com:/usr/local/app/resin/conf# /usr/local/app/resin/bin/resin.sh restart

14:访问http://618119.com:8080/resin-admin/,因为是第一次访问,可以生成帐号和密码。
我的username设置为:resinadmin,Password设置为:618119.com(密码一定要用不容易被人猜到的),Realm保持为resin不变。
点“Create Configuration File”进行提交,生成的文件为:/usr/local/app/resin/conf/admin-users.xml.generated
15.将生成的文件改名为admin-users.xml:
root@618119.com:/usr/local/app/resin/conf# mv admin-users.xml.generated  admin-users.xml
然后resin会自动重新加载.
16.再访问http://localhost:8080/resin-admin/,输入刚才帐号和密码,登录之后,就可以看到服务器状态信息了。

接下来配置外网访问JMX管理。
由于jdk的jmx管理端口启动时无法绑定指定的ip,默认是绑定到所有ip的,因此在公网上开放jmx端口时,必须设置jmx访问的帐号和密码:
操作步骤如下:
在/usr/local/app/resin/conf建立jmx权限配置文件:
1.复制jdk提供的jmx帐号和密码配置文件模板到resin的conf目录:
root@618119.com:/usr/local/app/resin/conf# cp /usr/local/app/jdk1.6.0_21/jre/lib/management/jmxremote.* /usr/local/app/resin/conf
查看文件:
root@618119.com:/usr/local/app/resin/conf# ls -alh jmxremote.*
-rw-r–r– 1 root root 4.0K Oct 23 14:49 jmxremote.access
-r–r–r– 1 root root 2.8K Oct 23 14:49 jmxremote.password.template
2.在/usr/local/app/resin/conf下重命名:jmxremote.password.template为jmxremote.password:
root@618119.com:/usr/local/app/resin/conf# mv jmxremote.password.template  jmxremote.password
3.给密码文件加上写权限:
root@618119.com:/usr/local/app/resin/conf# chmod +w jmxremote.password
查看文件:
root@618119.com:/usr/local/app/resin/conf# ls -alh jmxremote.*
-rw-r–r– 1 root root 4.0K Oct 23 14:49 jmxremote.access
-rw-r–r– 1 root root 2.8K Oct 23 14:49 jmxremote.password
4.以追加文件方式往jmx权限控制文件中加入一个有读写权限的帐号,帐号名字是resinjmx
root@618119.com:/usr/local/app/resin/conf# echo “resinjmx         readwrite” >> jmxremote.access
查看帐号添加是否ok:
root@618119.com:/usr/local/app/resin/conf# tail jmxremote.access
# Default access control entries:
# o The “monitorRole” role has readonly access.
# o The “controlRole” role has readwrite access and can create the standard
#   Timer and Monitor MBeans defined by the API.

monitorRole   readonly
controlRole   readwrite \
create javax.management.monitor.*,javax.management.timer.* \
unregister
resinjmx         readwrite
5.往jmx权限控制的密码文件中加入resinjmx帐号的密码:618119
root@618119.com:/usr/local/app/resin/conf# echo “resinjmx 618119″ >> jmxremote.password
查看密码信息是否添加ok:
root@618119.com:/usr/local/app/resin/conf# tail jmxremote.password
# or specify another, less accessible file in the management config file
# as described above.
#
# Following are two commented-out entries.  The “measureRole” role has
# password “QED”.  The “controlRole” role has password “R&D”.
#
# monitorRole  QED
# controlRole   R&D

resinjmx 618119

6.修改jmxremote.*的权限,只允许启动resin的用户名对该文件拥有读写权限:
root@618119.com:/usr/local/app/resin/conf# chmod 600 jmxremote.access
root@618119.com:/usr/local/app/resin/conf# chmod 600 jmxremote.password
root@618119.com:/usr/local/app/resin/conf# ls -alh jmxremote.*
-rw——- 1 root root 4.0K Oct 23 14:54 jmxremote.access
-rw——- 1 root root 2.9K Oct 23 14:57 jmxremote.password
(如果文件权限没有正确设置,在启动使用了jmx的resin时,jvm-default.log中的出错信息为:
Error: Password file read access must be restricted: /usr/local/app/resin//conf/jmxremote.password,可以参考:http://www.opennms.org/wiki/Tomcat_6_JMX_How-To
)
7.配置/usr/local/app/resin/conf的resin.xml
在<server-default>节点下加入下列启动参数,并保存resin.xml
<!–
需要在远程服务器上运行hostname -i,如果显示的127.0.0.1,则需要加上下面一行来指定hostname为公网ip
<jvm-arg>-Djava.rmi.server.hostname=75.126.115.214</jvm-arg>
配置该项的时候,java.rmi.server.hostname=127.0.0.1是肯定不行的,我就是这样绕了弯路:
root@618119.com:/usr/local/app/resin/log# hostname -i
75.126.115.214
–>
<jvm-arg>-Dcom.sun.management.jmxremote.port=50000</jvm-arg>
<jvm-arg>-Dcom.sun.management.jmxremote.ssl=false</jvm-arg>
<jvm-arg>-Dcom.sun.management.jmxremote.authenticate=true</jvm-arg>
<jvm-arg>-Dcom.sun.management.jmxremote.password.file=${resin.root}/conf/jmxremote.password</jvm-arg>
<jvm-arg>-Dcom.sun.management.jmxremote.access.file=${resin.root}/conf/jmxremote.access</jvm-arg>

8.重启resin:
root@618119.com:/usr/local/app/resin/conf# /usr/local/app/resin/bin/resin.sh shutdown
Resin/4.0.12 shutdown watchdog at 127.0.0.1:6600
root@618119.com:/usr/local/app/resin/conf# /usr/local/app/resin/bin/resin.sh start
Resin/4.0.12 launching watchdog at 127.0.0.1:6600
Resin/4.0.12 started -server ” for watchdog at 127.0.0.1:6600

9.在本地电脑运行/usr/local/app/jdk1.6.0_21/bin/jconsole,远程进程填上:618119.com:50000,
点“连接”,提示连接失败。
重新在用户名填resinjmx,口令填:618119.com.
连接成功。

resin.xml中的其它设置:
1.resin4.0默认启动了https端口在8443,可以将resin.xm中下面几行注释掉来关闭https功能:

<http address=”127.0.0.1″ port=”8443″>
<jsse-ssl self-signed-certificate-name=”resin@localhost”/>
</http>
2.resin4.0的resin.xml里没将stdout和stderr显示的声明出来了,
可以将stdout,stderr,accesslog配置成按天输出:
<stdout-log path-format=”log/stdout.log.%Y%m%d”
timestamp=”%Y-%m-%d %H:%M:%S”
rollover-period=”1D”/>
<stderr-log path-format=”log/stderr.log.%Y%m%d”
timestamp=”%Y-%m-%d %H:%M:%S”
rollover-period=”1D”/>
<access-log path-format=”log/access.log.%Y%m%d”
format=’%h %l %u %t “%r” %s %b “%{Referer}i” “%{User-Agent}i” “%{X-Real-IP}i”‘
rollover-period=”1D”/>
stdout-log和stderr-log放到resin元素节点下面.
参考:http://618119.com/archives/2009/02/18/135.html

3.增加Java虚拟机 其它的jvm启动参数:
<!–以server方式启动java虚拟机–>
<jvm-arg>-server</jvm-arg>
<!–指定文件编码默认为UTF-8–>
<jvm-arg>-Dfile.encoding=UTF-8</jvm-arg>
<!–输出log4j自身的调试信息–>
<jvm-arg>-Dlog4j.debug=true</jvm-arg>
<!–指定默认语言为英语–>
<jvm-arg>-Duser.language=en</jvm-arg>
<!–启用gc日志–>
<jvm-arg>-verbose:gc</jvm-arg>
<!–指定输出gc日志的路径–>
<jvm-arg>-Xloggc:${resin.root}/log/gc.log</jvm-arg>
<!–gc日志打印gc详细信息–>
<jvm-arg>-XX:+PrintGCDetails</jvm-arg>
<!–gc日志打印时间戳–>
<jvm-arg>-XX:+PrintGCTimeStamps</jvm-arg>

4.配置泛域名方式的虚拟主机(将发给*.lizongbo.com的请求全部转给一个webapp):

<host id=”lizongbo.com” root-directory=”/usr/local/app/resin/vhost/lizongbo.com”>
<host-alias-regexp>^([^/]*).lizongbo.com</host-alias-regexp>
<web-app id=”/” root-directory=”webapps/ROOT”/>
</host>

(host-alias-regexp的正则表达式是用的java的Pattern.compile(name, Pattern.CASE_INSENSITIVE); ,因此是java的标准正则。

lizongbo.com是才申请的,因此使用301永久重定向跳转到 http://618119.com

index.jsp的代码为:<?xml version=”1.0″ encoding=”UTF-8″?>
<%@page contentType=”text/html; charset=UTF-8″ language=”java”
pageEncoding=”UTF-8″%>
<%@ page import=”java.util.*” session=”false”%>
<%
String goURL=”http://618119.com/”;
response.setHeader(“Location”, goURL);
response.setStatus(HttpServletResponse.SC_MOVED_PERMANENTLY);
%>)

5.通过ps aux|grep java可以看到最终启动的resin进程命令为:
/usr/local/app/jdk1.6.0_21/bin/java -server -Dfile.encoding=UTF-8 -Dcom.sun.management.jmxremote.port=50000 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=true -Dcom.sun.management.jmxremote.password.file=/usr/local/app/resin//conf/jmxremote.password -Dcom.sun.management.jmxremote.access.file=/usr/local/app/resin//conf/jmxremote.access -Dlog4j.debug=true -Duser.language=en -verbose:gc -Xloggc:/usr/local/app/resin//log/gc.log -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -Dresin.server=1 -Djava.util.logging.manager=com.caucho.log.LogManagerImpl -Djava.system.class.loader=com.caucho.loader.SystemClassLoader -Djavax.management.builder.initial=com.caucho.jmx.MBeanServerBuilderImpl -Djava.awt.headless=true -Dresin.home=/usr/local/app/resin/ -Xss1m -Xmx256m -Dresin.watchdog= -Djava.util.logging.manager=com.caucho.log.LogManagerImpl -Djavax.management.builder.initial=com.caucho.jmx.MBeanServerBuilderImpl -Djava.awt.headless=true -Dresin.home=/usr/local/app/resin/ -Dresin.root=/usr/local/app/resin/ -Dresin.watchdog= -Djava.util.logging.manager=com.caucho.log.LogManagerImpl -Djavax.management.builder.initial=com.caucho.jmx.MBeanServerBuilderImpl -Djava.awt.headless=true -Dresin.home=/usr/local/app/resin/ -Dresin.root=/usr/local/app/resin/ com.caucho.server.resin.Resin –root-directory /usr/local/app/resin/ -conf /usr/local/app/resin/conf/resin.xml -socketwait 37260 start –log-directory /usr/local/app/resin/log

Tags: , , , , , , ,