用${jetty.home}和${jetty.base}配置安全

Jetty 9.1中:

 1)${jetty.home}是jetty公布(二进制)的文件夹路径;

 2)${jetty.base}是用户定制化的文件夹路径。

这样分化:

 1)同意你管理多个Jetty安装;

 2)当你升级Jetty后,更easy保留你当前的配置。

很多其它的信息在后面讲《启动Jetty》时会详述。

并且,Jetty 9.1參数化了全部的标准XML配置。比如SSL,參数如今仅是在start.ini中的属性,不须要编辑XML文件。

Jetty 9.1也使用模块。Jetty不再直接的为一个特征列出全部的库、属性和XML文件,改为使用软件模块,而且start.jar机制同意你创建新模块。你定义一个模块在一个modules/*.mod文件里,包含库、依赖、XML、和模板INI文件。你仅仅须要用--module=name命令行选项就可以载入模块。模块使用依赖来控制库和XML文件的顺序,很多其它的信息在《启动Jetty》讲述。

在Jetty 9.1中配置SSL

以下是一个使用${jetty.home}和${jetty.base}配置SSL的样例,当中也包含了模块怎么工作的细节。

这个样例假定你的Jetty公布放在/home/user/jetty-distribution-9.1.0.RC0。

1)创建一个base目录

[/home/user]$ mkdir my-base
[/home/user]$ cd my-base

2)为SSL、HTTP和webapp部署添加模块

[my-base]$ java -jar /home/user/jetty-distribution-9.1.0.RC0/start.jar --add-to-start=ssl,http,deploy

ssl             initialised in ${jetty.base}/start.ini (appended)
ssl enabled in ${jetty.base}/start.ini
DOWNLOAD: http://git.eclipse.org/c/jetty/org.eclipse.jetty.project.git/plain/jetty-server/src/main/config/etc/keystore to etc/keystore
server initialised in ${jetty.base}/start.ini (appended)
server enabled in ${jetty.base}/start.ini
http initialised in ${jetty.base}/start.ini (appended)
http enabled in ${jetty.base}/start.ini
server enabled in ${jetty.base}/start.ini
deploy initialised in ${jetty.base}/start.ini (appended)
deploy enabled in ${jetty.base}/start.ini
MKDIR: ${jetty.base}/webapps
server enabled in ${jetty.base}/start.ini

3)查看你的目录

[my-base]$ ls -la
total 20
drwxrwxr-x 4 user group 4096 Oct 8 06:55 ./
drwxr-xr-x 103 user group 4096 Oct 8 06:53 ../
drwxrwxr-x 2 user group 4096 Oct 8 06:55 etc/
-rw-rw-r-- 1 user group 815 Oct 8 06:55 start.ini
drwxrwxr-x 2 user group 4096 Oct 8 06:55 webapps/

4)拷贝你的WAR文件到webapps

[my-base]$ ls -la
[my-base]$ cp ~/code/project/target/gadget.war webapps/

5)拷贝你的keystore

[my-base]$ cp ~/code/project/keystore etc/keystore

6)编辑start.ini配置你的SSL设置

[my-base]$ cat start.ini

7)初始化模块ssl

--module=ssl

8)为安全重定向定义port

jetty.secure.port=8443

9)建立一个示范keystore和truststore

jetty.keystore=etc/keystore
jetty.truststore=etc/keystore

10)设置示范password

jetty.keystore.password=OBF:1vny1zlo1x8e1vnw1vn61x8g1zlu1vn4
jetty.keymanager.password=OBF:1u2u1wml1z7s1z7a1wnl1u2g
jetty.truststore.password=OBF:1vny1zlo1x8e1vnw1vn61x8g1zlu1vn4

11)初始化模块server

--module=server
threads.min=10
threads.max=200
threads.timeout=60000
#jetty.host=myhost.com
jetty.dump.start=false
jetty.dump.stop=false

12)初始化模块http

--module=http
jetty.port=8080
http.timeout=30000

13)初始化模块部署

--module=deploy

查看你如今的配置:

[my-base]$ java -jar /home/user/jetty-distribution-9.1.0.RC0/start.jar --list-config

Java Environment:
-----------------
java.home=/home/user/java/jdk-7u21-x64/jre
java.vm.vendor=Oracle Corporation
java.vm.version=23.21-b01
java.vm.name=Java HotSpot(TM) 64-Bit Server VM
java.vm.info=mixed mode
java.runtime.name=Java(TM) SE Runtime Environment
java.runtime.version=1.7.0_21-b11
java.io.tmpdir=/tmp Jetty Environment:
-----------------
jetty.home=/home/user/jetty-distribution-9.1.0.RC0
jetty.base=/home/user/my-base
jetty.version=9.1.0.RC0 JVM Arguments:
--------------
(no jvm args specified) System Properties:
------------------
jetty.base = /home/user/my-base
jetty.home = /home/user/jetty-distribution-9.1.0.RC0 Properties:
-----------
http.timeout = 30000
jetty.dump.start = false
jetty.dump.stop = false
jetty.keymanager.password = OBF:1u2u1wml1z7s1z7a1wnl1u2g
jetty.keystore = etc/keystore
jetty.keystore.password = OBF:1vny1zlo1x8e1vnw1vn61x8g1zlu1vn4
jetty.port = 8080
jetty.secure.port = 8443
jetty.truststore = etc/keystore
jetty.truststore.password = OBF:1vny1zlo1x8e1vnw1vn61x8g1zlu1vn4
threads.max = 200
threads.min = 10
threads.timeout = 60000 Jetty Server Classpath:
-----------------------
Version Information on 11 entries in the classpath.
Note: order presented here is how they would appear on the classpath.
changes to the --module=name command line options will be reflected here.
0: 3.1.0 | ${jetty.home}/lib/servlet-api-3.1.jar
1: 3.1.RC0 | ${jetty.home}/lib/jetty-schemas-3.1.jar
2: 9.1.0.RC0 | ${jetty.home}/lib/jetty-http-9.1.0.RC0.jar
3: 9.1.0.RC0 | ${jetty.home}/lib/jetty-continuation-9.1.0.RC0.jar
4: 9.1.0.RC0 | ${jetty.home}/lib/jetty-server-9.1.0.RC0.jar
5: 9.1.0.RC0 | ${jetty.home}/lib/jetty-xml-9.1.0.RC0.jar
6: 9.1.0.RC0 | ${jetty.home}/lib/jetty-util-9.1.0.RC0.jar
7: 9.1.0.RC0 | ${jetty.home}/lib/jetty-io-9.1.0.RC0.jar
8: 9.1.0.RC0 | ${jetty.home}/lib/jetty-servlet-9.1.0.RC0.jar
9: 9.1.0.RC0 | ${jetty.home}/lib/jetty-webapp-9.1.0.RC0.jar
10: 9.1.0.RC0 | ${jetty.home}/lib/jetty-deploy-9.1.0.RC0.jar Jetty Active XMLs:
------------------
${jetty.home}/etc/jetty.xml
${jetty.home}/etc/jetty-http.xml
${jetty.home}/etc/jetty-ssl.xml
${jetty.home}/etc/jetty-deploy.xml

如今启动Jetty:

[my-base]$ java -jar /home/user/jetty-distribution-9.1.0.RC0/start.jar
2013-10-08 07:06:55.837:INFO:oejs.Server:main: jetty-9.1.0.RC0
2013-10-08 07:06:55.853:INFO:oejdp.ScanningAppProvider:main: Deployment monitor [file:/home/joakim/my-base/webapps/] at interval 1
2013-10-08 07:06:55.872:INFO:oejs.ServerConnector:main: Started ServerConnector@72974691{HTTP/1.1}{0.0.0.0:8080}

回想配置

以下又一次回想上面的配置。

${jetty.base}和${jetty.home}

首先注意${jetty.base}和${jetty.home}的划分。

 1)${jetty.home}是你的公布位于的路径,未改变的,为编辑的;

 2)${jetty.base}是你的定制位于的路径。

模块

注意你配置的--module=<name>,你打包模块(库、配置XML和属性)进入一个单个的单元,包含依赖。

你能查看模块的列表:

[my-base]$ java -jar /home/user/jetty-distribution-9.1.0.RC0/start.jar --list-modules

Jetty All Available Modules:
---------------------------- Module: annotations
LIB: lib/jetty-annotations-${jetty.version}.jar
LIB: lib/annotations/*.jar
XML: etc/jetty-annotations.xml
depends: [plus] Module: client
LIB: lib/jetty-client-${jetty.version}.jar
depends: [] Module: debug
XML: etc/jetty-debug.xml
depends: [server] Module: deploy
LIB: lib/jetty-deploy-${jetty.version}.jar
XML: etc/jetty-deploy.xml
depends: [webapp]
enabled: ${jetty.base}/start.ini Module: ext
LIB: lib/ext/*.jar
depends: [] Module: http
XML: etc/jetty-http.xml
depends: [server]
enabled: ${jetty.base}/start.ini Module: https
XML: etc/jetty-https.xml
depends: [ssl] Module: ipaccess
XML: etc/jetty-ipaccess.xml
depends: [server] Module: jaas
LIB: lib/jetty-jaas-${jetty.version}.jar
XML: etc/jetty-jaas.xml
depends: [server] Module: jaspi
LIB: lib/jetty-jaspi-${jetty.version}.jar
LIB: lib/jaspi/*.jar
depends: [security] Module: jmx
LIB: lib/jetty-jmx-${jetty.version}.jar
XML: etc/jetty-jmx.xml
depends: [] Module: jndi
LIB: lib/jetty-jndi-${jetty.version}.jar
LIB: lib/jndi/*.jar
depends: [server] Module: jsp
LIB: lib/jsp/*.jar
depends: [servlet] Module: jvm
depends: [] Module: logging
XML: etc/jetty-logging.xml
depends: [] Module: lowresources
XML: etc/jetty-lowresources.xml
depends: [server] Module: monitor
LIB: lib/jetty-monitor-${jetty.version}.jar
XML: etc/jetty-monitor.xml
depends: [client, server] Module: npn
depends: [] Module: plus
LIB: lib/jetty-plus-${jetty.version}.jar
XML: etc/jetty-plus.xml
depends: [server, security, jndi] Module: proxy
LIB: lib/jetty-proxy-${jetty.version}.jar
XML: etc/jetty-proxy.xml
depends: [client, server] Module: requestlog
XML: etc/jetty-requestlog.xml
depends: [server] Module: resources
LIB: resources
depends: [] Module: rewrite
LIB: lib/jetty-rewrite-${jetty.version}.jar
XML: etc/jetty-rewrite.xml
depends: [server] Module: security
LIB: lib/jetty-security-${jetty.version}.jar
depends: [server] Module: server
LIB: lib/servlet-api-3.1.jar
LIB: lib/jetty-schemas-3.1.jar
LIB: lib/jetty-http-${jetty.version}.jar
LIB: lib/jetty-continuation-${jetty.version}.jar
LIB: lib/jetty-server-${jetty.version}.jar
LIB: lib/jetty-xml-${jetty.version}.jar
LIB: lib/jetty-util-${jetty.version}.jar
LIB: lib/jetty-io-${jetty.version}.jar
XML: etc/jetty.xml
depends: []
enabled: ${jetty.base}/start.ini Module: servlet
LIB: lib/jetty-servlet-${jetty.version}.jar
depends: [server] Module: servlets
LIB: lib/jetty-servlets-${jetty.version}.jar
depends: [servlet] Module: setuid
LIB: lib/setuid/jetty-setuid-java-1.0.1.jar
XML: etc/jetty-setuid.xml
depends: [server] Module: spdy
LIB: lib/spdy/*.jar
XML: etc/jetty-ssl.xml
XML: etc/jetty-spdy.xml
depends: [ssl, npn] Module: ssl
XML: etc/jetty-ssl.xml
depends: [server]
enabled: ${jetty.base}/start.ini Module: stats
XML: etc/jetty-stats.xml
depends: [server] Module: webapp
LIB: lib/jetty-webapp-${jetty.version}.jar
depends: [servlet] Module: websocket
LIB: lib/websocket/*.jar
depends: [annotations] Module: xinetd
XML: etc/jetty-xinetd.xml
depends: [server] Jetty Active Module Tree:
-------------------------
+ Module: server [enabled]
+ Module: http [enabled]
+ Module: servlet [transitive]
+ Module: ssl [enabled]
+ Module: webapp [transitive]
+ Module: deploy [enabled]

上面包括了模块名、使用的库、使用的XML配置、以及他们依赖的其他模块(甚至包括可选的),而且标注了模块是否激活。

你能够通过编辑${jetty.base}/start.ini来管理激活模块列表。

假设你想启动一个新模块:

[my-base] $ java -jar ../jetty-distribution-9.1.0.RC0/start.jar --add-to-start=https

这添加--module=行和相关的属性(上面提到的參数化值)到你的start.ini。

參数

接下来是參数化全部的标准配置XML。在这个样例中,全部的SSL參数都是start.ini中的属性,非常少或者没有编辑XML的须要。

在${jetty.base}中覆盖${jetty.home}

最后,你能在${jetty.base}中覆盖你在${jetty.home}中看到的不论什么东西,即使XML配置和库。

在《启动Jetty》中将有更具体的论述。

在Jetty 9.1中配置SSL总结

1)下载并解压Jetty 9.1到/home/user/jetty-distribution-9.1.0.RC1;

 2)不使用了编辑该公布,到你的base目录;

 [my-base]$ java -jar /home/user/jetty-distribution-9.1.0.RC1/start.jar

 ------Jetty 9.1公布提供了XML配置文件,在这里是jetty-http.xml和jetty-ssl.xml。你能在${jetty.home}/etc/中找到他们。

 ------我们在那些XML中參数化全部的配置项。你如今能用简单的属性来设置这些值,或者在命令行中,或者在${jetty.base}/start.ini中。

 ------当你激活HTTP和HTTPS模块时,Jetty自己主动加入相应的库和XML到Jetty。除非你有高级别的自己定义设置(比如监听两个不同的port,用SSL在每个上面,每个都有自己的keystore和配置),你应该不须要改动XML文件。

 3)用模块配置HTTPS:

 ------http -> server

 ------https -> ssl -> server

 你能在${jetty.home}/modules/中找到模块的细节。为SSL包含modules/http.mod、modules/https.mod、modules/ssl.mod和modules/server.mod。

 理论上,这些细节对你是不重要的。重要的是你想使用HTTPS,而且想配置它。你通过加入--module=https到你的start.ini来达到。默认情况下,模块系统是完整的,且包含全部的依赖模块。

不须要启动Jetty,在全部的模块被解析后,你能够查看配置,通过:

[my-base] $ java -jar ../jetty-distribution-9.1.0.RC0/start.jar --list-config

注意JAR包在磁盘中,并不意味着他们被使用,他们的使用通过配置项控制。

用--list-config来查看配置。注意仅公布版本号中的JAR的子集被使用,你激活的模块决定这个子集。

[my-base]$ java -jar ~/jetty-distribution-9.1.0.RC0/start.jar --list-config

认证

Jetty server内的web应用(或上下文)的安全涉及两个方面:

 1)认证:web应用能通过一个机制配置确定用户标识,这通过标准声明、Jetty提供的机制和这节将讲到的配置方式共同配置。

 2)授权:一旦用户的标识被确认(或否决),web应用能通过带有安全限制的标准描写叙述符配置用户可以訪问哪些资源。

配置一个认证机制

Jetty server支持集中标准的认证机制:BASIC;DIGEST;FORM;CLIENT-CERT;以及其它能被插入到使用可扩展的JASPI或者SPNEGO机制的机制。

内在地,配置一个认证机制是通过设置一个Authenticator接口的实例到上下文的SecurityHandler来实现的,但大部分实例都是是通过在web.xml中设置< login-config>元素或者使用注解来实现的。

以下是一个样例,来自jetty-test-webapp web.xml(http://git.eclipse.org/c/jetty/org.eclipse.jetty.project.git/tree/tests/test-webapps/test-jetty-webapp/src/main/webapp/WEB-INF/web.xml?h=release-9),配置BASIC认证:

<login-config>
<auth-method>BASIC</auth-method>
<realm-name>Test Realm</realm-name>
</login-config>

jetty-test-webapp web.xml也包含凝视掉的DIGEST和FORM配置的样例:

<login-config>
<auth-method>FORM</auth-method>
<realm-name>Test Realm</realm-name>
<form-login-config>
<form-login-page>/logon.html?param=test</form-login-page>
<form-error-page>/logonError.html?param=test</form-error-page>
</form-login-config>
</login-config>

使用FORM认证,你也必须配置产生一个登录表格和处理错误的页面的URL。以下简单的HTML表格来自test webapp logon.html(http://git.eclipse.org/c/jetty/org.eclipse.jetty.project.git/tree/tests/test-webapps/test-jetty-webapp/src/main/webapp/logon.html?h=release-9):

<HTML>
<H1>FORM Authentication demo</H1>
<form method="POST" action="j_security_check">
<table border="0" cellspacing="2" cellpadding="1">
<tr>
<td>Username:</td>
<td><input size="12" value="" name="j_username" maxlength="25" type="text"></td>
</tr>
<tr>
<td>Password:</td>
<td><input size="12" value="" name="j_password" maxlength="25" type="password"></td>
</tr>
<tr>
<td colspan="2" align="center">
<input name="submit" type="submit" value="Login">
</td>
</tr>
</table>
</form>
</HTML>

认证机制为上下文/web应用定义服务端怎么从client获取认证证书,可是它不定义服务端怎么检查这些证书是否有效。为了检查证书,server和/或上下文也须要配置LoginService实例,能够通过域名匹配。

安全域

安全域用于防止你的web应用被未认证的进入。保护基于认证(表示谁正在请求进入webapp)和进入控制(限制什么能被訪问和怎么訪问)。

webapp在web.xml中静态地配置它的安全要求。认证通过<login-config>元素控制。訪问控制通过<security-constraint>和<security-role-ref>元素指定。当一个请求请求一个受保护的资源时,web容器检查用户是否被认证,而且用户所在的角色是否有该资源的訪问权限。

Servlet指导手冊没有指定在WEB-INF/web.xml中的静态安全信息怎么被匹配到容器的执行时环境。在Jetty中,LoginService履行这个职责。

LoginService有一个唯一name,而且同意訪问用户列表。每一个用户都有认证信息(比如:password)和与之关联的角色列表。

你能够依据须要配置一个或者多个不同的LoginService。单一的域将表明你希望你的全部web应用共享安全信息。不同的域同意你在不同的webapp将划分安全信息。

当一个请求请求认证和授权时,Jetty将用web.xml中的<login-config>元素内的<realm-name>子元素履行对LoginService的一次精确匹配。

安全域范围

一个LoginService有一个唯一名称,由一个用户列表组成。每一个用户有认证信息(比如:password)和与之关联的角色列表。你能依据你的须要配置一个或多个不同的域:

 1)配置一个单个的LoginService,你的全部web应用共享安全信息。

 2)配置不同的LoginService,为webapp划分不同的安全信息。

全局范围

假设你定义LoginService在Jetty配置文件里,比如${jetty.home}/etc/jetty.xml,那么它在一个Server实例上对全部的web应用都是有效的。以下是一个样例,定义一个in-memory类型的LoginService,叫做HashLoginService:

<Configure id="Server" class="org.eclipse.jetty.server.Server">
<Call name="addBean">
<Arg>
<New class="org.eclipse.jetty.security.HashLoginService">
<Set name="name">Test Realm</Set>
<Set name="config"><SystemProperty name="jetty.home" default="."/>/etc/realm.properties</Set>
<Set name="refreshInterval">0</Set>
</New>
</Arg>
</Call>
</Configure>

假设你在一个Server上定义超过一个LoginService,你将须要为每个上下文指定你想使用哪一个。你能够告诉上下文LoginService的名称,或者传递它给LoginService实例。最以下是一个样例:

<Configure class="org.eclipse.jetty.webapp.WebAppContext">
<Get name="securityHandler">
<!-- Either: -->
<Set name="loginService">
<New class="org.eclipse.jetty.security.HashLoginService">
<Set name="name">Test Realm</Set>
</New>
</Set> <!-- or if you defined a LoginService called "Test Realm" in jetty.xml : -->
<Set name="realmName">Test Realm</Set> </Get>

每webapp范围

你也能够为单独的web应用定义LoginService。以下是怎么为上下文定义相同的HashLoginService:

<Configure class="org.eclipse.jetty.webapp.WebAppContext">
<Set name="contextPath">/test</Set>
<Set name="war"><SystemProperty name="jetty.home" default="."/>/webapps/test</Set>
<Get name="securityHandler">
<Set name="loginService">
<New class="org.eclipse.jetty.security.HashLoginService">
<Set name="name">Test Realm</Set>
<Set name="config"><SystemProperty name="jetty.home" default="."/>/etc/realm.properties</Set>
</New>
</Set>
</Get>
</Configure>

Jetty提供了一组不同的LoginService类型,以下将做介绍。

配置一个LoginService

一个LoginService实例有一个认证机制,被用于检查被认证机制收集的username和证书的有效性。Jetty提供了以下的LoginService的实现:

 ------HashLoginService

 用户域是一个hash表,通过编程填充或者通过Java属性文件填充。

 ------JDBCLoginService

 使用一个JDBC连接到一个SQL数据库进行认证。

 ------DataSourceLoginService

 用JNDI定义认证的DataSource。

 ------JAASLoginService

 用JAAS提供商进行验证。

 ------SpnegoLoginService

 SPNEGO认证。

一个LoginService的实例能通过以下的方式匹配到上下文/webapp:

 1)一个LoginService实例能够被直接设置到SecurityHandler实例,通过代码或者IoC XML。

 2)用LoginService实例(作为依赖bean设置到Server实例中)的名称匹配定义在web.xml中的域名。

 3)假设仅一个单个的LoginService实例被设置到Server,则它被用于上下文的登录service。

HashLoginService

HashLoginService是一个简单有效的登录service,用于从一个Java属性文件载入username、证书和角色集,属性文件格式例如以下;

username: password[,rolename ...]

这里:

 ------username

 用户的唯一标识

 ------password

 用户password(可能被扰乱或者被MD5加密)

 ------rolename

 用户的角色

比如:

admin: CRYPT:ad1ks..kc.1Ug,server-administrator,content-administrator,admin
other: OBF:1xmk1w261u9r1w1c1xmq
guest: guest,read-only

你使用一个名称和属性文件地址配置HashLoginService:

<Item>
<New class="org.eclipse.jetty.security.HashLoginService">
<Set name="name">Test Realm</Set>
<Set name="config"><SystemProperty name="jetty.home" default="."/>/etc/realm.properties</Set>
</New>
</Item>

你也能配置它定期检測属性文件改变,假设发生变化则又一次载入它。reloadInterval的单位是秒:

<New class="org.eclipse.jetty.security.HashLoginService">
<Set name="name">Test Realm</Set>
<Set name="config"><SystemProperty name="jetty.home" default="."/>/etc/realm.properties</Set>
<Set name="reloadInterval">5</Set>
<Call name="start"></Call>
</New>

JDBCLoginService

在这个实现中,认证和角色信息被存储在数据库中,通过JDBC訪问。一个属性文件定义JDBC连接和数据库表信息。以下是属性文件的样例:

jdbcdriver = org.gjt.mm.mysql.Driver
url = jdbc:mysql://localhost/jetty
username = jetty
password = jetty
usertable = users
usertablekey = id
usertableuserfield = username
usertablepasswordfield = pwd
roletable = roles
roletablekey = id
roletablerolefield = role
userroletable = user_roles
userroletableuserkey = user_id
userroletablerolekey = role_id
cachetime = 300

数据库表的格式是(伪sql):

users
(
id integer PRIMARY KEY,
username varchar(100) NOT NULL UNIQUE KEY,
pwd varchar(50) NOT NULL
);
user_roles
(
user_id integer NOT NULL,
role_id integer NOT NULL,
UNIQUE KEY (user_id, role_id),
INDEX(user_id)
);
roles
(
id integer PRIMARY KEY,
role varchar(100) NOT NULL UNIQUE KEY
);

这里:

 ------users为每一个用户包括一个条目,包括:

  ------id:用户的唯一标识

  ------user:username

  ------pwd:用户password(可能被扰乱或者被MD5加密)

 ------user-roles是一个表格,每行表示一个角色授权给一个用户:

  ------user_id:用户唯一标识

  ------role_id:用户角色

 ------roles是一个表格,包括系统中的全部角色

  ------id:角色的唯一标识

  ------role:角色的可读的名称

假设你想使用扰乱、MD5扰乱或者加密password,users表的pwd列必须足够大。

你定义一个JDBCLoginService,须要指定域名和描写叙述数据库的属性文件路径:

<New class="org.eclipse.jetty.security.JDBCLoginService">
<Set name="name">Test JDBC Realm</Set>
<Set name="config">etc/jdbcRealm.properties</Set>
</New>

授权

依照servlet指导文档,授权基于角色。就像我们看到过的,一个LoginService关联的一个用户相应一组角色。当一个用于请求一个受保护的资源时,LoginService将被用于认证请求的用户,然后确认用户相应的角色集中是否存在对该资源有权限的角色。

在Servlet 3.1之前,基于角色的授权能定义:

 1)授权于一组命名的角色

 2)訪问全然禁止,不管不论什么角色

 3)訪问授权给一个相应web.xml中定义的不论什么角色的用户。这通过在<security-constraint>中为<auth-constraint>的<role-name>指定为"*"表明

Servlet 3.1添加了还有一个授权:

 1)訪问授权给被认证的不论什么用户,不管不论什么角色。这通过在<security-constraint>中为<auth-constraint>的<role-name>指定值"**"来表明

限制表单内容

提交到服务端的表单内容被Jetty组织为一个參数map交给web应用处理。这个机制是easy被攻击的,client可以通过提交大数据量的表单内容或者大量的表单keys来消耗服务端的内容和CPU,这就是拒绝服务攻击(DOS)。因此Jetty限制可以提交到Jetty的数据和keys的数量。

Jetty同意的默认的最大值是200000 bytes和1000 keys.你能改变这个默认值为特定Server实例上的一个特定的webapp或者全部的webapp。

配置表单显示为一个webapp

为了为单个webapp配置表单限制,上下文处理器(或者webappContext)实例必须用以下的方式配置:

ContextHandler.setMaxFormContentSize(int maxSizeInBytes);
ContextHandler.setMaxFormKeys(int formKeys);

这些方法能够在代码中直接调用,但更通常的是通过上下文XML或者WEB-INF/jetty-web.xml配置:

<Configure class="org.eclipse.jetty.webapp.WebAppContext">

 

  ...

 

  <Set name="maxFormContentSize">200000</Set>

  <Set name="maxFormKeys">200</Set>

</Configure>

配置表单限制为Server

假设一个上下文没有指定表单限制,那么将使用server的配置。以下是在jetty.xml中配置:

<configure class="org.eclipse.jetty.server.Server">

  ...

  <Call name="setAttribute">
<Arg>org.eclipse.jetty.server.Request.maxFormContentSize</Arg>
<Arg>100000</Arg>
</Call>
<Call name="setAttribute">
<Arg>org.eclipse.jetty.server.Request.maxFormKeys</Arg>
<Arg>2000</Arg>
</Call>
</configure>

别名文件和符号链接(Aliased Files and Symbolic links)

web应用将常常提供静态内容。然而因为文件系统常常为相同的文件提供多个别名,导致安全限制和其它servlet URI空间映射通过别名被绕过。

比較典型的样例是在Windows文件系统下的大写和小写敏感和8.3文件名称实现。假设一个webapp中的文件叫做/mysecretfile.txt,被安全限制保护,相应URI为/mysecretfile.txt,那么一个对/MySecretFile.TXT的请求将不匹配URI限制,由于URI是大写和小写敏感的,可是Windows文件系统将报告存在这个文件而且为这个请求提供服务,从而绕过安全限制。比大写和小写敏感更少见的是Windows文件系统也支持8.3文件名称,主要是为了兼容性。因此一个对URI为/MYSECR~1.TXT的请求将不匹配安全限制,但文件系统会找到相应的文件并提供服务。

有一些别名的样例,不只在windows上:

 1)NTFS Alternate流命名为这样c:\test\file.txt::$DATA:name。

 2)OpenVMS支持文件版本号化,/mysecret.txt;N表示相应/mysecret.txt的版本号N,本质上是别名。

 3)clearcase软件配置管理系统提供一个文件系统,在一个文件名称中的@@表示相应一个特定版本号的别名。

 4)unix文件系统支持/./foo.txt作为/foo.txt的别名。

 5)一些JVM实现不对的假定null字符是一个字符串的终结符,以至于一个文件名称/foobar.txt%00是/foobar.txt的别名。

 6)Unix符号链接和硬链接是别名的一种形式,同意相同的文件或目录有多个名称。

另外,不只URI安全限制能被绕过。比如匹配模式*.jsp到JSP Servlet的URI映射能够被绕过,通过请求一个别名象/foobar.jsp%00,导致JSP的源码被文件系统返回,而不是运行这个JSP。

好的安全实践

别名导致的问题,一部分是因为标准web应用安全模式是同意全部的请求除非请求被安全限制明白否定。一个安全的最佳实践是否定全部的请求,仅仅同意那些特定标注为同意的。以这样的方式设计web应用安全限制是可能的,但在全部的场景下这样做是困难的,因此它不是默认的。因此探測和否定对别名静态内容的请求对Jetty来说是重要的。

别名探測

要Jetty知道被文件系统实现的全部别名是不可能的,因此它不会尝试去做已知的别名检查。取而代之Jetty通过用一个文件的标准路径来探測别名。假设一个被Jetty处理的文件资源有一个标准名,不同于请求这个资源的名称,那么Jetty确定这是一个资源的别名请求,它将被返回通过ServletContext.getResource(String)方法(或类似的),而不是作为静态资源服务。

假设Jetty正执行在一个windows操作系统上,那么一个叫/MySecret.TXT的文件将有一个精确匹配的标准名。于是当对/mysecret.txt或者/MYSECR~1.TXT的请求到达时,因为和标准名不匹配,这些请求被觉得是对别名的请求,他们将不被作为静态资源服务,终于可以一个404响应返回。

服务别名和符号链接

不是全部的别名都是坏的,或者被觉得尝试破坏安全限制的。当组合复杂的web应用时,符号链接是非常实用的,然而默认Jetty将不服务他们。因此Jetty上下文支持一个可扩展的AliasCheck机制,为了同意别名资源被作为有条件的服务。在这个方面,“好”别名能被探測而且服务。Jetty提供了几种AliasCheck接口的通用的实现,作为ContextHandler的内嵌类:

 ------ApproveAliases

 接收全部别名(使用需慎重!)

 ------AllowSymLinkAliasChecker

 使用java-7 Files.readSymbolicLink(path) and Path.toRealPath(...) APIs检查别名,通过的作为有效的符号链接。

一个应用能够自由的实现它自己的别名检查。别名检查能通过上下文部署文件或者WEB-INF/jetty-web.xml安装:

<!-- Allow symbolic links  -->
<Call name="addAliasCheck">
<Arg><New class="org.eclipse.jetty.server.handler.AllowSymLinkAliasChecker"/></Arg>
</Call>

安全password扰乱

有非常多地方你可能想使用和存储password,比如为SSL链接器和域中的用户password。

password能被存储在明文、被扰乱的、被检验和的和被加密的,为了添加安全性。为了password安全,方法的选择依赖于你正在什么地方使用password。在很多场景下,比如keystorepassword和摘要式身份验证,系统必须又一次得到原始password,这须要用到扰乱方法。扰乱算法的缺陷是它仅保护password免于任意查看。

当存储的password同用户输入的进行比較时,代码能对用户输入应用和保护存储password相同的算法,然后比較结果,使password认证更加安全。

类org.eclipse.jetty.http.security.Password能被用于产生全部password的变化。

不带參数运行能够看到使用指导:

$ export JETTY_VERSION=9.0.0-SNAPSHOT
$ java -cp lib/jetty-util-$JETTY_VERSION.jar org.eclipse.jetty.util.security.Password Usage - java org.eclipse.jetty.util.security.Password [<user>] <password>
If the password is ?, the user will be prompted for the password

比如,为了产生一个安全的password版本号,假定用户"me",password"blah",则:

$ export JETTY_VERSION=9.0.0.RC0
$ java -cp lib/jetty-util-$JETTY_VERSION.jar org.eclipse.jetty.util.security.Password me blah
blah
OBF:20771x1b206z
MD5:639bae9ac6b3e1a84cebb7b403297b79
CRYPT:me/ks90E221EY

你如今能剪切,然后粘贴你选择的安全版本号进入你的配置文件或者java代码。

比如,以下的最后一行展示了你怎么将上面产生的加密后的password剪切并粘贴到你的属性文件里,供LoginService使用:

admin: CRYPT:ad1ks..kc.1Ug,server-administrator,content-administrator,admin
other: OBF:1xmk1w261u9r1w1c1xmq
guest: guest,read-only
me:CRYPT:me/ks90E221EY

注意:不要忘记拷贝OBF:、MD5:或者CRYPT:前缀,否则Jetty将无法正确使用。

你也能用在Jetty xml文件里使用扰乱的password。以下是一个样例,为JDBC DataSource设置扰乱的password:

<New id="DSTest" class="org.eclipse.jetty.plus.jndi.Resource">
<Arg></Arg>
<Arg>jdbc/DSTest</Arg>
<Arg>
<New class="com.jolbox.bonecp.BoneCPDataSource">
<Set name="driverClass">com.mysql.jdbc.Driver</Set>
<Set name="jdbcUrl">jdbc:mysql://localhost:3306/foo</Set>
<Set name="username">dbuser</Set>
<Set name="password">
<Call class="org.eclipse.jetty.util.security.Password" name="deobfuscate">
<Arg>OBF:1ri71v1r1v2n1ri71shq1ri71shs1ri71v1r1v2n1ri7</Arg>
</Call>
</Set>
<Set name="minConnectionsPerPartition">5</Set>
<Set name="maxConnectionsPerPartition">50</Set>
<Set name="acquireIncrement">5</Set>
<Set name="idleConnectionTestPeriod">30</Set>
</New>
</Arg>
</New>

JAAS支持

兴许补充

Spnego支持

兴许补充

Jetty:配置安全的更多相关文章

  1. IntelliJ IDEA使用(二):tomcat和jetty配置

    上一讲用idea创建了maven web项目,接下来我们把项目发布到tomcat和jetty运行,以便进一步地开发和调试 配置tomcat 第一.打开菜单栏 第二.点击设置按钮,添加应用服务器,选择t ...

  2. 阿里云服务器Linux CentOS安装配置(五)jetty配置、部署

    阿里云服务器Linux CentOS安装配置(五)jetty配置.部署 1.官网下载jetty:wget http://repo1.maven.org/maven2/org/eclipse/jetty ...

  3. IntelliJ IDEA使用(二):tomcat和jetty配置(转自:http://www.cnblogs.com/jenkinschan/p/6052948.html)

    上一讲用idea创建了maven web项目,接下来我们把项目发布到tomcat和jetty运行,以便进一步地开发和调试 配置tomcat 第一.打开菜单栏 第二.点击设置按钮,添加应用服务器,选择t ...

  4. idea jetty 配置

    一.jetty 网址下载地:https://www.eclipse.org/jetty/ 1.如下图红色箭头--> 点击Downloads 下载 2.选择最新版 .ZIP 下载 3.选择安装路径 ...

  5. Jetty配置

    类似TomCat 登陆官网www.eclipse.org Download下载Jetty zip压缩版 解压到文件夹,打开idea的Config->Jetty-server->Local- ...

  6. apache+jetty 配置web jsp服务器负载均衡

    首先,查找中文资料,貌似很少,有一个网友写了点,但是1版本过老,2有些地方有错误. 经过我自己摸索,记录一下.这个图很简洁明了 第一阶段 ,配置jetty 首先从 http://download.ec ...

  7. maven jetty 配置

    对于jdk8增加如下配置: <plugin> <groupId>org.eclipse.jetty</groupId> <artifactId>jett ...

  8. JDK1.7 和 jetty配置教程

    系统是windows 7 64位版本,32位版本同理,xp系统的自己google设置环境变量 打开设置环境变量窗口,右键计算机->我的电脑,选择属性 点击高级系统设置 选择环境变量 红线为需要设 ...

  9. 内置Jetty配置JSP支持过程中的常见报错

    目录 1. 常见报错及解决 1.1 JSP support not configured 1.2 JSTL标签解析 1.3 JSP编译 1.4 JSP实现依赖 1.5 EL表达式支持 2. 小结 1. ...

  10. Jetty配置虚拟目录,实现把web项目发布到自定义目录,指定指定上下文访问;jetty编码修改

    2019-12-31     17:28:38 一般只需要把Java站点文件夹或*.war文件拷贝到Web Server的webapps文件夹下,即可启动运行该站点,但更多时候,我们并不想拷贝站点,而 ...

随机推荐

  1. 使用ant的jar任务打jar包

    <?xml version="1.0" encoding="UTF-8"?> <project name="javaTest&quo ...

  2. django-template-loader

    当在settings.py中设置了如下 TEMPLATE_LOADERS=( 'django.template.loaders.filesystem.Loader', 'django.template ...

  3. 简要解析XMPP框架及iOS-Objective-C的使用

    前言:这两天看了XMPP框架,查阅了一些资料,写下这篇文章记录一下学习笔记 一.简要解析XMPP核心部分 XMPP框架分为两个部分 1.核心部分 2.扩展部分 扩展部分主要讲好友列表(roster). ...

  4. vi编辑器使用介绍

    vi是linux下使用及其广泛的一个编辑器,虽然看上去很简单,但实际功能强大. 使用vi,核心就是熟悉它的一些命令.vi的命令非常多,但我们常用的实际就那几种. 下面将vi最核心的使用点介绍下. 一. ...

  5. 一步一步重写 CodeIgniter 框架 (3) —— 用面向对象重构代码

    前面两篇文章为了重点突出 CodeIgniter 框架的原理,程序的结构很乱,有很多全局变量,在这一课中我们采用面向对象的方法对原先代码进行重构. 到目前为止,程序主要完成的就是 URL 分析,并根据 ...

  6. 怎样让js不产生冲突,避免全局变量的泛滥,合理运用命名空间

    为了避免变量之间的覆盖与冲突.能够生成命名空间.命名空间是一种特殊的前缀,在js中,通过{ }对象实现. 在不同的匿名函数中,依据功能声明一个不同的命名空间,每一个匿名函数中GLOBAL对象的属性都不 ...

  7. BZOJ 1486: [HNOI2009]最小圈( 二分答案 + dfs判负圈 )

    二分答案m, 然后全部边权减掉m, 假如存在负圈, 那么说明有平均值更小的圈存在. 负圈用dfs判断. ------------------------------------------------ ...

  8. 终于懂了:WM_PAINT中应该用BeginPaint与EndPaint这两个api,它们的功能正是使无效区域恢复(所以WM_PAINT里即使什么都不做,也必须写上BeginPaint与EndPaint)——Delphi里WM_PAINT消息的三个走向都做到了这一点 good

    程序本来是想实现鼠标单击改变背景颜色.可是,程序运行时,为什么没有任何消息触发,背景颜色就一直不断的改变了?WM_PAINT怎么被触发的 #include <windows.h> #inc ...

  9. HBase概念学习(七)HBase与Mapreduce集成

    这篇文章是看了HBase权威指南之后,依据上面的解说搬下来的样例,可是略微有些不一样. HBase与mapreduce的集成无非就是mapreduce作业以HBase表作为输入,或者作为输出,也或者作 ...

  10. Swift - 通过设置视图的transform属性实现动画

    设置视图对象的transform属性,可以实现各种动画效果. 1,移动 指在同一平面内,将控件按照某个直线方向平移一定的距离. 1 2 3 4 5 //每次都从当前位置平移 self.imageVie ...