Java Filter过滤器------对未登录用户访问地址的控制

一、什么是Filter过滤器

  • 顾名思义,过滤器是处于客户端与服务器资源文件之间的一道过滤网,在访问资源文件之前,通过一系列的过滤器对请求进行修改、判断等,把不符合规则的请求在中途拦截或修改。也可以对响应进行过滤,拦截或修改响应。它是对web服务器管理的所有web资源,例: 静态图片文件、静态html文件、Servlet、Jsp等进行拦截,从而,实现一些特殊的功能。filter主要是用来对用户请求进行预处理,也能够对HttpServletResponse进行后处理。

  • 定义一个过滤器需要实现(implement)Filter接口,这里实现的是javax.servlet.Filter。

    过滤器是一个程序,它先于与之相关的servlet或JSP页面运行在服务器上。过滤器可附加到一个或多个servlet或JSP页面上,并且可以检查进入这些资源的请求信息。在这之后,过滤器可以作如下的选择:
    ①以常规的方式调用资源(即,调用servlet或JSP页面)。
    ②利用修改过的请求信息调用资源。
    ③调用资源,但在发送响应到客户机前对其进行修改。
    ④阻止该资源调用,代之以转到其他的资源,返回一个特定的状态代码或生成替换输出

  • 举个例子,甲的心上人是乙,每天坚持给乙写几封信,但是每次乙的妈妈都会先取到信件,将其中爱慕之情的信件扣掉,只留下有关学习交流的信件再交送给乙,而乙每次的回信也是被如此操作。也就是说Filter过滤器会过滤掉来自客户端的部分请求后再传给服务端,而服务端拿到被过滤的请求后再做出响应。

在这里插入图片描述

二、 为什么要用Filter过滤器

场景: 防止用户未登录就随意访问了网站内部

在实际场景中,我们在开发完成后,为了保证网站的安全性,只有登录后才能访问某些网站内部的页面,如果不进行一层登录的过滤,那么任何人都能通过URL来随意的访问到网站内部的页面,这是不合理的。例如此刻的我网站内部一个页面URL是

http://localhost:8080/sis/public/page/main.html

但是我想让只有登录过的人才能合法的访问到这个页面,此时使用Filter过滤器就能解决这个问题。实现逻辑是通过Session信息判断是否登录了,如果未登录就重定向到登录的首页。

其他:通过对JSP、Servlet、静态图片文件、或静态HTML文件进行拦截,以实现URL级别的权限控制、过虑敏感词汇、压缩响应信息等一些高级功能。

三、如何使用

1. 重写过滤器的三个方法
public class QuickFilter  implements Filter{
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        System.out.println("qucikFilterRunning");
        //放行请求
        chain.doFilter(request, response);
    }
    @Override
    public void destroy() {
    }
}
  • init(FilterConfig filterConfig)
    代表filter对象初始化方法,filter对象创建时执行

  • doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
    代表filter执行过滤的核心方法,业务逻辑所在。如果某资源在已经被配置到这个filter进行过滤的话,那么每次访问这个资源都会执行doFilter方法,

    ServletRequest/ServletResponse:doFile中的request和response需要强转为HttpServletRequest和HttpServletResponse的类型,再根据需求进行修改请求信息或者设置重定向等操作。
    FilterChain:过滤器链对象,通过该对象的doFilter方法可以放行该请求

  • destory()
    代表是filter销毁方法,当filter对象销毁时执行该方法

三个方法都是可以表现 Filter 生命周期的方法,其中 init() 方法在 Web 应用程序加载时会被调用,destroy() 方法在 Web 应用程序卸载(或关闭)时被调用这两个方法都只会被调用一次而 doFilter() 方法会被调用多次(只要客户端有请求时就会被调用),Filter 所有的工作集中在 doFilter() 方法中。

2.使用案例

防止未登录用户访问到网站内部页面,未登录的情况下访问,会进行一个重定向跳转到登录页面。而请求后端非登录接口,不允许访问,一律设置为401

 @WebFilter("/*")//模糊匹配 所以的路径都会过滤 
public class LoginFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }
    @Override
/**  只要是匹配到了路径,①都先执行doFilter ,②再去执行Servlet*/
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest req = (HttpServletRequest) servletRequest;
        HttpServletResponse res = (HttpServletResponse) servletResponse;
        String uri = req.getServletPath();
// 校验:①前端html拦截    ②非前端的就是后台接口,除了登录接口之外
        HttpSession session = req.getSession(false);//没有session时候 返回null
        if (session == null) { //没有登录
            //首页重定向到登录页面
            if (  "/public/page/main.html".equals(uri) ) {
                res.setContentType("text/html;charset= UTF-8");
//开始重定向
                String schema = req.getScheme();//HTTP
                String host = req.getServerName();//服务器ip
                int port = req.getServerPort();//端口号
                String ctx = req.getContextPath();//项目部署路径 应用上下文 sis
                // 错误写法①res.sendRedirect("/public/page/main.html");②res.sendRedirect("public/page/main.html");
                String basePath = schema+"://"+host+":"+port+ctx;
                res.sendRedirect(basePath+"/public/index.html");//正确写法
                return;
//请求后端非登录接口, 未登录不允许访间的请求,一般返回401状态码
            }else if ( (!uri.startsWith("/public/")
                    && !uri.startsWith("/static/") && !"/user/login".equals(uri))) {
                res.setContentType("application/json");
                PrintWriter pw = res.getWriter();
                Response r = new Response();
                r.setCode("ERR401");
                r.setMessage("不允许访问");
                res.setStatus(401);//设置响应的状态码
                pw.println(JSONUtil.write(r)); //响应打到前端
                pw.flush();
                return;
            }
        }
        filterChain.doFilter( servletRequest,servletResponse);
    }
    @Override
    public void destroy() {
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值