1.什么是Filter
① JavaWeb的一个重要组件,可以对发送到Servlet的请求进行拦截,并对响应也进行拦截。
② Filter是实现了Filter接口的Java类
③ Filter 需要在web.xml文件中进行配置和映射
2.如何创建一个Filter,并跑起来
①.创建一个Filter类:实现Filter接口:public class MyFilter implements Filter
②.在web.xml文件中配置并映射该Filter
<!-- 注册Filter --> <filter> <filter-name>firstFilter</filter-name> <filter-class>com.java.testFilter.MyFilter</filter-class> </filter> <!-- 映射Filter --> <filter-mapping> <filter-name>firstFilter</filter-name> <url-pattern>/test.jsp</url-pattern> </filter-mapping>
3.Filter的API
Filter接口:
@Override
public void destroy()
释放当前Filter 所占用的资源的方法.在Filter被销毁之前调用,且只被调用一次.
@Override
public void doFilter(ServletRequest arg0, ServletResponse arg1,
FilterChain filterChain) throws IOException, ServletException
真正Filter的逻辑代码需要写在该方法中.每次拦截都会调用该方法.
*FilterChain : Filter链,多个Filter可以构成一个Filter链.
filterChain.doFilter(ServletRequest arg0, ServletResponse arg1) 把请求传给Filter链的下一个
Filter,若当前Filter是Filter链的最后一个Filter,将把请求给到目标Servlet(或JSP)
*多个Filter的拦截顺序和<filter-mapping>的配置顺序有关,靠前的先被调用.
@Override
public void init(FilterConfig arg0) throws ServletException {
System.out.println("init...");
}
//类似于Servlet的init方法.在创建Filter对象(Filter对象被web应用加载时立即被调用,
且只被调用一次.该方法对于当前的Filter进行初始化操作.Filter实例是单例的)
*FilterConfig 类似于 ServletConfig
*可以在web.xml文件中配置当前Filter 的初始化参数.配置方式也和Servlet类似.
<!-- 注册Filter --> <filter> <filter-name>firstFilter</filter-name> <filter-class>com.java.testFilter.MyFilter</filter-class> <init-param> <param-name>name</param-name> <param-value>java</param-value> </init-param> </filter>
*与开发Servlet不同的是,Filter 接口并没有相应的实现类可以继承,要开发过滤器只能实现接口
同一个web.xml文件中可以为同一个Filter设置多个映射
example:
一个登陆界面
<font color="red">${message }</font> <br><br> <form action="${pageContext.request.contextPath }/hello.jsp" method="post"> UserName:<input type="text" name="username" value="${param.username }"> <br> Password :<input type="password" name="password"> <br> <input type="submit" value="submit"> </form>
两个过滤器
package com.java.testFilter; import java.io.IOException; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * 拦截/hello.jsp,如果username 不是Tom 则转发到login.jsp,否则放行 */ public class UserNameFilter implements Filter { public UserNameFilter() { } public void destroy() { } public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { String initUser = filterConfig.getInitParameter("username"); String username = request.getParameter("username"); if(!initUser.equals(username)){ request.setAttribute("message", "用户名错误!"); request.getRequestDispatcher("/login.jsp").forward(request, response); return; } chain.doFilter(request, response); } private FilterConfig filterConfig; public void init(FilterConfig fConfig) throws ServletException { this.filterConfig = fConfig; } }
package com.java.testFilter; import java.io.IOException; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; /** * 若密码不是1234,则把请求给login.jsp,否则给目标页面 */ public class PasswordFilter implements Filter { public PasswordFilter() { // TODO Auto-generated constructor stub } public void destroy() { // TODO Auto-generated method stub } public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { ServletContext servletContext = filterConfig.getServletContext(); String initPass = servletContext.getInitParameter("password"); String password = request.getParameter("password"); if(!initPass.equals(password)){ request.setAttribute("message", "密码错误!"); request.getRequestDispatcher("/login.jsp").forward(request, response); return; } chain.doFilter(request, response); } /** * @see Filter#init(FilterConfig) */ private FilterConfig filterConfig; public void init(FilterConfig fConfig) throws ServletException { this.filterConfig = fConfig; } }
web.xml配置
<context-param> <param-name>password</param-name> <param-value>1234</param-value> </context-param> <filter> <display-name>UserNameFilter</display-name> <filter-name>UserNameFilter</filter-name> <filter-class>com.java.testFilter.UserNameFilter</filter-class> <init-param> <param-name>username</param-name> <param-value>Tom</param-value> </init-param> </filter> <filter-mapping> <filter-name>UserNameFilter</filter-name> <url-pattern>/hello.jsp</url-pattern> </filter-mapping> <filter> <display-name>PasswordFilter</display-name> <filter-name>PasswordFilter</filter-name> <filter-class>com.java.testFilter.PasswordFilter</filter-class> </filter> <filter-mapping> <filter-name>PasswordFilter</filter-name> <url-pattern>/hello.jsp</url-pattern> </filter-mapping> <servlet> <description></description> <display-name>TestServlet2</display-name> <servlet-name>TestServlet2</servlet-name> <servlet-class>com.java.testFilter.TestServlet2</servlet-class> </servlet> <servlet-mapping> <servlet-name>TestServlet2</servlet-name> <url-pattern>/TestServlet2</url-pattern> </servlet-mapping>
hello.jsp
<h4>Hello Page</h4> Hello:${param.username }
写一个HttpFilter类 实现Filter
1 package com.java.testFilter; 2 3 import java.io.IOException; 4 5 import javax.servlet.Filter; 6 import javax.servlet.FilterChain; 7 import javax.servlet.FilterConfig; 8 import javax.servlet.ServletException; 9 import javax.servlet.ServletRequest; 10 import javax.servlet.ServletResponse; 11 import javax.servlet.http.HttpServletRequest; 12 import javax.servlet.http.HttpServletResponse; 13 14 public abstract class HttpFilter implements Filter{ 15 16 @Override 17 public void destroy() { 18 } 19 20 @Override 21 public void doFilter(ServletRequest arg0, ServletResponse arg1, 22 FilterChain filterChain) throws IOException, ServletException { 23 HttpServletRequest request = (HttpServletRequest)arg0; 24 HttpServletResponse response = (HttpServletResponse)arg1; 25 doFilter(request,response,filterChain); 26 } 27 28 public abstract void doFilter(HttpServletRequest request,HttpServletResponse response, 29 FilterChain filterChain); 30 31 private FilterConfig filterConfig; 32 @Override 33 public void init(FilterConfig arg0) throws ServletException { 34 this.filterConfig = arg0; 35 init(); 36 } 37 38 protected void init() { 39 } 40 }
下次写Filter可以直接继承HttpFiter
** 多个Filter 的代码执行顺序 理解Filter链
前边的例子 login.jsp --> hello.jsp 通过两个过滤器 UserNameFilter.java , PasswordFilter.java
在过滤器前后分别加上标记
1 public class UserNameFilter implements Filter { 2 3 public UserNameFilter() { 4 } 5 6 public void destroy() { 7 } 8 9 public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { 10 String initUser = filterConfig.getInitParameter("username"); 11 String username = request.getParameter("username"); 12 if(!initUser.equals(username)){ 13 request.setAttribute("message", "用户名错误!"); 14 request.getRequestDispatcher("/login.jsp").forward(request, response); 15 return; 16 } 17 System.out.println("1..."); 18 chain.doFilter(request, response); 19 System.out.println("2..."); 20 } 21 22 private FilterConfig filterConfig; 23 public void init(FilterConfig fConfig) throws ServletException { 24 this.filterConfig = fConfig; 25 } 26 27 }
1 public class PasswordFilter implements Filter { 2 3 public PasswordFilter() { 4 // TODO Auto-generated constructor stub 5 } 6 7 public void destroy() { 8 // TODO Auto-generated method stub 9 } 10 11 public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { 12 ServletContext servletContext = filterConfig.getServletContext(); 13 String initPass = servletContext.getInitParameter("password"); 14 String password = request.getParameter("password"); 15 if(!initPass.equals(password)){ 16 request.setAttribute("message", "密码错误!"); 17 request.getRequestDispatcher("/login.jsp").forward(request, response); 18 return; 19 } 20 System.out.println("3..."); 21 chain.doFilter(request, response); 22 System.out.println("4..."); 23 } 24 25 /** 26 * @see Filter#init(FilterConfig) 27 */ 28 private FilterConfig filterConfig; 29 public void init(FilterConfig fConfig) throws ServletException { 30 this.filterConfig = fConfig; 31 } 32 33 }
hello.jsp 页面
1 <%@ page language="java" contentType="text/html; charset=UTF-8" 2 pageEncoding="UTF-8"%> 3 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> 4 <html> 5 <head> 6 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> 7 <title>Insert title here</title> 8 </head> 9 <body> 10 11 <h4>Hello Page</h4> 12 Hello:${param.username } 13 <% 14 System.out.println("5..."); 15 %> 16 </body> 17 </html>
执行后控制台输出为
1... 3... 5... 4... 2...
chain.doFilter()是放行当前过滤器,交给下个过滤器处理
**<dispatcher>节点 指定过滤器所拦截资源被Servlet容器调用的方式
可以是 REQUEST(直接请求的方式,包括GET或POST),INCLUDE,FORWARD(请求转发的方式),ERROR
<filter-mapping>
<dispatcher>
</filter-mapping>
<a href="test.jsp">Test</a>
public class MyFilter implements Filter { @Override public void destroy() { System.out.println("destroy..."); } @Override public void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain arg2) throws IOException, ServletException { System.out.println("doFilter..."); } @Override public void init(FilterConfig arg0) throws ServletException { System.out.println("init..."); } }
<filter> <filter-name>firstFilter</filter-name> <filter-class>com.java.testFilter.MyFilter</filter-class> <init-param> <param-name>name</param-name> <param-value>java</param-value> </init-param> </filter> <filter-mapping> <filter-name>firstFilter</filter-name> <url-pattern>/test.jsp</url-pattern> </filter-mapping>
在<filter-mapping>中如果不配置<dispatcher>,默认是请求的方式,即get或post的方式,直接请求
若修改页面为
index.jsp
<a href="dispatcher.jsp">Test</a>
dispatcher.jsp
<jsp:forward page="test.jsp"></jsp:forward>
则拦截器会不起作用,如果需要拦截转发的方式,需要配置
<filter-mapping>
<filter-name>firstFilter</filter-name>
<url-pattern>/test.jsp</url-pattern>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>
配置<dispatcher>FORWARD</dispatcher>后,默认的请求方式会无法拦截,若需同时起作用需啊哟两个同时配置
<filter-mapping>
<filter-name>firstFilter</filter-name>
<url-pattern>/test.jsp</url-pattern>
<dispatcher>FORWARD</dispatcher>
<dispatcher>REQUEST</dispatcher>
</filter-mapping>
配置<dispatcher>INCLUDE</dispatcher>道理相同
<dispatcher>ERROR</dispatcher>:
<error-page> <exception-type>java.lang.ArithmeticException</exception-type> <location>/test.jsp</location> </error-page>
此时需要在过滤器中配置
<filter-mapping> <filter-name>firstFilter</filter-name> <url-pattern>/test.jsp</url-pattern> <dispatcher>FORWARD</dispatcher> <dispatcher>REQUEST</dispatcher> <dispatcher>ERROR</dispatcher> </filter-mapping>
才能正确跳转到定义的错误页面
应用1:禁用浏览器缓存的过滤器
有3个HTTP响应头字段都可以禁止浏览器缓存当前页面,他们在Servlet中的示例代码如下:
response.setDateHeader("Expires", -1);
response.setHeader("Cache-Control", "no-cache");
response.setHeader("Pragma", "no-cache");
并不是所有浏览器都能完全支持上面的三个响应头,因此最好是同时使用上面的三个响应头
cache目录中有
a.html , b.html , a.jpg, b.jpg
a.html
<a href="b.html">To BBB Page</a>
<img alt="" src="b.jpg">
b.html
<a href="a.html">To AAA Page</a>
在ie中运行a.html后,修改src="a.jpg",不刷新浏览器再次点击跳转链接时,由于缓存原因,显示的图片
没有刷新过来,在配置 禁用浏览器缓存后可以 可以禁止缓存
public class NoCacheFilter extends HttpFilter {
@Override
public void doFilter(HttpServletRequest request,
HttpServletResponse response, FilterChain filterChain) throws IOException, ServletException {
response.setDateHeader("Expires", -1);
response.setHeader("Cache-Control", "no-cache");
response.setHeader("Pragma", "no-cache");
filterChain.doFilter(request, response);
}
}
其中HttpFilter是自己实现Filter的一个抽象类,为了简便直接使用,在之前已经说过。
<filter> <filter-name>noCacheFilter</filter-name> <filter-class>com.java.testNoCache.NoCacheFilter</filter-class> </filter> <filter-mapping> <filter-name>noCacheFilter</filter-name> <url-pattern>/cache/*</url-pattern> </filter-mapping>
典型应用2:自己写一个字符编码过滤器(虽然Spring已经提供了),为了更好的理解
两个jsp页面跳转时,如果没有字符编码的处理,传递中文会出现乱码问题
login.jsp
<form action="hello.jsp" method="post">
Hello:<input type="text" name="username">
<input type="submit" value="Submit">
</form>
hello.jsp
Hello:${param.username }
输入中文时会出现乱码:
Hello:è¿æ»¤å¨
------------------------------
第1种做法:之前的做法是在目标页面写一个字符编码处理
<%
request.setCharacterEncoding("UTF-8");
%>
Hello:${param.username }
如果是通过Servlet处理,则这句可以再Servlet里写,若一个工程有100个页面,则这种办法行不通
第二种做法通过过滤器处理:
package com.java.encoding;
import java.io.IOException;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.java.testFilter.HttpFilter;
public class EncodingFilter extends HttpFilter {
private String encoding;
@Override
protected void init() {
encoding = getFilterConfig().getServletContext().getInitParameter("encoding");
}
@Override
public void doFilter(HttpServletRequest request,
HttpServletResponse response, FilterChain filterChain)
throws IOException, ServletException {
request.setCharacterEncoding(encoding);
filterChain.doFilter(request, response);
}
}
这里依旧使用之前写的HttpFilter,并且这里从web.xml中获取web应用的初始化参数
web.xml中过滤器的配置
<context-param> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </context-param> <filter> <filter-name>encodingFilter</filter-name> <filter-class>com.java.encoding.EncodingFilter</filter-class> </filter> <filter-mapping> <filter-name>encodingFilter</filter-name> <url-pattern>/encoding/*</url-pattern> </filter-mapping>
如果使用Spring,可以直接使用Spring提供的Filter
典型应用3:检查用户是否登录的过滤器
需求:系统中的某些页面登录后才能访问,用户请求这些页面时要检查session中有无该用户信息,但在所有的页面上添加session判断太麻烦.
解决方案:写一个检测用户是否登录的过滤器,如果用户未登录,则重定向到指定的登录页面
要求:需检查在Session中保存的关键字、如果用于未登录需重定向到指定的页面、不做检查的URL列表(URL不包括ContextPath)都要采取可配置的方式;
有些页面只用用户登录后才能访问,有些页面用户没有登录不能访问
不用过滤器最直接的做法:
不需要登录可以访问的页面
a.jsp
<h4>AAA Page</h4> <br> <a href="list.jsp">List Page</a>
需要登录才能访问的页面:(不使用过滤器,所有的目标页面都要做出session的判断)
b.jsp
<%
//检查用户是否登录,若没有登录则重定向到login.jsp
Object user = session.getAttribute("user");
if(null == user){
response.sendRedirect("login.jsp");
}
%>
<h4>BBB Page</h4>
<br>
<a href="list.jsp">List Page</a>
登录页面(写的简单) login.jsp
<form action="doLogin.jsp" method="post">
username:<input type="text" name="username">
<input type="submit" value="submit">
</form>
需要将用户信息写入到sesison的处理,简单用jsp代替servlet, doLogin.jsp
<%
//1.获取用户登录信息
String username = request.getParameter("username");
//2.将用户登录信息写入session
session.setAttribute("user", username);
//3.重定向到list.jsp
response.sendRedirect("list.jsp");
%>
用户访问的首页 list.jsp
<a href="a.jsp">AAA</a> <br><br> <a href="b.jsp">BBB</a> <br><br> <a href="c.jsp">CCC</a> <br><br> <a href="d.jsp">DDD</a> <br><br> <a href="e.jsp">EEE</a> <br><br>
使用过滤器
修改b.jsp
<%--
//检查用户是否登录,若没有登录则重定向到login.jsp
Object user = session.getAttribute("user");
if(null == user){
response.sendRedirect("login.jsp");
}
--%>
<h4>BBB Page</h4>
<br>
<a href="list.jsp">List Page</a>
LoginFilter.java
package com.java.login;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import javax.servlet.FilterChain;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.java.testFilter.HttpFilter;
public class LoginFilter extends HttpFilter {
private String sessionKey;
private String redirectURL;
private String uncheckURLs;
@Override
protected void init() {
ServletContext servletContext = getFilterConfig().getServletContext();
sessionKey = servletContext.getInitParameter("sessionKey");
redirectURL = servletContext.getInitParameter("redirectURL");
uncheckURLs = servletContext.getInitParameter("uncheckURLs");
}
@Override
public void doFilter(HttpServletRequest request,
HttpServletResponse response, FilterChain filterChain)
throws IOException, ServletException {
String requestURL = request.getRequestURL().toString();
String requestURI = request.getRequestURI();
String servletPath1 = request.getServletPath();
System.out.println(requestURL);
System.out.println(requestURI);
System.out.println(servletPath1);
/*http://localhost:8080/testFilter/login/a.jsp
/testFilter/login/a.jsp
/login/a.jsp*/
//1.获取请求的ServletPath
String servletPath = request.getServletPath();
//2.判断uncheckURLs里是否包含ServletPath,若包含,则直接放行,方法结束
List<String> urls = Arrays.asList(uncheckURLs.split(","));
if(urls.contains(servletPath)){
filterChain.doFilter(request, response);
return;
}
//3.从session中获取sessionKey对应的值,若不存在,则重定向到redirectURL
Object user = request.getSession().getAttribute(sessionKey);
if(null == user){
response.sendRedirect(request.getContextPath()+redirectURL);
return;
}
//4.若存在,放行
filterChain.doFilter(request, response);
}
}
web.xml
<!-- 将参数变为可配置的 --> <!-- 存储session的关键字 --> <context-param> <param-name>sessionKey</param-name> <param-value>SESSIONKEY</param-value> </context-param> <!-- 如果没有登录,则重定向到的页面 --> <context-param> <param-name>redirectURL</param-name> <param-value>/login/login.jsp</param-value> </context-param> <!-- 不需要检查的url--> <context-param> <param-name>uncheckURLs</param-name> <param-value>/login/a.jsp,/login/list.jsp,/login/login.jsp,/login/doLogin.jsp</param-value> </context-param> <!-- 配置检查用户登录的过滤器 --> <filter> <filter-name>loginFilter</filter-name> <filter-class>com.java.login.LoginFilter</filter-class> </filter> <filter-mapping> <filter-name>loginFilter</filter-name> <url-pattern>/login/*</url-pattern> </filter-mapping>
修改doLogin.jsp
<%
//1.获取用户登录信息
String username = request.getParameter("username");
//3.若登录信息完整重定向到list.jsp
if(null != username && !username.trim().equals("")){
//2.将用户登录信息写入session
session.setAttribute(application.getInitParameter("sessionKey"), username);
response.sendRedirect("list.jsp");
}else{
response.sendRedirect("login.jsp");
}
%>
通过测试
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Insert title here</title> </head> <body> <center> <form action="authorityServlet?method=getAuthority" method="post"> name:<input type="text" name="userName"/> <input type="submit" value="Submit"/> </form> </center> <br><br> <center> <c:if test="${requestScope.user.userName != null}"> ${requestScope.user.userName }的权限是: <br><br> <form action="authorityServlet?method=updateAuthority" method="post"> <input type="hidden" name="userName" value="${requestScope.user.userName }"/> <c:forEach items="${authorities}" var="auth"> <c:set var="flag" value="false"></c:set> <c:forEach items="${user.authorities }" var="au"> <c:if test="${au.url == auth.url }"> <c:set var="flag" value="true"></c:set> </c:if> </c:forEach> <c:if test="${flag == true }"> <input type="checkbox" name="authorities" value="${auth.url }" checked="checked"/>${auth.authorityName }<br><br> </c:if> <c:if test="${flag == false }"> <input type="checkbox" name="authorities" value="${auth.url }"/>${auth.authorityName }<br><br> </c:if> </c:forEach> <input type="submit" value="Update"/> </form> </c:if> </center> </body> </html>
AuthorityServlet.java
package com.java.authority.servlet; import java.io.IOException; import java.lang.reflect.Method; import java.util.List; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import com.java.authority.dao.AuthorityDao; import com.java.authority.entity.Authority; import com.java.authority.entity.User; public class AuthorityServlet extends HttpServlet { private static final long serialVersionUID = 1L; AuthorityDao authorityDao = new AuthorityDao(); protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String methodName = request.getParameter("method"); try { Method method = getClass().getMethod(methodName, HttpServletRequest.class,HttpServletResponse.class); method.invoke(this, request,response); } catch (Exception e) { e.printStackTrace(); } } public void getAuthority(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String userName = request.getParameter("userName"); User user = authorityDao.getUser(userName); request.setAttribute("user", user); List<Authority> authorities = authorityDao.getAuthority(); request.setAttribute("authorities", authorities); request.getRequestDispatcher("/authority/authority-manager.jsp").forward(request, response); } public void updateAuthority(HttpServletRequest request, HttpServletResponse response) throws IOException{ String userName = request.getParameter("userName"); String [] urls = request.getParameterValues("authorities"); List<Authority> auths = authorityDao.getAuthorities(urls); authorityDao.update(userName, auths); response.sendRedirect(request.getContextPath()+"/authority/authority-manager.jsp"); } }
package com.java.authority.entity; import java.util.List; public class User { private String userName; private List<Authority> authorities; public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } public List<Authority> getAuthorities() { return authorities; } public void setAuthorities(List<Authority> authorities) { this.authorities = authorities; } public User(String userName, List<Authority> authorities) { super(); this.userName = userName; this.authorities = authorities; } public User() { super(); } }
Authority.java
package com.java.authority.entity; public class Authority { private String authorityName; private String url; public String getAuthorityName() { return authorityName; } public void setAuthorityName(String authorityName) { this.authorityName = authorityName; } public String getUrl() { return url; } public void setUrl(String url) { this.url = url; } public Authority(String authorityName, String url) { super(); this.authorityName = authorityName; this.url = url; } public Authority() { super(); } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((url == null) ? 0 : url.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; Authority other = (Authority) obj; if (url == null) { if (other.url != null) return false; } else if (!url.equals(other.url)) return false; return true; } }
package com.java.authority.dao; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import com.java.authority.entity.Authority; import com.java.authority.entity.User; public class AuthorityDao { private static Map<String,User> users; private static List<Authority> authorities; static{ users = new HashMap<>(); authorities = new ArrayList<>(); authorities.add(new Authority("article-1", "/authority/article-1.jsp")); authorities.add(new Authority("article-2", "/authority/article-2.jsp")); authorities.add(new Authority("article-3", "/authority/article-3.jsp")); authorities.add(new Authority("article-4", "/authority/article-4.jsp")); users.put("AAA", new User("AAA", authorities.subList(0, 2))); users.put("BBB", new User("BBB", authorities.subList(2, 4))); } public List<Authority> getAuthority(){ return authorities; } public User getUser(String userName){ return users.get(userName); } public void update(String userName,List<Authority> authorities){ users.get(userName).setAuthorities(authorities); } public List<Authority> getAuthorities(String[] urls) { List<Authority> authorities2 = new ArrayList<>(); for(Authority authority : authorities){ for(String url:urls){ if(authority.getUrl().equals(url)){ authorities2.add(authority); } } } return authorities2; } }
servlet 的配置
<servlet> <description></description> <display-name>AuthorityServlet</display-name> <servlet-name>AuthorityServlet</servlet-name> <servlet-class>com.java.authority.servlet.AuthorityServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>AuthorityServlet</servlet-name> <url-pattern>/authority/authorityServlet</url-pattern> </servlet-mapping>
以上是权限管理,以下是权限的过滤结合权限管理
文件结构目录:
package com.java.authority.servlet; import java.io.IOException; import java.lang.reflect.Method; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import com.java.authority.dao.AuthorityDao; import com.java.authority.entity.User; public class LoginServlet extends HttpServlet { private static final long serialVersionUID = 1L; private AuthorityDao authorityDao = new AuthorityDao(); protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doPost(request, response); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String methodName = request.getParameter("method"); try { Method method = getClass().getMethod(methodName, HttpServletRequest.class,HttpServletResponse.class); method.invoke(this,request, response); } catch (Exception e) { e.printStackTrace(); } } public void login(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String username = request.getParameter("username"); User user = authorityDao.getUser(username); request.getSession().setAttribute("user", user); //重定向到articles.jsp response.sendRedirect(request.getContextPath()+"/authority/articles.jsp"); } public void logout(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.getSession().invalidate(); response.sendRedirect(request.getContextPath()+"/authority/login.jsp"); } }
在Servlet之前会有一个过滤器
AuthorityFilter.java
package com.java.authority; import java.io.IOException; import java.util.Arrays; import java.util.List; import javax.servlet.FilterChain; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import com.java.authority.entity.Authority; import com.java.authority.entity.User; import com.java.testFilter.HttpFilter; public class AuthorityFilter extends HttpFilter { @Override public void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws IOException, ServletException { String servletPath = request.getServletPath(); List<String> uncheckURL = Arrays.asList("/authority/login.jsp", "/authority/logout.jsp", "/authority/articles.jsp", "/authority/authority-manager.jsp", "/authority/403.jsp"); // 检查不过滤的页面 if (uncheckURL.contains(servletPath)) { filterChain.doFilter(request, response); return; } User user = (User) request.getSession().getAttribute("user"); //若用户没有登录,重定向到login.jsp if (user == null) { response.sendRedirect(request.getContextPath() + "/authority/login.jsp"); return; } //获取用户拥有的 权限 List<Authority> authorities = user.getAuthorities(); //检查用户是否有请求servletPath的权限,遍历以外的方法 Authority authority = new Authority(null, servletPath); if(authorities.contains(authority)){ filterChain.doFilter(request, response); return; } //没有权限 response.sendRedirect(request.getContextPath()+"/authority/403.jsp"); return; } }
web.xml配置
<filter> <display-name>AuthorityFilter</display-name> <filter-name>AuthorityFilter</filter-name> <filter-class>com.java.authority.AuthorityFilter</filter-class> </filter> <filter-mapping> <filter-name>AuthorityFilter</filter-name> <url-pattern>*.jsp</url-pattern> </filter-mapping>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Insert title here</title> </head> <body> <h4>Ariticle-1 Page</h4> <br> <a href="articles.jsp">返回</a> </body> </html>
403.jsp页面
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Insert title here</title> </head> <body> <h4>您没有权限访问,</h4> 请<a href="${pageContext.request.contextPath }/authority/403.jsp">返回</a> </body> </html>
典型应用5:论坛中关键字的拦截及过滤(例如 fuck... 等)