本文主要是介绍第十四章_安全性,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
14.1、验证和授权
验证是检验某个人是否是他/她所声称的那个人的过程。在Servlet/JSP应用程序中,验证一般是通过要求用户输入用户名和密码来完成的。
授权主要是确定一个用户具有什么样的访问级别。它使用于包含多个访问区域的应用程序,使用户能够访问应用程序的某一部分,但是不能访问其他部分。例如,网上商店可以分为公共区(供一般的公共浏览和查找商品),买家区(供已注册用户下单用),以及需要最高访问级别的管理区。不仅管理员用户自身也需要进行验证,并且还必须是已经被允许访问管理区的用户才行。访问级别经常被称作角色。
14.1.1、定义用户和角色
每一种兼容的Servlet/JSP容器都必须提供一种定义用户和角色的方法。如果你使用的是Tomcat,就可以通过编辑conf目录下的tomcat-users.xml文件来创建用户和角色。tomcat-users.xml文件范例如下:
<?xml version=’1.0’ encoding=’utf-8’?>
<tomcat-users>
<role rolename=”manager”/>
<role rolename=”member”/>
<user username=”tom” password=”secret” roles=”manager,member”/>
<user username=”jerry” password=”secret” roles=”member”/>
</tomcat-users>
tomcat-users.xml文件是一个带有tomcat-users根源素的XML文档。其中有role和user元素。role元素定义角色,user元素定义用户。role元素有一个rolename属性,用来指定角色的名称。user元素有username、password和roles属性。username属性指定用户名称,password属性指定密码,roles属性则指定该用户所属的一个或多个角色
14.1.2、强加安全性约束
前面讲过,将静态资源和JSP页面保存在WEB-INF或其下的某一个目录下,可以讲他们隐藏起来。放在这里的资源无法直接通过输入网址而访问到,但是仍然可以通过一个Servlet或者JSP页面跳转到那里。虽然这种方法简单直接,但缺点是藏在这里的资源就永远被藏起来了。它们永远无法被直接访问到。如果只是想避免未授权的用户访问这些资源,那么可以讲它们放在应用程序目录下的某一个目录中,并在部署描述符中声明一个安全性约束。
security-constraint元素用于指定一个资源集合,以及可以访问这些资源的一个或多个角色。这个元素可以有两个子元素:web-resource-collection和auth-constraint。
web-resource-collection元素用于指定一个资源集合,并且可以带有以下元素:web-resource-name、description、url-pattern、http-method和http-method-ommission。
web-resource-collection元素可以带有多个url-pattern元素,每一个子元素都表示所包含安全性约束实行的一种URL模式。我们可以在url-pattern元素中用一个星号(*)表示一种特定的资源类型(如*.jsp),或者表示某个目录下的所有资源(如/*或/jsp/*)。但是这两种不能合二为一,比如,无法表示某一个特定目录下的某一种特定的类型。因此,如果用/jsp/*.jsp表示jsp目录下的所有jsp页面,那么这个URL模式将是无效的,而是要用/jsp/*来表示,但是这样又限制了jsp目录下那些非jsp的页面。
http-method元素中定义了一个HTTP方法,包含的安全性约束即应用到该方法中。例如,web-resource-collection元素带有一个GET http-method元素,表示web-resource-collection元素只应用于HTTP的get方法。包含资源集合的安全性约束并不能保护其他的HTTP方法,例如Post方法和Put方法。如果没有http-method元素,表示这个安全性约束将会限制对所有HTTP方法的访问。同一个web-resource-collection元素中可以带有多个http-method元素。
http-method-omission元素指定的是不再所包含安全性约束中的HTTP方法。因此,指定<http-method-omission>GET</http-method-omission>限制了对除GET之外的所有HTTP方法的访问。
http-method和http-method-omission元素不能同时出现在同一个web-resource-collection元素中。
部署描述符中可以有多个security-constraint元素。如果安全性约束元素中没有auth-constraint元素,那么这个资源集合将不能受到保护。此外,如果你指定了一个没有在容器中定义的角色,那么将没有人能够直接访问这个资源集合。但是,你还是可以通过一个Servlet或者JSP页面跳转到集合中的某个资源。
举个例子。下面的web.xml文件中的security-constraint元素限制了对所有jsp页面的访问。由于auth-constraint元素中没有包含role-name元素,因此不能通过url来访问这些资源。
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"><display-name></display-name> <welcome-file-list><welcome-file>index.jsp</welcome-file></welcome-file-list><security-constraint><web-resource-collection><web-resource-name>JSP pages</web-resource-name><!-- 所有的jsp页面都不能被访问 --><url-pattern>*.jsp</url-pattern></web-resource-collection><auth-constraint></auth-constraint></security-constraint>
</web-app>
现在,可以在浏览器中打开网址测试一下:
Servlet容器会发送一条HTTP403错误,温柔地告诉你:Access to the requested resource has been denied(禁止访问)。
14.2、验证方法
学会如何对一个资源集合强加安全性约束之后,还应该知道如何对访问这些资源的用户进行验证。对于声明式保护的资源,可以在部署描述符中使用security-constraint元素,通过使用HTTP 1.1提供的解决方案来完成验证:基本访问验证和摘要访问验证。此外,也可以使用基于表单的访问验证。
14.2.1、基本访问验证
基本访问验证,简称基本验证,是一种接受用户名和密码的HTTP验证。在基本访问验证中,如果用户访问受保护的资源,将会遭到服务器的拒绝,并返回一个401(未授权)响应。该响应中包含一个WWW-Authenticate标头,其中至少包含一个适用于被请求资源的角色,例如:
HTTP/1.1 401 Authorization Required
Server: Apache-Coyote/1.1
Date: Wed, 21 Dec 2011 11:32:09 GMT
WWW-Authenticate: Basic realm=”Members Only”
随后浏览器屏幕上回显示一个登录对话框,供用户输入用户名和密码。当用户单击Login登录按钮时,用户名后面会被添上一个冒号,并和密码结合在一起。这个字符串被送到服务器之前,将先用Base64算法进行编码。登录成功之后,服务器就会发出被请求的资源。
Base64是一种很弱的算法,因此Base64消息很容易被破解。因此,要考虑使用摘要访问来代替。
下面展示了如何使用基本访问验证。第一个security-constraint元素是避免JSP页面被直接访问。第二个是限制只有manager和member角色的用户才能访问Servlet1 Servlet。Servlet1类是一个跳转到1.jsp页面的简单Servlet
web.xml<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"><display-name></display-name> <welcome-file-list><welcome-file>index.jsp</welcome-file></welcome-file-list><security-constraint><web-resource-collection><web-resource-name>JSP pages</web-resource-name><!-- 所有的jsp页面都不能被访问 --><url-pattern>*.jsp</url-pattern></web-resource-collection><auth-constraint></auth-constraint></security-constraint><security-constraint><web-resource-collection><web-resource-name>Servlet1</web-resource-name><url-pattern>/servlet1</url-pattern></web-resource-collection><auth-constraint><role-name>member</role-name><role-name>manager</role-name></auth-constraint></security-constraint><login-config><!-- BASIC必须全部大写 --><auth-method>BASIC</auth-method><!-- 显示在浏览器的登陆对话框中 --><realm-name>Members Only</realm-name></login-config>
</web-app>
servlet1.java
package app11a.servlet;import java.io.IOException;import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet(urlPatterns={"/servlet1"})
public class Servlet1 extends HttpServlet{private static final long serialVersionUID = 1L;@Overridepublic void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {RequestDispatcher dispatcher = request.getRequestDispatcher("/jsp/1.jsp") ;dispatcher.forward(request, response);}
}
由于映射到Servlet1的auth-constraint元素指定了manager和member两种角色,因此通过tom或者jerry都可以登录。
14.2.2、摘要访问验证
摘要访问验证,或简称摘要验证,它也是一种HTTP验证,与基本访问验证相似。摘要访问验证不是使用软弱的Base64算法,而是用MD5算法创建一个散列,其中结合了用户名、relam名称以及密码,并将这个散列发送到服务器。摘要访问验证旨在取代基本访问验证,因为她提供了更加安全的环境。
Servlet/JSP容器没有强制要求支持摘要访问验证,但是大多数容器都支持。
将应用程序配置成使用摘要访问验证,做法与使用基本访问验证时相似。事实上,它们之间的唯一区别在于login-config元素中的auth-method元素的值。在摘要访问验证中,这个元素的值必须为DIGEST(全部大写)。
下面就是举个例子使用了摘要访问验证。
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"><display-name></display-name> <welcome-file-list><welcome-file>index.jsp</welcome-file></welcome-file-list><security-constraint><web-resource-collection><web-resource-name>JSP pages</web-resource-name><!-- 所有的jsp页面都不能被访问 --><url-pattern>*.jsp</url-pattern></web-resource-collection><auth-constraint></auth-constraint></security-constraint><security-constraint><web-resource-collection><web-resource-name>Servlet1</web-resource-name><url-pattern>/servlet1</url-pattern></web-resource-collection><auth-constraint><role-name>member</role-name><role-name>manager</role-name></auth-constraint></security-constraint><login-config><auth-method>DIGEST</auth-method><!-- 显示在浏览器的登陆对话框中 --><realm-name>Disest authentication</realm-name></login-config>
</web-app>
打开浏览器输入http:/.localhost:8080/SingleUploadServlet/servlet1进行验证,又出现了刚才上面的页面。
14.2.3、基于表单的验证
基本和摘要访问验证都不允许使用定制的登陆表单。如果你必须使用定制的表单,那么可以使用基于表单的验证方法。由于她所传输的值没有进行加密,因此这个应该与SSL结合起来使用。
使用基于表单的验证时,需要创建一个login页面和一个error页面,它们可以是HTML页面,也可以是JSP页面。当第一次请求某一个受保护的资源时,Servlet/JSP容器将会发出Login页面。登录成功后,再发出被请求的资源。但是如果登录失败,用户将会看到Error页面。
使用基于表单的验证时,部署描述符中的auth-method元素值必须设为FORM(全部大写)。此外,login-config元素必须有一个form-login-config元素,它带有两个子元素:form-login-page和form-error-page。下面就是在基于表单的验证中,login-config元素的范例。
<login-config>
<auth-method>FORM</auth-method>
<form-login-config>
<form-login-page>/login.html</form-login-page>
<form-error-page>/error.html</form-error-page>
</form-login-config>
</login-config>
下面是一个基于表单验证的例子:web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"><display-name></display-name> <welcome-file-list><welcome-file>index.jsp</welcome-file></welcome-file-list><security-constraint><web-resource-collection><web-resource-name>JSP pages</web-resource-name><!-- 所有的jsp页面都不能被访问 --><url-pattern>*.jsp</url-pattern></web-resource-collection><auth-constraint></auth-constraint></security-constraint><security-constraint><web-resource-collection><web-resource-name>Servlet1</web-resource-name><url-pattern>/servlet1</url-pattern></web-resource-collection><auth-constraint><role-name>member</role-name><role-name>manager</role-name></auth-constraint></security-constraint><login-config><auth-method>FORM</auth-method><form-login-config><form-login-page>/login.html</form-login-page><form-error-page>/error.html</form-error-page></form-login-config></login-config>
</web-app>
login.html
<!DOCTYPE html>
<html><head><title>Login</title><meta http-equiv="keywords" content="keyword1,keyword2,keyword3"><meta http-equiv="description" content="this is my page"><meta http-equiv="content-type" content="text/html; charset=UTF-8"><!--<link rel="stylesheet" type="text/css" href="./styles.css">--></head><body><h1>Login Form</h1><form action='j_security_check' method='post'><div>User Name: <input name="j_username"/></div><div>Password: <input type='password' name='j_password'/></div><div><input type='submit' value='Login'/></div></form></body>
</html>
error.html
<!DOCTYPE html>
<html><head><title>Login error</title><meta http-equiv="keywords" content="keyword1,keyword2,keyword3"><meta http-equiv="description" content="this is my page"><meta http-equiv="content-type" content="text/html; charset=UTF-8"><!--<link rel="stylesheet" type="text/css" href="./styles.css">--></head><body>Login failed</body>
</html>
打开浏览器继续输入刚才的地址,会出来以下的页面:
客户端证书验证
客户端证书验证是在HTTPS(用SSL加密了的HTTP)上进行的,它要求每一个客户端都要有一个客户端证书。这是一种非常健壮的验证机制,但是不适用于在互联网上部署的应用程序,因为不可能要求每一个互联网用户都拥有一个数字证书。然而,这种验证方法可以用来访问公司内部网的应用程序。
15.3、SSL
SSL(Secure Socket Layer,加密套接字层)协议最早是Netscape公司开发出来的,它可以针对互联网上的通信进行加密,同时确保数据的保密性和完整性。
14.3.1、密码学
一开始,人们是利用对称加密进行加密和解密的。在对称加密中,用同一个密钥对信息进行加密和解密。这是一种非常简单的加密/解密技术。
假设,加密方法是用一个加密数字将字母表中的每一个字母都往前移。因此,如果加密数字为2,”ThisFriday”经过加密之后就变成了”VjkuHtkfca”。当你读完字母表时,又从头开始,因此y变成了a。接收方知道密钥为2,可以很容易地破解信息。
但是,对称加密要求双方都要提前知道加密/解密的密钥。基于以下原因,对称加密不适用于互联网:
1、交换信息的双方经常是互相不认识的。例如,在XX网上买书时,要将你的个人资料和信用卡资料发过去。如果使用对称加密术,你将不得不在进行交易之前给XX网站打电话,双方先确定以下密钥。
2、大家都希望能够与许多其他方进行通信。如果使用对称加密术,大家只好保留许多不同的唯一密钥,每个不同的通信方一个密钥。
3、由于你不认识即将进行通信的实体,因此必须确认对方是否真的是他们所生成的那个人。
4、在互联网上传递的信息要经过许多不同的计算机,因此要窃取别人的信息是很容易地事情。对称加密不能确保第三方不会篡改数据。
因此,当今互联网上的加密通信是采用非对称加密,它具有以下三个特征:
1、加密/解密。加密过的信息对第三方隐藏了信息。只有既定的接受方才能对信息进行解密。
2、验证。验证时证明某个实体是否为它所声明的那一个。
3、数据完整性。在互联网上发送的信息要传过许多计算机,因此必须确保所发送的数据没有被修改过,并且是完整的。
在非对称加密中,使用的是公钥加密法。在这种加密方法中,数据的加密和解密是通过一对非对称的密钥来实现的,即一个公钥和一个私钥。私钥是私人的,主人必须把它保存在一个安全的地方,绝不能被任何地方占有。公钥则是分发给公众的,通常想要与这些公钥的主人进行通信时,就可以下载到。配对的公钥和私钥可以利用工具来生成。
公钥加密的魅力在于,用公钥加密的数据只能利用对应的私钥才能进行解密;由此类推,用私钥加密的数据也只能用对应的公钥才能进行解密。这种完美的算法是基于非常巨大的质数,由麻省理工学院(MIT)的Ron Rivest、Adi Shamir和Len Adleman发明与1977年。他们将这种算法简单地称作RSA算法,即以它们三个人的姓的首字母组合而成。
14.3.2加密/解密
想要交换信息的双方中,必须要有偶乙方拥有一对密钥。假设Alice想要和Bob进行通信。Bob有一个公钥和一个私钥。Bob要将他的公钥发给Alice,Alice就可以用它对要发给Bob的信息进行加密。只有Bob能够对这些信息进行解密,因为他拥有对应的私钥。为了将信息发给Alice,Bob要利用它的私钥进行加密,Alice就可以用Bob的公钥进行解密。
但是,除非Bob能够亲自见到Alice并把它的公钥交给他,否则这种方法就很不完善了,单凡拥有密钥对的人们都可能声称自己是Bob,Alice根本无法查证。在互联网上,交换信息的双方经常住的相隔遥远,见面通常是不太可能的。
14.3.3、验证
在SSL中,验证是通过引入证书来解决的。证书包含以下内容:
1、一个公钥
2、相关主题的信息,如公钥的所有者。
3、证书颁发商的名称。
4、某种时间戳,使证书过了一定的时期之后会过期。
证书最为关键的是,必须通过可I型男人的证书颁发商进行数字签名,例如VeriSign或者Thawte,对一个电子文档进行数字签名,就是将你的的签名添加到文档/文件中。原始文件没有进行加密,签名的真正目的是要确保文档/文件没有被篡改,对一个文档进行签名,要包括创建文档的摘要信息,并利用颁发商的私钥对摘要进行加密,为了查看这个文档是否仍然保持原封不动,要执行以下两个步骤:
1、利用签署者的公钥对文档的摘要信息进行解密。你很快就会学到,可信任证书颁发商的公钥是很容易获取到的。
2、给文档创建摘要信息。
3、将上述第一步和第二步的结果进行比较,如果这两个结果匹配,则表示文件没有被篡改。
这种验证方法之所以可行,是因为只有私钥的所有者能够对文档摘要进行解密,并且这个柴窑信息只能通过对应公钥进行解密。加入你能确定自己所有拥有的是原版的公钥,那么就会知道这个文件有没有被修改过。
注意:由于证书可以通过可信任的证书颁发商进行数字签名,因此人们可以将他们的证书供大家公开下载,而不是采用他们的公钥。
证书颁发商会有一对公钥和私钥。申请证书时,Bob必须生成一对密钥,并将其公钥发给证书颁发商,随后证书颁发商就会请Bob发一份护照或者其他身份证明给他,由此证明Bob的身份。对Bob晚上验证后,证书颁发商就会用它的私钥对证书进行签名。“签名”的意思就是加密。因此,证书只能利用证书颁发商的公钥才能解毒。证书颁发商的公钥一般很容易下载到。例如,几乎所有主流浏览器都默认包含几家证书颁发商的公钥。
现在,有了数字证书之后,Bob在与别人交换信息之前,可以先发布他的数字证书,而不是发布他的公钥了。
其工作流程如下:
A->B Bob,你好!我要跟你通话,但我需要先确认以下你是否真实Bob
B->A 当然可以,这是我的证书。
A->B 这些还不够,我还需要你其他的身份证明资料。
B->A Alice,真的是我+[用Bob的密钥加密过的信息摘要]。
在Bob发给Alice的最后一条信息中,也就是用Bob的公钥进行签名的那条消息,可以向Alice证明这条信息是可信的。这就是验证的过程。Alice联系Bob,Bob将其证书发过去。但是,光有证书还不够,因为任何人都可能得到Bob的证书。别忘了,Bob可是将他的证书发给所有想要与他通信的人啊!因此,Bob还要给她发送一条消息(“Alice,真的是我”),并附上曾用其私钥对这条信息进行过加密的摘要。
Alice从证书中获得Bob的公钥。这个她可以做到,因为证书是利用证书颁发商的私钥签名的,Alice可以访问证书颁发商的公钥(她的浏览器上就有一份)。现在,她又收到一条消息,以及用Bob私钥加密过的摘要。Alice只要给这条消息创建一个摘要,并将它与Bob发给她的加密摘要进行对比即可。Alice之所以能够解密,是因为它是用Bob的私钥加密的,而Alice又有一份Bob的公钥。如果两者匹配,Alice就可以确定对方就是真正的Bob。
Alice对Bob完成验证之后,第一件事就是发送一个加密密钥,这个将在接下来的信息交流中使用。使得,一但建立其了加密渠道,SSL就会采用对称加密法,因为它的速度要比不对称加密法快得多。
这里还漏掉了一件事情没有交代。互联网上的信息要在许多计算机上传递的,那么你如何确保哪些信息的完整性呢?因为在传输途中,任何人都可能截取那些信息啊。
14.3.4、数据完整性
假设Mallet是一个怀有恶意的人,他很可能就坐在Alice和Bob之间,试图破解正在传递的消息,令Mallet遗憾的是,虽然他能够复制到信息,但是因为进行过加密,他并不知道密钥。但Mallet仍然可能破坏信息,或者不转播其中的某一个部分。为了解决这个问题,SSL引用了一个消息验证码(Message Authentication Code,MAC)。MAC是通过一个密钥和一些传输数据计算出来的一组数据。由于Mallet不知道密钥,因此他无法算出摘要的正确值,信息的接受者则可以,并且因此可以发现是否有人试图破坏数据,或者发现数据是否不完整。如果答案是肯定的,那么双方可以停止通信。
这类信息摘要算法之一为MD5,是由RSA发明的,非常安全。例如,如果使用128位的MAC值,那么恶意破坏者猜中正确值的几率大约为18 446 744 073 709 551 616分之一,也就是说,几乎永远不可能猜中。
14.3.5、SSL工作原理
知道了SSL如何解决加密/解密、验证及数据完整性的问题,现在来看一下SSL的工作原理。这次我们以Amazon(代替Bob)和一个买家(代替Alice)为例。就像其他任何合法的电子商务卖家一样,Amazon也向一个可信任的证书颁发商申请了一份证书。买家使用的是IE浏览器,其中嵌有可信任的证书颁发商的公钥。买家并不需要真正了解SSL的工作原理,也不需要拥有公钥和私钥。他只需要确保在输入重要的资料时,例如信用卡号码时,用HTTPS代替HTTP协议即可。这个必须显示在地址栏中的。
当买家输入一个加密页面(当他完成购物时),在后台中,这个浏览器和Amazon服务器之间会发生以下一系列事件。
浏览器:你真的是Amazon.com吗?
服务器:是的,这是我的证书。
然后,浏览器会利用证书颁发商的公钥进行解密,来验证证书的有效性。如果有哪里不对,例如证书过期,浏览器就会向用户发出警告。如果用户不顾证书过期,同意继续,浏览器就会继续。
浏览器:光有证书还不够,请再发点别的身份证明给我。
服务器:我真的是Amazon.com+[这条信息用Amazon.com的私钥加密过的摘要]
浏览器利用Amazon的公钥对消息摘要进行解密,并未“我真的是Amazon.com”创建一条消息摘要。如果两者匹配,表示验证成功。随后,浏览器就会产生一个随机密钥,利用Amazon的公钥对它进行加密。这个随机密钥将用于对后续的消息进行加密和解密,换句话说,一旦完成对Amazon的验证,就会采用对称加密,因为它的速度比飞对称加密要快得多。除了消息之外,双方还要发送消息摘要,以确保这些消息是完整的,没有被修改过。
14.4、通过编程确保安全性
尽管声明式安全简单易用,但偶尔还是需要通过编写代码来确保应用程序的安全性。为此,可以在HttpServletRequest接口中使用安全注解类型和方法。这两者都在下面进行讨论。
14.4.1、安全注解类型
javax.servlet.annotation包中与安全相关的3个注解类型是:ServletSecurity、HttpConstraint和HttpMethodConstraint。
ServletSecurity注解可以带有value和httpMethodConstraints属性。
httpConstraint注解类型用来定义一个安全约束,并且只能赋给ServletSecurity注解的value属性。如果包含的ServletSecurity注解中没有出现httpMethodConstraints属性,那么HttpConstraint注解所强加的安全约束将应用于所有的HTTP方法。否则,安全约束将只应用于httpMethodConstraints属性中定义的HTTP方法。例如,以下HttpConstraint注解表示所注解的Servlet只能由manager角色中的访客进行访问。
@ServletSecurity(value = @HttpConstraint(rolesAllowed = “manager”))
当然,上述注解也可以改写成:
@ServletSecurity(@HttpConstraint(rolesAllowed = “manager”))
但仍然需要在部署描述符中声明一个login-config元素,以便容器能够对用户进行验证。
将一个HttpConstraint注解的transportGuarantee属性设置为TransportGuarantee.CONFIDENTIAL,将使这个Servlet只能通过某个秘密渠道进行访问,例如SSL
@ServletSecurity(@HttpConstraint(transportGuarantee = TransportGuarantee.CONFIDENTIAL))
如果Servlet/JSP容器通过HTTP接收到针对这种Servlet的请求,它会将浏览器重定向到该URL的HTTPS版本。
HttpMethodConstraint注解类型用于定义某个安全约束索要应用到的HTTP方法,它只能放在ServletSecurity注解的httpMethodConstraints属性值数组中。例如,下面的httpMethodConstraint注解限制了只有manager角色的用户可以通过HTTP Get访问被注解的Servlet。对于其他的HTTP方法,则不存在任何限制。
@ServletSecurity(httpMethodConstraints = {@HttpMethodConstraint(value = “GET”, rolesAllowed = “manager”)})
注意,如果HttpMethodConstraint注解中没有出现rolesAllowed属性,那么所定义的HTTP方法将不受任何限制。例如,以下的ServletSecurity注解中使用了value和httpMethodConstraints这两个属性。
@ServletSecurity(value = @HttpConstraint(rolesAllowed = “manager”),
httpMethodConstraints = {@HttpMethodConstraint(“GET”)}
)
但是,如果HttpMethodConstraint注解类型的emptyRoleSemantic属性值为Empty-RoleSemantic.DENY,那么该方法将限制所有用户访问。例如,用下列ServletSecurity进行注解的Servlet,将禁止通过Get方法进行访问,但是云溪member角色中的所有用户通过其他的HTTP方法进行访问。
@ServletSecurity(value = @HttpConstraint(rolesAllowed = “member”),
httpMethodConstraints = {@HttpMethodConstraint(value = “GET”,
emptyRoleSemantic = EmptyRoleSemantic.DENY
)}
)
14.4.2、Servlet安全API
除了利用注解类型,也可以在HttpServletRequest接口中利用以下方法来实现编程式的安全性。
java.lang.String getAuthType()
返回用来保护Servlet的验证方案,如果该Servlet中没有应用任何安全约束,则返回null。
java.lang.String getRemoteUser()
返回发出该请求的用户的登录名,如果该用户未经验证,则返回null
boolean isUserInRole(java.lang.String role)
返回一个布尔值,表明该用户是否属于规定的角色。
java.lang.Principal getUserPrincipal()
返回一个包含当前被验证用户详细信息的java.security.Principal,如果该用户未经验证,则返回null
boolean authenticate(HttpServletResponse response) throws java.io.IOException
命令浏览器显示一个登录窗口,以便对用户进行验证。
void login(java.lang.String userName, java.lang.String password) throws javax.servlet.ServletException
通过提供的用户名和密码进行登录,如果登录成功,该方法将不返回任何内容。否则,将抛出一个ServletException。
void logout() throws javax.servlet.ServletException
注销用户
下面是一个例子,展示了如何通过编程来完成对用户的验证。
ProgrammaticServlet.java
package servlet ;import java.io.IOException;
import java.io.PrintWriter;import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet(urlPatterns = {"/prog"})
public class ProgrammaticServlet extends HttpServlet {private static final long serialVersionUID = 1L;@Overridepublic void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {if (request.authenticate(response)) {response.setContentType("text/html");PrintWriter out = response.getWriter() ;out.println("Welcome");} else {System.out.println("User not authenicated");}}
}
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1"><login-config><auth-method>DIGEST</auth-method><realm-name>Digest authentication</realm-name></login-config>
</web-app>
当用户第一次请求该Servlet时,用户还没有进行验证,验证方法将返回false。因此,Servlet/JSP容器会发出一个WWW-Authenticate标头,使浏览器显示一个登录对话框,进行摘要访问验证。当用户提交填有正确用户名和密码的表单时,authenticate方法返回true,并显示欢迎消息。
这篇关于第十四章_安全性的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!