第十四章_安全性
Posted yutingliuyl
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了第十四章_安全性相关的知识,希望对你有一定的参考价值。
14.1、验证和授权
验证是检验某个人是否是他/她所声称的那个人的过程。
在Servlet/JSP应用程序中,验证通常是通过要求用户输入username和password来完毕的。
授权主要是确定一个用户具有什么样的訪问级别。
它使用于包括多个訪问区域的应用程序,使用户可以訪问应用程序的某一部分,可是不能訪问其它部分。
比如。网上商店可以分为公共区(供一般的公共浏览和查找商品),买家区(供已注冊用户下单用),以及须要最高訪问级别的管理区。不仅管理员用户自身也须要进行验证,而且还必须是已经被同意訪问管理区的用户才行。訪问级别常常被称作角色。
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、基本訪问验证
基本訪问验证,简称基本验证,是一种接受username和password的HTTP验证。在基本訪问验证中,假设用户訪问受保护的资源,将会遭到server的拒绝,并返回一个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”
随后浏览器屏幕上回显示一个登录对话框。供用户输入username和password。
当用户单击Login登录button时,username后面会被添上一个冒号,并和password结合在一起。这个字符串被送到server之前,将先用Base64算法进行编码。登录成功之后。server就会发出被请求的资源。
Base64是一种非常弱的算法,因此Base64消息非常easy被破解。
因此。要考虑使用摘要訪问来取代。
以下展示了怎样使用基本訪问验证。第一个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; @Override public 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算法创建一个散列。当中结合了username、relam名称以及password,并将这个散列发送到server。摘要訪问验证旨在代替基本訪问验证,由于她提供了更加安全的环境。
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>
打开浏览器继续输入刚才的地址,会出来下面的页面:
client证书验证
client证书验证是在HTTPS(用SSL加密了的HTTP)上进行的,它要求每个client都要有一个client证书。这是一种很健壮的验证机制。可是不适用于在互联网上部署的应用程序。由于不可能要求每个互联网用户都拥有一个数字证书。然而。这样的验证方法能够用来訪问公司内部网的应用程序。
15.3、SSL
SSL(Secure Socket Layer,加密套接字层)协议最早是Netscape公司开发出来的,它能够针对互联网上的通信进行加密。同一时候确保数据的保密性和完整性。
14.3.1、password学
一開始。人们是利用对称加密进行加密和解密的。
在对称加密中。用同一个密钥对信息进行加密和解密。这是一种很easy的加密/解密技术。
如果,加密方法是用一个加密数字将字母表中的每个字母都往前移。因此,如果加密数字为2。”ThisFriday”经过加密之后就变成了”VjkuHtkfca”。当你读完字母表时。又从头開始,因此y变成了a。
接收方知道密钥为2,能够非常easy地破解信息。
可是。对称加密要求两方都要提前知道加密/解密的密钥。基于下面原因。对称加密不适用于互联网:
1、交换信息的两方常常是互相不认识的。
比如。在XX网上买书时,要将你的个人资料和信用卡资料发过去。假设使用对称加密术,你将不得不在进行交易之前给XX站点打电话。两方先确定下面密钥。
2、大家都希望可以与更多方进行通信。假设使用对称加密术。大家仅仅好保留很多不同的唯一密钥。每一个不同的通信方一个密钥。
3、因为你不认识即将进行通信的实体。因此必须确认对方是否真的是他们所生成的那个人。
4、在互联网上传递的信息要经过很多不同的计算机,因此要窃取别人的信息是非常easy地事情。
对称加密不能确保第三方不会篡改数据。
因此,当今互联网上的加密通信是採用非对称加密。它具有下面三个特征:
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、利用签署者的公钥对文档的摘要信息进行解密。你非常快就会学到,可信任证书颁发商的公钥是非常easy获取到的。
2、给文档创建摘要信息。
3、将上述第一步和第二步的结果进行比較,假设这两个结果匹配,则表示文件没有被篡改。
这样的验证方法之所以可行,是由于仅仅有私钥的全部者可以对文档摘要进行解密,而且这个柴窑信息仅仅能通过相应公钥进行解密。增加你能确定自己全部拥有的是原版的公钥,那么就会知道这个文件有没有被改动过。
注意:因为证书能够通过可信任的证书颁发商进行数字签名,因此人们能够将他们的证书供大家公开下载,而不是採用他们的公钥。
证书颁发商会有一对公钥和私钥。
申请证书时。Bob必须生成一对密钥,并将其公钥发给证书颁发商,随后证书颁发商就会请Bob发一份护照或者其它身份证明给他,由此证明Bob的身份。对Bob晚上验证后,证书颁发商就会用它的私钥对证书进行签名。“签名”的意思就是加密。因此,证书仅仅能利用证书颁发商的公钥才干解毒。证书颁发商的公钥一般非常easy下载到。比如,差点儿全部主流浏览器都默认包括几家证书颁发商的公钥。
如今。有了数字证书之后,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协议就可以。
这个必须显示在地址栏中的。
当买家输入一个加密页面(当他完毕购物时),在后台中,这个浏览器和Amazonserver之间会发生下面一系列事件。
浏览器:你真的是Amazon.com吗?
server:是的,这是我的证书。
然后,浏览器会利用证书颁发商的公钥进行解密,来验证证书的有效性。假设有哪里不正确,比如证书过期,浏览器就会向用户发出警告。假设用户不顾证书过期。允许继续,浏览器就会继续。
浏览器:光有证书还不够,请再发点别的身份证明给我。
server:我真的是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
通过提供的username和password进行登录,假设登录成功。该方法将不返回不论什么内容。否则,将抛出一个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; @Override public 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标头,使浏览器显示一个登录对话框。进行摘要訪问验证。当用户提交填有正确username和password的表单时,authenticate方法返回true。并显示欢迎消息。
以上是关于第十四章_安全性的主要内容,如果未能解决你的问题,请参考以下文章