在JSP和servlet开发的应用程序中,Web开发人员可以使用几种机制来保护应用程序。资源通过在应用程序部署描述符中标识它们并向其分配角色来以声明方式进行保护。
有几个级别的身份验证可用,从使用标识符和密码的基本身份验证到使用证书的复杂身份验证。
基于角色的认证
servlet规范中的认证机制使用了一种称为基于角色的安全性技术。这个做法是,不是在用户级别限制资源,而是创建角色并通过角色限制资源。
可以在文件tomcat-users.xml
中定义不同的角色,tomcat-users.xml
位于Tomcat的主目录conf
中。此文件的示例如下所示 -
<?xml version = '1.0' encoding = 'utf-8'?>
<tomcat-users>
<role rolename = "tomcat"/>
<role rolename = "role1"/>
<role rolename = "manager"/>
<role rolename = "admin"/>
<user username = "tomcat" password = "tomcat" roles = "tomcat"/>
<user username = "role1" password = "tomcat" roles = "role1"/>
<user username = "both" password = "tomcat" roles = "tomcat,role1"/>
<user username = "admin" password = "secret" roles = "admin,manager"/>
</tomcat-users>
此文件定义了用户名,密码和角色之间的简单映射。请注意,给定的用户可能有多个角色; 例如,username =“both”
有两个角色:“tomcat”
角色和“role1”
角色。
当确定并定义了不同的角色,就可以通过使用WEB-INF
目录中web.xml
文件中的<security-constraint>
元素,将基于角色的安全限制放在不同的Web应用程序资源上。
以下是web.xml中的示例元素项 -
<web-app>
...
<security-constraint>
<web-resource-collection>
<web-resource-name>SecuredBookSite</web-resource-name>
<url-pattern>/secured/*</url-pattern>
<http-method>GET</http-method>
<http-method>POST</http-method>
</web-resource-collection>
<auth-constraint>
<description>
Let only managers use this app
</description>
<role-name>manager</role-name>
</auth-constraint>
</security-constraint>
<security-role>
<role-name>manager</role-name>
</security-role>
<login-config>
<auth-method>BASIC</auth-method>
</login-config>
...
</web-app>
以上元素项将意味着 -
- 对与
/secured/*
匹配的URL的任何HTTP GET或POST请求将受到安全限制。 - 具有
manager
角色的人员可获得安全资源。 login-config
元素用于描述BASIC认证形式。
如果尝试浏览包含/security
目录的任何URL,将显示以下对话框,要求输入用户名和密码。 如果提供了用户:admin
和密码:secrer
,那么可以访问与/secured/*
匹配的URL,因为我们已将用户管理员定义为允许访问该资源的manager
角色。
基于表单的认证
使用表单身份验证方法时,必须提供登录表单以提示用户输入用户名和密码。 以下是login.jsp
的简单代码。 这有助于为同一目的创建一个表单 -
<html>
<body bgcolor = "#ffffff">
<form method = "POST" action ="j_security_check">
<table border = "0">
<tr>
<td>Login</td>
<td><input type = "text" name="j_username"></td>
</tr>
<tr>
<td>Password</td>
<td><input type = "password" name="j_password"></td>
</tr>
</table>
<input type = "submit" value = "Login!">
</form>
</body>
</html>
在这里,必须确保登录表单中有包含名为:j_username
和j_password
的表单元素。 <form>
标签中的操作必须是j_security_check
。必须用作表单方法: POST
。 同时,还需要修改<login-config>
标签,将auth-method
指定为FORM
-
<web-app>
...
<security-constraint>
<web-resource-collection>
<web-resource-name>SecuredBookSite</web-resource-name>
<url-pattern>/secured/*</url-pattern>
<http-method>GET</http-method>
<http-method>POST</http-method>
</web-resource-collection>
<auth-constraint>
<description>Let only managers use this app</description>
<role-name>manager</role-name>
</auth-constraint>
</security-constraint>
<security-role>
<role-name>manager</role-name>
</security-role>
<login-config>
<auth-method>FORM</auth-method>
<form-login-config>
<form-login-page>/login.jsp</form-login-page>
<form-error-page>/error.jsp</form-error-page>
</form-login-config>
</login-config>
...
</web-app>
现在当尝试访问URL /secured/*
任何资源时,将显示上述表单,询问用户ID和密码。 当容器看到j_security_check
操作时,它使用一些内部机制来认证调用者。
如果登录成功并且呼叫者被授权访问受保护的资源,则容器使用会话ID从该点起为调用者标识登录会话。容器使用包含session-id
的cookie维护登录会话。 服务器将cookie发送回客户端,只要主调用方后续请求者提供该cookie,容器将知道调用者是谁。
如果登录失败,则服务器返回通过表单错误页面设置标识的页面
这里,j_security_check
是使用表单登录的应用程序必须为登录表单指定的操作。 同样的形式,还应该有一个名为j_username
的文本输入控件和一个名为j_password
的密码输入控件。当看到这个,这意味着表单中包含的信息将被提交到服务器,这将检查名称和密码。 这是如何完成的是服务器特定的。
检查标准领域实现,以了解j_security_check
如何用于Tomcat容器。
Servlet/JSP中的程序安全性
HttpServletRequest
对象提供以下方法,可用于在运行时挖掘安全信息 -
编号 | 方法 | 描述 |
---|---|---|
1 | String getAuthType() |
getAuthType() 方法返回一个String 对象,该对象表示用于保护Servlet的认证方案的名称。 |
2 | boolean isUserInRole(java.lang.String role) |
isUserInRole() 方法返回一个布尔值:如果用户处于给定角色,则返回true ,否则返回false 。 |
3 | String getProtocol() |
getProtocol() 方法返回一个String对象,表示用于发送请求的协议。可以检查该值以确定是否使用安全协议。 |
4 | boolean isSecure() |
isSecure() 方法返回一个布尔值,表示是否使用HTTPS进行请求。值设置为true 意味着它是和连接是安全的。 值设置为false 表示请求不是安全的。 |
5 | Principle getUserPrinciple() |
getUserPrinciple() 方法返回一个java.security.Principle 对象,该对象包含当前已验证用户的名称。 |
例如,对于链接到管理员的页面的JSP,可以使用以下代码 -
<% if (request.isUserInRole("manager")) { %>
<a href = "managers/mgrreport.jsp">Manager Report</a>
<a href = "managers/personnel.jsp">Personnel Records</a>
<% } %>
通过检查用户在JSP或Servlet中的角色,可以自定义该页面,仅向用户显示可以访问的项目。 如果需要在认证表单中输入用户名,可以在请求对象中调用getRemoteUser()
方法。