项目源码:https://github.com/tsouhsiaopenk/sys-dorm-sys/
一、项目描述
学生宿舍管理是一个基于http协议开发的一个web项目。目的在于开发出一个学生住宿信息管理的系统。
二、项目功能
用户注册、登陆、学生住宿管理是项目的核心功能。
通过该管理系统可以实现新增学生信息,删除、修改,以及给学生分配宿舍等功能。
三、项目要点/难点
访问控制
在URI中输入敏感资源,不用通过登录就可以直接访问显然是不合适的。
通过查资料,发现Java中有一个Filter接口,他可以实现过滤的功能,就是在Tomcat开始调用某个Servlet程序的时候,如果发现存在一个Filter过滤器对Servlet进行拦截,那么容器就不再直接调用Servlet中的service方法,而是调用Filter中的doFilter方法,再有doFilter方法决定是否去调用service方法。于是就在项目中引入了Filter接口,并在doFilter方法中加上了过滤条件,如果URI不满足要求就不让他去调用service方法,从而让他不能直接获取到敏感资源。
Filter 的基本工作原理
1、Filter 程序是一个实现了特殊接口的 Java 类,与 Servlet 类似,也是由 Servlet 容器进行调用和执行的。
2、当在 web.xml 注册了一个 Filter 来对某个 Servlet 程序进行拦截处理时,它可以决定是否将请求继续传递给 Servlet 程序,以及对请求和响应消息是否进行修改。
3、当 Servlet 容器开始调用某个 Servlet 程序时,如果发现已经注册了一个 Filter 程序来对该 Servlet 进行拦截,那么容器不再直接调用 Servlet 的 service 方法,而是调用 Filter 的 doFilter 方法,再由 doFilter 方法决定是否去激活 service 方法。
4、但在 Filter.doFilter 方法中不能直接调用 Servlet 的 service 方法,而是调用 FilterChain.doFilter 方法来激活目标 Servlet 的 service 方法,FilterChain 对象时通过 Filter.doFilter 方法的参数传递进来的。
5、只要在 Filter.doFilter 方法中调用 FilterChain.doFilter 方法的语句前后增加某些程序代码,这样就可以在 Servlet 进行响应前后实现某些特殊功能。
6、如果在 Filter.doFilter 方法中没有调用 FilterChain.doFilter 方法,则目标 Servlet 的 service 方法不会被执行,这样通过 Filter 就可以阻止某些非法的访问请求。
部分代码
package filter;
import model.Response;
import util.JSONUtil;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.io.PrintWriter;
// 过滤器,满足 url 请求的url匹配的路径规则,才会过滤(调用filter中的方法)
@WebFilter("/*")
public class LoginFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse res = (HttpServletResponse) response;
/**
* 页面的静态资源,后台服务
* 需要处理的敏感资源:
* 1.首页:/public/page/main.html没有登陆,重定向到登陆页面
* 2,后端的服务资源:除登陆接口/user/login以外,其他接口
*/
// 获取session信息
HttpSession session = req.getSession(false);// 没有session时返回null
if (session == null) {// 没有登陆
// 获取当前http请求的路径
String uri = req.getServletPath();
// 访问 /public/page/main.html 就让它重定向到登陆页面
if ("/public/page/main.html".equals(uri)) {
// http
String schema = req.getScheme();
// 服务器域名或者ip
String host = req.getServerName();
// 服务器端口号
int port = req.getServerPort();
// 项目部署名
String contextPath = req.getContextPath();
String basePath = schema + "://" + host + ":" + port + contextPath;
res.sendRedirect(basePath+"/public/index.html");
return;
} else if (!"/user/login".equals(uri) &&
!uri.startsWith("/public/") &&
!uri.startsWith("/static/")) {
// 访问了后台资源(除登陆等前端页面),返回错误信息(JSON格式)
req.setCharacterEncoding("UTF-8");
res.setCharacterEncoding("UTF-8");
res.setContentType("application/json"); //设置响应数据格式
Response r = new Response();
r.setCode("301"); // 不是响应的状态码,是响应的字段
r.setMessage("未授权的HTTP请求");
PrintWriter pw = res.getWriter();
pw.println(JSONUtil.write(r));
pw.flush();
return;
}
}
filterChain.doFilter(request, response);
}
@Override
public void destroy() {
}
}