struts下通过过滤器进行权限控制

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/ttff521xx/archive/2009/08/10/4430143.aspx

 

权限验证
(代码中部分删除,保留框架)
1.struts框架安全隐患
使用Struts框架时,权限通常控制在Action级(比如将权限验证放在Action的基类中,这样新的Action都继承于这个Action基类,所有Action就可以专注于业务逻辑,而不需要重复地进行权限控制了),这也符合MVC中的角色划分。然而,这会产生一个安全隐患。因为权限控制在Action中,所以,页面也就没有安全屏障了。一般的新增数据、更新数据不会有什么问题,因为这些数据必须通过HTML的Form提交到Struts的中心控制器,最终由相应的Action来处理,所以Action中就可以验证该用户的权限了。然而,对于一些不需要Action进行数据存取,或者有的页面没有严格按照MVC的角色划分而在页面中有获取数据的代码,那么这个页面就危险了。比如,显示一张通知页面,通常可以通过配置权限,使部分授权的用户才可以看到该级别的通知。这个通知页面是不需要从数据库中获取数据的。所以,可以不通过Action的调用来显示,而是直接敲入显示该通知的页面的链接就可以看到了。甚至不需要登录系统,不用管是否有查看该通知的权限!

比如下图中:

请求1:

http://.../XXX.do

是通过正常的途径访问的,需要经过权限验证。

而请求2:

http://.../XXX.jsp

则完全绕过了权限检查,任何人,不需要登录系统就可以访问到该信息了。

 

 

2.解决方案
解决的办法: 采用servlet过滤器

servlet过滤器是小型的web组件,它能够处理传入的请求和传出的响应。Filter 不是一个servlet,它不能产生一个response,它能够在一个request到达servlet之前预处理request,也可以在离开servlet时处理response。它具有高度的透明性,无需更改应用程序代码,就可以根据需要添加、修改或从应用程序中将它删除。

一个filter 包括:

1. 在servlet被调用之前截获;

2. 在servlet被调用之前检查servlet request;

3. 根据需要修改request头和request数据;

4. 根据需要修改response头和response数据;

5. 在servlet被调用之后截获.

你能够配置一个filter 到一个或多个servlet;单个servlet或servlet组能够被多个filter 使用。几个实用的filter包括:用户辨认filter,日志filter,审核filter,加密filter,符号filter,能改变xml内容的XSLT filter等。

一个客户化的过滤器要实现Filter接口的三个方法:init()、destroy()和doFilter()。

    1. init():在容器实例化过滤器时调用,该方法接受一个FilterConfig类型的对象做为输入。

    2. destroy():执行一些清理操作。

    3. doFilter():类似servlet的doPost()、doGet()方法,执行具体的过滤任务。

设置URL拦截器,对截获的请求url(两部分包括XXX.do和XXX.Jsp)做权限验证,具有该权限则继续下一步,否则跳转到相应页面显示用户没有权限。

 

 

3.具体步骤
统过滤器配置具体步骤:

1.     首先写一个权限过滤filter类,实现Filter接口
jsp权限过滤器permissionFilter

package dao;

import javax.servlet.Filter;

import javax.servlet.FilterConfig;

import javax.servlet.ServletException;

import javax.servlet.ServletRequest;

import javax.servlet.ServletResponse;

import javax.servlet.FilterChain;

import java.io.IOException;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpSession;

import javax.servlet.http.HttpServletResponse;

import po.login;

/*

 * jsp安全过滤器

 * filter:permissionFilter

 * */

public class permissionFilter implements Filter {

    // 1,doFilter方法的第一个参数为ServletRequest对象。

    // 此对象给过滤器提供了对进入的信息(包括表单数据、cookie和HTTP请求头)的完全访问。

    // 第二个参数为ServletResponse,通常在简单的过滤器中忽略此参数。

    // 最后一个参数为FilterChain,此参数用来调用servlet或JSP页。

    private FilterConfig filterConfig;

    private FilterChain chain;

    private HttpServletRequest request;

    private HttpServletResponse response;

    public void destroy() {

       this.filterConfig = null;

    }

    public void init(FilterConfig filterConfig) throws ServletException {

       this.filterConfig = filterConfig;

    }

    public void doFilter(ServletRequest servletRequest,

           ServletResponse servletResponse, FilterChain chain) {

       this.chain = chain;

       this.request = (HttpServletRequest) servletRequest;

       // 如果处理HTTP请求,并且需要访问诸如getHeader或getCookies等在ServletRequest中无法得到的方法,

       // 就要把此request对象构造成HttpServletRequest

       this.response = ((HttpServletResponse) servletResponse);

       // 获取当前页面文件名此处url为:/Gzlkh/login.jsp

       String url = request.getRequestURI();

       // 此处截取的url为:login.jsp

       url = url.substring(url.lastIndexOf("/") + 1, url.length());

       try {

           HttpSession session = request.getSession();

           // 获取网站访问根目录

           String accessPath = request.getContextPath();

           // 获取用户登录验证信息

           login st = (login) session.getAttribute("st");

           if (noFileUrl(url, request)) {

 // 不需要判断权限的请求如登录页面,则跳过

              chain.doFilter(request, response);// 继续执行请求

           } else if (st == null) {

              response.sendRedirect(accessPath + "/login.jsp");

// 未登录或超时,返回登陆页面

           } else {

              verifyUrl(url, st);// 判断当前user是否拥有访问此url的权限

           }

       } catch (Exception sx) {

           sx.printStackTrace();

       }

    }

    /**

     * 判断当前user是否拥有访问此url的权限

     * @param url

     * 当前请求的url

     * @param st

     * 当前登录用户信息

     * @throws IOException

     * @throws ServletException

     */

    private void verifyUrl(String url, login st) throws IOException,

           ServletException {

// 获取user拥有的所有资源串,此处全部提取出来,以方便以后项目扩展

//更好的方式是把此处的权限页面存储在数据库中,与角色建立关系,以后可以直接根据用户角色从

//数据库中取出

       String sturl = null;

// 拥有权限页1的jsp页面

String url1="";

// // 拥有权限页2的jsp页面

String url2 = ""

// // 拥有权限页3的jsp页面     

 String url3 = "";

       // 拥有权限页4的jsp页面     

 String url4 = "";

       // // 拥有权限页5的jsp页面      

String url5 = "";

       // 拥有权限页6的jsp页面

       String url6 = "";

       // 公共

       String url7 = "";

       sturl = url7;

       //以下判断用户是否有进入该页面的权限,有则加入

       if ("1".equals(st.getKhbfqx())) {

           sturl = sturl + "," + url1;

       }

       if ("1".equals(st.getRcgzqx())) {

           sturl = sturl + "," + url2;

       }

       if ("1".equals(st.getKhzbqx())) {

           sturl = sturl + "," + url3;

       }

       if ("1".equals(st.getKhjgqx())) {

           sturl = sturl + "," + url4;

       }

       if ("1".equals(st.getXtpzqx())) {

           sturl = sturl + "," + url6;

       }

       if ("1".equals(st.getYhglqx())) {

           sturl = sturl + "," + url5;

       }

       if (sturl.indexOf(url) >= 0) {

           //判断用户权限页面包含请求url里面的页面

           chain.doFilter(request, response);

       } else {

           //用户无权限跳转提示

           response.setContentType("text/html;charset=GBK");

           response.getWriter().println("<div style='margin: 100 auto;text-align: center;  "

           + "font: bold 18px 宋体;color: #0066CC;vertical-align: middle'> Sorry,您没有权限访问该资源!</div>");

       }

    }

    /**

     * 特殊页面判断

     * 是否需要判断权限,如客户端浏览、登录页面则不需要判断权限

     */

    protected boolean noFileUrl(String url, HttpServletRequest request) {

       //不需要权限验证的页面动作等

       String exclude = "xx.jsp";

        //判断请求页面是否是特殊页面

       if (exclude.indexOf(url) >= 0) {

           return true;

       }

       return false;

    }

}

Action权限过滤器permissiondoFilter

package dao;

 

import javax.servlet.Filter;

import javax.servlet.FilterConfig;

import javax.servlet.ServletException;

import javax.servlet.ServletRequest;

import javax.servlet.ServletResponse;

import javax.servlet.FilterChain;

import java.io.IOException;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpSession;

import javax.servlet.http.HttpServletResponse;

import po.login;

 

public class permissiondoFilter implements Filter {

    //1,doFilter方法的第一个参数为ServletRequest对象。

    //此对象给过滤器提供了对进入的信息(包括表单数据、cookie和HTTP请求头)的完全访问。

    //第二个参数为ServletResponse,通常在简单的过滤器中忽略此参数。

    //最后一个参数为FilterChain,此参数用来调用servlet或JSP页。

    private FilterConfig filterConfig;

    private FilterChain chain;

    private HttpServletRequest request;

    private HttpServletResponse response;

    public void destroy() {

        this.filterConfig = null;

    }

    public void init(FilterConfig filterConfig) throws ServletException {

        this.filterConfig = filterConfig;

    }

    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse,

           FilterChain chain) {

        this.chain = chain;

        this.request = (HttpServletRequest) servletRequest;

        //如果处理HTTP请求,并且需要访问诸如getHeader或getCookies等在ServletRequest中无法得到的方法,就要把此request对象构造成HttpServletRequest

        this.response = ((HttpServletResponse) servletResponse);

       // 获取当前页面文件名此处url为:/Gzlkh/login.jsp

       String url = request.getRequestURI();

       // 此处截取的url为:login.jsp

       url = url.substring(url.lastIndexOf("/") + 1, url.length());

       try {

 

           // 排除后台不作权限控制的页面名

           // 登陆页面无需验证文件 

            HttpSession session = request.getSession();

            // 获取网站访问根目录

           String accessPath = request.getContextPath();

            login st = (login) session.getAttribute("st");         

            if (noFileUrl(url, request)) {  // 不需要判断权限的请求如登录页面,则跳过

                chain.doFilter(request, response);

            } else if (st == null) {

            response.sendRedirect(accessPath + "/login.jsp");// 返回登陆页面(未登录或超时)

            } else {

              System.out.println(st.getRolename()+st.getUsername()+"-访问-"+url);

                verifyUrl(url, st);// 判断当前user是否拥有访问此url的权限

            }                    

       } catch (Exception sx) {

           sx.printStackTrace();

       }

    }

    /**

     * @param url

     *            当前请求的url

     * @param user

     *            当前登录用户

     * @throws IOException

     * @throws ServletException

     */

    private void verifyUrl(String url, login st)throws IOException, ServletException {

        // 获取user拥有的所有资源串

    String sturl=null;

    String url1="";

    String url2="";

    // 考核结果页面

    String url3="";

    // 用户管理页面

    String url4="";

    // 权重配置页面

    String url5="";

    // 个人密码修改公共

    String url6="";     

    sturl=url6;

         if("1".equals(st.getRcgzqx())){

        sturl=sturl+","+url1;

    }

        if("1".equals(st.getKhzbqx())){

        sturl=sturl+","+url2;

    }

        if("1".equals(st.getKhjgqx())){

        sturl=sturl+","+url3;

    }

        if("1".equals(st.getXtpzqx())){

        sturl=sturl+","+url4;

    }

        if("1".equals(st.getYhglqx())){

        sturl=sturl+","+url5;

    }

    if(sturl.indexOf(url)>=0){  

          System.out.println("有权访问!");

        chain.doFilter(request, response);

            }else{ 

                System.out.println("无权限!");

             response.setContentType("text/html;charset=GBK");

                 response.getWriter().println("<div style='margin: 100 auto;text-align: center;background-image:url(images/bg.jpg); "

                                         + "font: bold 18px 宋体;color: #0066CC;vertical-align: middle'> Sorry,您没有权限访问该资源!</div>");      

            }

    }

  /**

     * 是否需要判断权限,如客户端浏览、登录页面则不需要判断权限

     */

    protected boolean noFileUrl(String url, HttpServletRequest request) {

    String exclude = "login.do";

        if (exclude.indexOf(url)>=0) {

            return true;

        }

        return false;

    }

    }

2.配置 Servlet过滤器
容器通过 Web 应用程序中的配置描述符 web.xml 文件了解过滤器。有两个新的标记与过滤器相关:<filter> 和 <filter-mapping>。应该指定它们为 web.xml 文件内 <web-app> 标记的子标记。
过滤器定义的元素
<filter> 标记是一个过滤器定义,它必定有一个 <filter- name> 和 <filter-class> 子元素。

<filter-name> 子元素给出了一个与过滤器实例相关的、基于文本的名字。

<filter-class> 指定了由容器载入的实际类。您能随意地包含一个 <init-param> 子元素为过滤器实例提供初始化参数。

 

 

<!--权限jsp过滤器-->

 <filter >

<filter-name>permission </filter-name>

       <filter-class>dao.permissionFilter</filter-class>

    </filter>

    <filter-mapping>

       <filter-name>permission </filter-name>

<!-- 只过滤 .jsp 结尾的url, 其余的如 .do, .html, .jpg, .css 等不作过滤-->

       <url-pattern>*.jsp</url-pattern>

    </filter-mapping>

<!--权限do过滤器-->

 <filter >

<filter-name>permissiondo </filter-name>

       <filter-class>dao.permissiondoFilter</filter-class>

    </filter>

    <filter-mapping>

       <filter-name>permissiondo </filter-name>

<!-- 只过滤 .do 结尾的url, 其余的如 .jsp, .html, .jpg, .css 等不作过滤-->

       <url-pattern>*.do</url-pattern>

    </filter-mapping>

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值