1- 为什么使用安全性?
安全性是在Internet 上传输重要数据的应用程序的一个重要方面。
验证
身份验证是在用户进入网站保护区之前验证用户访问权限的过程。有两种主要的身份验证方法:基本身份验证和基于表单的身份验证。
基本认证
对于基本身份验证,用户可以完全正常访问每个页面。对于要求安全的页面,将显示一个窗口供用户输入他/她的 用户名/密码。用户名/密码信息将 与请求一起发送到服务器。
当用户在浏览器上输入路径时,按Enter请求页面。一个“用户代理”信息被创建并随请求一起发送。通常,这些信息包括用户的浏览器信息、操作系统信息。在基本身份验证的情况下,用户名/密码信息捆绑在“用户代理”中。
在这篇文章中,我没有详细提及基本身份验证。
基于表单的身份验证
大多数网站使用基于表单的身份验证。网站允许用户在不要求密码的情况下访问每个常见页面。但是,如果用户访问受保护的页面,它将重定向到登录页面。
在本课中,我将详细介绍如何使用Servlet 过滤器来 保密Java Web
在安全方面,有两个重要的概念,例如Principal和 Role。
角色
角色 是应用程序的一组权限。
为简单起见,我举个例子,ABC应用程序有“ EMPLOYEE ”和“ MANAGER ”两个角色。
- “ EMPLOYEE”角色被允许使用销售功能和客户信息创建功能。
- “ 经理” 角色被允许使用员工管理功能并查看收入报告。
主要的
Principal可以暂时理解为登录系统后的“Subject”。它有权在系统中做某事。“主题”可以有一个或多个角色。这取决于每个不同用户帐户的应用程序权限。
在Java Servlet应用程序中, Servlet 过滤器 专门用于处理安全性。它通常被称为安全过滤器。
以下是安全过滤器的操作原理。
当用户访问受保护的页面时,安全过滤器将对其进行测试。如果用户没有登录,用户的请求将被重定向到登录页面。
如果用户访问成功,则创建一个 Principal 对象。它带来了用户的信息,包括角色。
如果用户之前已经成功登录,并访问了受保护的页面。安全过滤器将检查用户的角色是否适合访问此页面。如果它无效,它将向用户显示一个页面,通知访问被拒绝。
这是我们将执行的应用程序结构:
该应用程序包括 2 个角色,例如 EMPLOYEE和 MANAGER。
- EMPLOYEE角色允许访问 /userInfo 和 /employeeTask等2 个页面
- MANAGER角色允许访问 2 个页面, 例如 /userInfo和 /managerTask。
有 2 个用户,例如employee1 和 manager1。
- 员工1 被分配了EMPLOYEE角色
- manager1 被 分配了MANAGER和 EMPLOYEE角色。
用户可以正常访问所有未受保护的页面。但是,如果用户访问受保护的 ABC 页面,它将重定向到登录页面。用户登录成功,会出现两种情况:
- 如果userName具有合适的角色,应用程序将在登录成功后重定向到 ABC页面。
- 如果用户名具有不适当 的角色,应用程序将显示拒绝访问信息。
在 Eclipse 上,创建一个 名为SecurityWebApp的“动态 Web 项目”,并进行配置以便它可以在Tomcat Server上运行。具体步骤我就不细说了,大家可以参考下面的教程:
UserAccount类代表应用程序的用户。
用户帐户.java
package org.o7planning.securitywebapp.bean;
import java.util.ArrayList;
import java.util.List;
public class UserAccount {
public static final String GENDER_MALE = "M";
public static final String GENDER_FEMALE = "F";
private String userName;
private String gender;
private String password;
private List<String> roles;
public UserAccount() {
}
public UserAccount(String userName, String password, String gender, String... roles) {
this.userName = userName;
this.password = password;
this.gender = gender;
this.roles = new ArrayList<String>();
if (roles != null) {
for (String r : roles) {
this.roles.add(r);
}
}
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public List<String> getRoles() {
return roles;
}
public void setRoles(List<String> roles) {
this.roles = roles;
}
}
DataDAO类用于 查询数据库中的数据(模拟)。
数据DAO.java
package org.o7planning.securitywebapp.utils;
import java.util.HashMap;
import java.util.Map;
import org.o7planning.securitywebapp.bean.UserAccount;
import org.o7planning.securitywebapp.config.SecurityConfig;
public class DataDAO {
private static final Map<String, UserAccount> mapUsers = new HashMap<String, UserAccount>();
static {
initUsers();
}
private static void initUsers() {
// This user has a role as EMPLOYEE.
UserAccount emp = new UserAccount("employee1", "123", UserAccount.GENDER_MALE, //
SecurityConfig.ROLE_EMPLOYEE);
// This user has 2 roles EMPLOYEE and MANAGER.
UserAccount mng = new UserAccount("manager1", "123", UserAccount.GENDER_MALE, //
SecurityConfig.ROLE_EMPLOYEE, SecurityConfig.ROLE_MANAGER);
mapUsers.put(emp.getUserName(), emp);
mapUsers.put(mng.getUserName(), mng);
}
// Find a User by userName and password.
public static UserAccount findUser(String userName, String password) {
UserAccount u = mapUsers.get(userName);
if (u != null && u.getPassword().equals(password)) {
return u;
}
return null;
}
}
SecurityConfig类有助于配置允许该角色访问的角色和功能(站点) 。
安全配置.java
package org.o7planning.securitywebapp.config;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
public class SecurityConfig {
public static final String ROLE_MANAGER = "MANAGER";
public static final String ROLE_EMPLOYEE = "EMPLOYEE";
// String: Role
// List<String>: urlPatterns.
private static final Map<String, List<String>> mapConfig = new HashMap<String, List<String>>();
static {
init();
}
private static void init() {
// Configure For "EMPLOYEE" Role.
List<String> urlPatterns1 = new ArrayList<String>();
urlPatterns1.add("/userInfo");
urlPatterns1.add("/employeeTask");
mapConfig.put(ROLE_EMPLOYEE, urlPatterns1);
// Configure For "MANAGER" Role.
List<String> urlPatterns2 = new ArrayList<String>();
urlPatterns2.add("/userInfo");
urlPatterns2.add("/managerTask");
mapConfig.put(ROLE_MANAGER, urlPatterns2);
}
public static Set<String> getAllAppRoles() {
return mapConfig.keySet();
}
public static List<String> getUrlPatternsForRole(String role) {
return mapConfig.get(role);
}
}
SecurityUtils类是一个实用程序类,它具有帮助检查请求是否需要登录以及该请求是否适合用户登录角色的方法。
SecurityUtils.java
package org.o7planning.securitywebapp.utils;
import java.util.List;
import java.util.Set;
import javax.servlet.http.HttpServletRequest;
import org.o7planning.securitywebapp.config.SecurityConfig;
public class SecurityUtils {
// Check whether this 'request' is required to login or not.
public static boolean isSecurityPage(HttpServletRequest request) {
String urlPattern = UrlPatternUtils.getUrlPattern(request);
Set<String> roles = SecurityConfig.getAllAppRoles();
for (String role : roles) {
List<String> urlPatterns = SecurityConfig.getUrlPatternsForRole(role);
if (urlPatterns != null && urlPatterns.contains(urlPattern)) {
return true;
}
}
return false;
}
// Check if this 'request' has a 'valid role'?
public static boolean hasPermission(HttpServletRequest request) {
String urlPattern = UrlPatternUtils.getUrlPattern(request);
Set<String> allRoles = SecurityConfig.getAllAppRoles();
for (String role : allRoles) {
if (!request.isUserInRole(role)) {
continue;
}
List<String> urlPatterns = SecurityConfig.getUrlPatternsForRole(role);
if (urlPatterns != null && urlPatterns.contains(urlPattern)) {
return true;
}
}
return false;
}
}
UrlPatternUtils.java
package org.o7planning.securitywebapp.utils;
import java.util.Collection;
import java.util.Map;
import javax.servlet.ServletContext;
import javax.servlet.ServletRegistration;
import javax.servlet.http.HttpServletRequest;
public class UrlPatternUtils {
private static boolean hasUrlPattern(ServletContext servletContext, String urlPattern) {
Map<String, ? extends ServletRegistration> map = servletContext.getServletRegistrations();
for (String servletName : map.keySet()) {
ServletRegistration sr = map.get(servletName);
Collection<String> mappings = sr.getMappings();
if (mappings.contains(urlPattern)) {
return true;
}
}
return false;
}
// servletPath:
// ==> /spath
// ==> /spath/*
// ==> *.ext
// ==> /
public static String getUrlPattern(HttpServletRequest request) {
ServletContext servletContext = request.getServletContext();
String servletPath = request.getServletPath();
String pathInfo = request.getPathInfo();
String urlPattern = null;
if (pathInfo != null) {
urlPattern = servletPath + "/*";
return urlPattern;
}
urlPattern = servletPath;
boolean has = hasUrlPattern(servletContext, urlPattern);
if (has) {
return urlPattern;
}
int i = servletPath.lastIndexOf('.');
if (i != -1) {
String ext = servletPath.substring(i + 1);
urlPattern = "*." + ext;
has = hasUrlPattern(servletContext, urlPattern);
if (has) {
return urlPattern;
}
}
return "/";
}
}
SecurityFilter是一个 Servlet 过滤器,它负责在允许访问受保护页面之前检查请求。
SecurityFilter读取 在 SecurityConfig 类中声明的“安全配置” 。
SecurityFilter读取 在 SecurityConfig 类中声明的“安全配置” 。
安全过滤器.java
package org.o7planning.securitywebapp.filter;
import java.io.IOException;
import java.util.List;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.o7planning.securitywebapp.bean.UserAccount;
import org.o7planning.securitywebapp.request.UserRoleRequestWrapper;
import org.o7planning.securitywebapp.utils.AppUtils;
import org.o7planning.securitywebapp.utils.SecurityUtils;
@WebFilter("/*")
public class SecurityFilter implements Filter {
public SecurityFilter() {
}
@Override
public void destroy() {
}
@Override
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) resp;
String servletPath = request.getServletPath();
// User information stored in the Session.
// (After successful login).
UserAccount loginedUser = AppUtils.getLoginedUser(request.getSession());
if (servletPath.equals("/login")) {
chain.doFilter(request, response);
return;
}
HttpServletRequest wrapRequest = request;
if (loginedUser != null) {
// User Name
String userName = loginedUser.getUserName();
// Roles
List<String> roles = loginedUser.getRoles();
// Wrap old request by a new Request with userName and Roles information.
wrapRequest = new UserRoleRequestWrapper(userName, roles, request);
}
// Pages must be signed in.
if (SecurityUtils.isSecurityPage(request)) {
// If the user is not logged in,
// Redirect to the login page.
if (loginedUser == null) {
String requestUri = request.getRequestURI();
// Store the current page to redirect to after successful login.
int redirectId = AppUtils.storeRedirectAfterLoginUrl(request.getSession(), requestUri);
response.sendRedirect(wrapRequest.getContextPath() + "/login?redirectId=" + redirectId);
return;
}
// Check if the user has a valid role?
boolean hasPermission = SecurityUtils.hasPermission(wrapRequest);
if (!hasPermission) {
RequestDispatcher dispatcher //
= request.getServletContext().getRequestDispatcher("/WEB-INF/views/accessDeniedView.jsp");
dispatcher.forward(request, response);
return;
}
}
chain.doFilter(wrapRequest, response);
}
@Override
public void init(FilterConfig fConfig) throws ServletException {
}
}
UserRoleRequestWrapper.java
package org.o7planning.securitywebapp.request;
import java.security.Principal;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
/**
* An extension for the HTTPServletRequest that overrides the getUserPrincipal()
* and isUserInRole(). We supply these implementations here, where they are not
* normally populated unless we are going through the facility provided by the
* container.
* <p>
* If he user or roles are null on this wrapper, the parent request is consulted
* to try to fetch what ever the container has set for us. This is intended to
* be created and used by the UserRoleFilter.
*
* @author thein
*
*/
public class UserRoleRequestWrapper extends HttpServletRequestWrapper {
private String user;
private List<String> roles = null;
private HttpServletRequest realRequest;
public UserRoleRequestWrapper(String user, List<String> roles, HttpServletRequest request) {
super(request);
this.user = user;
this.roles = roles;
this.realRequest = request;
}
@Override
public boolean isUserInRole(String role) {
if (roles == null) {
return this.realRequest.isUserInRole(role);
}
return roles.contains(role);
}
@Override
public Principal getUserPrincipal() {
if (this.user == null) {
return realRequest.getUserPrincipal();
}
// Make an anonymous implementation to just return our user
return new Principal() {
@Override
public String getName() {
return user;
}
};
}
}
HomeServlet.java
package org.o7planning.securitywebapp.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({ "/", "/index" })
public class HomeServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
public HomeServlet() {
super();
}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
RequestDispatcher dispatcher //
= this.getServletContext().getRequestDispatcher("/WEB-INF/views/homeView.jsp");
dispatcher.forward(request, response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
登录Servlet.java
package org.o7planning.securitywebapp.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;
import org.o7planning.securitywebapp.bean.UserAccount;
import org.o7planning.securitywebapp.utils.AppUtils;
import org.o7planning.securitywebapp.utils.DataDAO;
@WebServlet("/login")
public class LoginServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
public LoginServlet() {
super();
}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
RequestDispatcher dispatcher //
= this.getServletContext().getRequestDispatcher("/WEB-INF/views/loginView.jsp");
dispatcher.forward(request, response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String userName = request.getParameter("userName");
String password = request.getParameter("password");
UserAccount userAccount = DataDAO.findUser(userName, password);
if (userAccount == null) {
String errorMessage = "Invalid userName or Password";
request.setAttribute("errorMessage", errorMessage);
RequestDispatcher dispatcher //
= this.getServletContext().getRequestDispatcher("/WEB-INF/views/loginView.jsp");
dispatcher.forward(request, response);
return;
}
AppUtils.storeLoginedUser(request.getSession(), userAccount);
//
int redirectId = -1;
try {
redirectId = Integer.parseInt(request.getParameter("redirectId"));
} catch (Exception e) {
}
String requestUri = AppUtils.getRedirectAfterLoginUrl(request.getSession(), redirectId);
if (requestUri != null) {
response.sendRedirect(requestUri);
} else {
// Default after successful login
// redirect to /userInfo page
response.sendRedirect(request.getContextPath() + "/userInfo");
}
}
}
AppUtils.java
package org.o7planning.securitywebapp.utils;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpSession;
import org.o7planning.securitywebapp.bean.UserAccount;
public class AppUtils {
private static int REDIRECT_ID = 0;
private static final Map<Integer, String> id_uri_map = new HashMap<Integer, String>();
private static final Map<String, Integer> uri_id_map = new HashMap<String, Integer>();
// Store user info in Session.
public static void storeLoginedUser(HttpSession session, UserAccount loginedUser) {
// On the JSP can access via ${loginedUser}
session.setAttribute("loginedUser", loginedUser);
}
// Get the user information stored in the session.
public static UserAccount getLoginedUser(HttpSession session) {
UserAccount loginedUser = (UserAccount) session.getAttribute("loginedUser");
return loginedUser;
}
public static int storeRedirectAfterLoginUrl(HttpSession session, String requestUri) {
Integer id = uri_id_map.get(requestUri);
if (id == null) {
id = REDIRECT_ID++;
uri_id_map.put(requestUri, id);
id_uri_map.put(id, requestUri);
return id;
}
return id;
}
public static String getRedirectAfterLoginUrl(HttpSession session, int redirectId) {
String url = id_uri_map.get(redirectId);
if (url != null) {
return url;
}
return null;
}
}
LogoutServlet.java
package org.o7planning.securitywebapp.servlet;
import java.io.IOException;
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("/logout")
public class LogoutServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
public LogoutServlet() {
super();
}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
request.getSession().invalidate();
// Redrect to Home Page.
response.sendRedirect(request.getContextPath() + "/");
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
this.doGet(request, response);
}
}
UserInfoServlet.java
package org.o7planning.securitywebapp.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("/userInfo")
public class UserInfoServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
public UserInfoServlet() {
super();
}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
RequestDispatcher dispatcher //
= this.getServletContext().getRequestDispatcher("/WEB-INF/views/userInfoView.jsp");
dispatcher.forward(request, response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
id="WebApp_ID" version="3.0">
<display-name>SecurityWebApp</display-name>
<welcome-file-list>
<welcome-file>/</welcome-file>
</welcome-file-list>
</web-app>
/WEB-INF/views/_menu.jsp
<a href="${pageContext.request.contextPath}/employeeTask">
Employee Task
</a>
||
<a href="${pageContext.request.contextPath}/managerTask">
Manager Task
</a>
||
<a href="${pageContext.request.contextPath}/userInfo">
User Info
</a>
||
<a href="${pageContext.request.contextPath}/login">
Login
</a>
||
<a href="${pageContext.request.contextPath}/logout">
Logout
</a>
<span style="color:red">[ ${loginedUser.userName} ]</span>
/WEB-INF/views/homeView.jsp
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Home Page</title>
</head>
<body>
<jsp:include page="_menu.jsp"></jsp:include>
<h3>Home Page</h3>
</body>
</html>
/WEB-INF/views/loginView.jsp
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Login</title>
</head>
<body>
<jsp:include page="_menu.jsp"></jsp:include>
<h3>Login Page</h3>
<p style="color: red;">${errorString}</p>
<form method="POST" action="${pageContext.request.contextPath}/login">
<input type="hidden" name="redirectId" value="${param.redirectId}" />
<table border="0">
<tr>
<td>User Name</td>
<td><input type="text" name="userName" value= "${user.userName}" /> </td>
</tr>
<tr>
<td>Password</td>
<td><input type="password" name="password" value= "${user.password}" /> </td>
</tr>
<tr>
<td colspan ="2">
<input type="submit" value= "Submit" />
<a href="${pageContext.request.contextPath}/">Cancel</a>
</td>
</tr>
</table>
</form>
<p style="color:blue;">Login with:</p>
employee1/123 <br>
manager1/123
</body>
</html>
/WEB-INF/views/userInfoView.jsp
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>User Info</title>
</head>
<body>
<jsp:include page="_menu.jsp"></jsp:include>
<h3>Hello: ${loginedUser.userName}</h3>
User Name: <b>${loginedUser.userName}</b>
<br />
Gender: ${loginedUser.gender } <br />
</body>
</html>
运行应用程序:
EmployeeTaskServlet.java
package org.o7planning.securitywebapp.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("/employeeTask")
public class EmployeeTaskServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
public EmployeeTaskServlet() {
super();
}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
RequestDispatcher dispatcher //
= this.getServletContext()//
.getRequestDispatcher("/WEB-INF/views/employeeTaskView.jsp");
dispatcher.forward(request, response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
ManagerTaskServlet.java
package org.o7planning.securitywebapp.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("/managerTask")
public class ManagerTaskServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
public ManagerTaskServlet() {
super();
}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
RequestDispatcher dispatcher //
= this.getServletContext()//
.getRequestDispatcher("/WEB-INF/views/managerTaskView.jsp");
dispatcher.forward(request, response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
/WEB-INF/views/employeeTaskView.jsp
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Employee Task</title>
</head>
<body>
<jsp:include page="_menu.jsp"></jsp:include>
<h3>Employee Task</h3>
Hello, This is a protected page!
</body>
</html>
/WEB-INF/views/managerTaskView.jsp
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Manager Task</title>
</head>
<body>
<jsp:include page="_menu.jsp"></jsp:include>
<h3>Manager Task</h3>
Hello, This is a protected page!
</body>
</html>
/WEB-INF/views/accessDenied.jsp
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Access Denied</title>
</head>
<body>
<jsp:include page="_menu.jsp"></jsp:include>
<br/><br/>
<h3 style="color:red;">Access Denied!</h3>
</body>
</html>
运行应用程序:
运行应用程序并使用userName = "employee1" 登录,这 是角色为 "EMPLOYEE"的用户。
运行应用程序并使用userName = "manager1"登录,该用户具有两个角色,例如"EMPLOYEE" 和 "MANAGER"。
查看更多教程: