JSP+Servlet实现的一个图片分享网站6_二重权限鉴定

文章目录

前言

对于网站来说,用户能否访问一个页面取决于TA拥有的权限,比如收藏等页面,就需要用户已经登陆,再比如删除或修改上传的图片,一定是只能删除自己上传的,不能是别人的,等等。前面一种情况,我最开始是在每个需要登陆的页面都加上一段验证代码,不断地复制粘贴,修改起来也很麻烦,直到我学了Filter,然后把项目重构了一下,从整个web项目的层面进行了一次过滤验证。至于后面一种情况,我就根本没有验证,虽然说仅仅通过页面上的元素来操作不会出现这种情况,但是如果是真实的网站,有些恶意用户会直接通过url来访问后端进行一些数据库的操作,就算是采用POST方法,在审查元素的情况下,大家都可以随机更改一部分页面的代码,注入恶意JS,导致一些不应该的操作,比如将穿给后端的uid改成别人的uid从而删除别人的数据。因此即使通过了一层鉴定,在服务器端的方法层面也应该再进行一次权限鉴定。

实现

1. 项目层面
利用Filter接口对访问进行过滤,可以有多个过滤器,即filterChain,按照在配置文件中的顺序依次进行过滤处理,直到最后到达url对应的文件。

  • web.xml文件中的配置
<filter>
    <filter-name>loginFilter</filter-name>
    <filter-class>filter.LoginFilter</filter-class>
</filter>
<!--需要登陆的页面的url-->
<filter-mapping>
    <filter-name>loginFilter</filter-name>
    <url-pattern>/collection.jsp</url-pattern>
</filter-mapping>
  • 实现HttpServlet,用来给其它具体的filter继承,就不用每次都写init的destroy这些方法了
package filter;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public abstract class HttpFilter implements Filter {
    /**
     * 用于保存 FilterConfig 对象.
     */
    private FilterConfig filterConfig;

      @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        this.filterConfig = filterConfig;
        init();
    }

    /**
     * 供子类继承的初始化方法. 可以通过 getFilterConfig() 获取 FilterConfig 对象.
     */
    protected void init() {}

    /**
     * 直接返回 init(ServletConfig) 的 FilterConfig 对象
     */
    public FilterConfig getFilterConfig() {
        return filterConfig;
    }

    @overrride
    public void doFilter(ServletRequest req, ServletResponse resp,
                         FilterChain chain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) resp;

        doFilter(request, response, chain);
    }

    /**
     * 抽象方法, 为 Http 请求定制. 必须实现的方法.
     * @param request
     * @param response
     * @param filterChain
     * @throws IOException
     * @throws ServletException
     */
    public abstract void doFilter(HttpServletRequest request, HttpServletResponse response,
                                  FilterChain filterChain) throws IOException, ServletException;

    /**
     * 空的 destroy 方法。
     */
    @Override
    public void destroy() {}
}
  • LoginFilter
package filter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;

public class LoginFilter extends HttpFilter {
    @Override
    public void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws IOException, ServletException {
        HttpSession session = request.getSession();
        String toPath = request.getRequestURI();
        if(session.getAttribute("userDetails") == null){
            System.out.println("没有到"+toPath+"的权限,要先登录");
            session.setAttribute("toPath",toPath);
            response.sendRedirect(request.getContextPath()+"/login.jsp");
        }
        else {
            filterChain.doFilter(request,response);
        }
    }
}

2. 方法层面
① 所需参数
每个servlet都需要一定的参数,若直接通过url访问,可能会没有所需参数,导致异常,所以在每个servlet的方法开头都要先保证参数的完整,若不完整则直接跳转并返回。
比如注册的servlet,

	String username = request.getParameter("username");
        String password = request.getParameter("md5Password");
        String email = request.getParameter("email");        
        if(!Require.requireStringNotEmpty(username,password,email)){
            response.sendRedirect(request.getContextPath()+"/register.jsp");
            return;
        }
public static boolean requireStringNotEmpty(String ... strings){
    for(String string :strings){
        if(string == null || string.length() == 0) return false;
    }
    return true;
}

这个方法的实现采用了动态参数
② 身份验证
刚开始我都是从前端传uid给后端来决定哪一名用户在操作,但是这很不安全,所以我就在后端验证传过来的uid是否是session中储存的uid即当前登录的uid,但是写完之后我才意识到,其实更好的办法是直接在后端通过session获取uid,不要从前端传给后端,因为其实前端的uid在正常情况下就是通过session来获取的,在非正常情况下更是没有意义的。比如说,收藏某张图片,如果从后端获取uid,就根本不用验证,只有在少数情况下,比如删除某张上传的图片,还需要判断当前uid是否是该图片的作者。
总而言之,在后端开发中,需要的信息就是能在后端获取就不要靠前端传回来,因为前端的数据是可能被修改的
当然,在前后端分离的前端开发中,能从前端获取的数据,就不要再请求一次后端,这样效率很低,比如vue+springboot项目中,登录过后就把用户的一些信息存在全局状态中。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值