• 过滤器实用案例


    1、转载:通过struts2拦截器实现权限管理

    1.1简单实例:

    避免login.jsp也被拦截,而永远不能登录了,一旦在某个包下定义了上面的默认拦截器栈,在该包下的所有 Action 都会自动增加权限检查功能,对于那些不需要使用权限控制的 Action ,将它们定义在另一个包中,这个新的包中依然使用 Struts 2 原有的默认拦截器栈,将不会有权限控制功能。

    <package name="manage" extends="struts-default" namespace="/manage">
    <!--配置系统烂机器-->
    <interceptors>
       <!-- 定义系统的登录控制的拦截器 -->
       <interceptor name="authority" class="com.Action.AuthorityInterceptor" />
      <!--定义系统auctionStack烂机器-->
       <interceptor-stack name="auctionStack">
        <!--引用系统默认拦截器-->
        <interceptor-ref name="defaultStack" />
        <!--引用登录控制拦截器-->
        <interceptor-ref name="authority" />
       </interceptor-stack>
      </interceptors>
    
      <!-- 将自定义连接器站定义成默认执行的拦截器 -->
      <default-interceptor-ref name="auctionStack" />
    
      <global-results>
       <!-- 当返回login视图名时,转入/login.jsp页面 -->
       <result name="login" type="redirect">/login.jsp</result>
      </global-results>
      <action...
    </package>
    <package name="admin" extends="struts-default,manage" namespace="/admin">
        <action name="login" class="com.dxz.SecurityAction" method="checklogin">
             <result name"errorlogin">/login.jsp</result>
             <!--显示引用系统默认的烂机器
             <interceptor-ref name="defaultStack"/>
         </action>
         <action name="loginout" ...
    </package>
     

    AuthorityInterceptor.java

    /**
     * 
     */
    package com.Action;
    
    import com.opensymphony.xwork2.ActionContext;
    import com.opensymphony.xwork2.ActionInvocation;
    import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
    
    /**
     * @author duanxz//用户登陆权限验证;
     *
     */
    public class AuthorityInterceptor extends AbstractInterceptor  {
      public String intercept(ActionInvocation invocation) throws Exception {   
             // 取得请求相关的ActionContext实例   
             ActionContext ctx=invocation.getInvocationContext(); 
             if(ctx.getSession().get("userinfo")==null)//未登陆
             {
              // return invocation.invoke();
              return "login";
              
             }
              return invocation.invoke();
         }  
    
    
    }

    第一次使用,只是简单的测试,用户的session,作个标记。

    1.2转载示例

    package com.work.qxgl.login;
    import java.util.List;
    import java.util.Map;
    import javax.servlet.http.HttpServletRequest;
    import org.apache.commons.logging.Log;
    import org.apache.commons.logging.LogFactory;
    import org.apache.struts2.StrutsConstants;
    import org.apache.struts2.config.DefaultSettings;
    import com.opensymphony.xwork2.Action;
    import com.opensymphony.xwork2.ActionInvocation;
    import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
    import com.work.core.QxglConstants;
    import com.work.core.spring.MyBeanUtil;
    import com.work.qxgl.model.QxglRole;
    import com.work.qxgl.usermodel.UserModelServiceDao;
    public class AuthorizationInterceptor extends AbstractInterceptor {
        /**
         * 
         */
        private static final long serialVersionUID = 4949812834762901805L;
        private static Log log = LogFactory.getLog(AuthorizationInterceptor.class);
        @Override
        public String intercept(ActionInvocation invocation) throws Exception {
            // 取得请求的Action名
            String name = invocation.getInvocationContext().getName(); // action
            // 的名称,在xml中配置的
            String namespace = invocation.getProxy().getNamespace(); // 获取到namespace,还能够获取到要执行的方法,class等
            if ((namespace != null) && (namespace.trim().length() > 0)) {
                if ("/".equals(namespace.trim())) {
                    // 说明是根路径,不需要再增加反斜杠了。
                } else {
                    namespace += "/";
                }
            }
            String URL = namespace + invocation.getProxy().getActionName();
            
            URL += ".action";
            log.debug("actionname=" + name + "||fullActionName=" + URL);
            if (name.equals("login") || name.equals("loginAccess")) {
                // 如果用户想登录,则使之通过
                return invocation.invoke();
            }
            Map session = invocation.getInvocationContext().getSession();
            // TODO 在这里判断用户是否已经登陆,更改此方法,和OnLineUserManager联系起来,
            //OnLineUserManager 是线程安全的,效率上可能会比较低!所以暂时还不更改!。
            String success = (String) session.get(QxglConstants.AUTH_SUCCESS);
            log.debug("success=" + success);
            // 如果没有登陆,那么就退出系统
            if (success == null || !"true".equals(success)) {
                log.debug("please login");
                return Action.LOGIN;
            }
            String userid = (String) session.get("userid");
            if (userid == null || "".equals(userid)) {
                log.error("用户id不能为空!");
                return Action.LOGIN;
            }
            // 如果是超级管理员,那么直接返回
            if ("admin1111222233334444555566admin".equals(userid)) {
                return invocation.invoke();
            }
            UserModelServiceDao userModelServiceDao = (UserModelServiceDao) MyBeanUtil
                    .getBean("userModelServiceDao");
            // 获取当前用户所拥有的角色
            List<QxglRole> userRoles = userModelServiceDao.getRoles(userid);
            if (userRoles == null || userRoles.size() < 1) {
                // 没有任何角色
                log.warn("此用户" + userid + "没有任何角色,没有权限执行任何功能");
                return "noPermit";
            }
            List<QxglRole> urlRoles = userModelServiceDao.getRolesByUrl(URL);
            // 如果此URL没有赋给任何角色,说明是合法用户就可以访问
            if (urlRoles == null || urlRoles.size() < 1) {
                log.debug("此资源未赋给任何角色,合法用户就可以访问");
                return invocation.invoke();
            }
            // 根据角色来判断用户是否有权限来使用当前的URL(action)
            boolean flag = false;// 如果有权限访问设置为true;
            int userLen = userRoles.size();
            int urlLen = urlRoles.size();
            QxglRole tempUserRole = null;
            QxglRole tempUrlRole = null;
            
            START:
            for (int i = 0; i < userLen; i++) {
                // 首先初始化
                tempUserRole = null;
                tempUrlRole = null;
                tempUserRole = userRoles.get(i);
                for (int j = 0; j < urlLen; j++) {
                    tempUrlRole = urlRoles.get(j);
                    if (tempUserRole.getId().equals(tempUrlRole.getId())) {
                        flag = true;
                        break START;
                    }
                }
            }
            if (flag) {
                log.debug("success auth");
                return invocation.invoke();
            } else {
                //用户如果在主页面中输入其他的任何链接,系统将自动执行logout动作,因为在/sysmenu/top.jsp中配置了onunload事件。
                log.warn("此用户" + userid + "没有权限执行此功能"+URL);
                return "noPermit";
            }
        }

    }

    在需要验证的包上加上配置,struts.xml

    <package name="qxglmain" extends="struts-default" namespace="/">
            <!-- 自定义拦截器 -->
            <interceptors>
                <interceptor name="auth"
                    class="com.work.qxgl.login.AuthorizationInterceptor" />
                <interceptor name="ourLogger"
                    class="com.work.core.interceptor.LoggingInterceptor" />
                <interceptor name="ourTimer"
                    class="com.work.core.interceptor.TimerInterceptor" />               
                <!-- 自定义拦截器堆栈 -->
                <interceptor-stack name="qxglStack">
                    <interceptor-ref name="auth" /><!--  权限控制 -->
                    <!-- 用来查看每个action执行了多长时间,看执行效率,只所以重新编写,因为xwork的源代码的日志级别低为INFO,我们配置的日志级别为ERROR。所以看不到了 -->
                    <interceptor-ref name="ourTimer" />
                    <interceptor-ref name="ourLogger" />
                    <!-- 
                    <interceptor-ref name="logger" /> -->
                    <!-- 引用默认的拦截器堆栈 -->
                    <interceptor-ref name="defaultStack" />
                </interceptor-stack>
            </interceptors>
            <!-- 重定义默认拦截器堆栈 -->
            <default-interceptor-ref name="qxglStack" />
            <global-results>
                <result name="login" type="redirectAction">login</result>
                <result name="error">/qxgl/error.jsp</result>
                <result name="noPermit">/qxgl/noPermit.jsp</result>
                <result name="input" type="redirectAction">login</result>           
            </global-results>
            <!--  exception的配置必须在global-results后面 -->
            <global-exception-mappings>
                <exception-mapping
                    exception="java.lang.NullPointerException" result="error" />
                <exception-mapping exception="java.lang.Exception"
                    result="error" />
                <exception-mapping
                    exception="com.work.core.exception.StorageException" result="error" />              
            </global-exception-mappings>
            
            <action name="qxglmain"
                class="com.work.qxgl.main.QxglMainAction">
                <result>/qxgl/menutree/qxglmain.jsp</result>
            </action>
            <action name="sysmain"
                class="com.work.qxgl.main.QxglMainAction" method="sysmain">
                <result>/sysmenu/sysMain.jsp</result>
            </action>
            <action name="login" class="com.work.qxgl.login.LoginAction"
                method="login">
                <result>/login.jsp</result>
            </action>
            <action name="logout" class="com.work.qxgl.login.LogoutAction">
                <result>/login.jsp</result>
            </action>
        
            <action name="loginAccess" class="com.work.qxgl.login.LoginAction">
                <result type="redirectAction">sysmain</result>
                <result name="input" >/login.jsp</result>
            </action>
            <action name="listOnLineUsers" class="com.work.qxgl.login.OnLineUserAction">
                <result>/qxgl/onlineuser/onlineuser.jsp</result>
            </action>   
            <action name="kickUser" class="com.work.qxgl.login.OnLineUserAction"
                method="kickUser">
                <result type="chain">listOnLineUsers</result>
            </action>       
            <action name="listMenu" class="com.work.qxgl.main.QxglMainAction"
                method="listMenu">
                <result>/sysmenu/menu.jsp</result>
            </action>       
        </package>

    缺点:

    struts2的拦截器只能够控制*.action,其他的jsp文件等会被忽略,所以通过struts2的拦截器实现权限控制有一定的缺陷。

    我们可以通过编写一个filter来控制其他请求的权限

    package com.work.core.filter;
    /**
     * @author wangmingjie
     * @date 2008-8-25下午10:09:26
     */
    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;
    import javax.servlet.http.HttpSession;
    import org.apache.commons.logging.Log;
    import org.apache.commons.logging.LogFactory;
    import com.work.core.QxglConstants;
    public class AuthFilter implements Filter {
        private static Log log = LogFactory.getLog(AuthFilter.class);
        public void init(FilterConfig filterConfig) throws ServletException {
            if(log.isDebugEnabled()){
                log.debug("初始化权限过滤器。");
            }
        }
        public void doFilter(ServletRequest servletRequest,
                ServletResponse servletResponse, FilterChain filterChain)
                throws IOException, ServletException {
            /**
             * 1,doFilter方法的第一个参数为ServletRequest对象。此对象给过滤器提供了对进入的信息(包括
             * 表单数据、cookie和HTTP请求头)的完全访问。第二个参数为ServletResponse,通常在简单的过
             * 滤器中忽略此参数。最后一个参数为FilterChain,此参数用来调用servlet或JSP页。
             */
            HttpServletRequest request = (HttpServletRequest) servletRequest;
            /**
             * 如果处理HTTP请求,并且需要访问诸如getHeader或getCookies等在ServletRequest中
             * 无法得到的方法,就要把此request对象构造成HttpServletRequest
             */
            HttpServletResponse response = (HttpServletResponse) servletResponse;
            String currentURL = request.getRequestURI(); // 取得根目录所对应的绝对路径:
            HttpSession session = request.getSession(false);
            //如果jsp就验证(login.jsp除外)
            if (currentURL.indexOf(QxglConstants.LOGIN_PAGE)==-1 && currentURL.indexOf(".jsp")>-1 ) { 
                if(log.isDebugEnabled()){
                    log.debug("对jsp文件进行权限验证。"+"请求的URL:"+currentURL);            
                }
                // 判断当前页是否是重定向以后的登录页面页面,如果是就不做session的判断,防止出现死循环
                if(session == null || session.getAttribute(QxglConstants.AUTH_SUCCESS) == null ){
                    response.sendRedirect(request.getContextPath()+QxglConstants.LOGIN_PAGE);
                    return ;
                }
            }
            // 加入filter链继续向下执行
            filterChain.doFilter(request, response);
            /**
             * 调用FilterChain对象的doFilter方法。Filter接口的doFilter方法取一个FilterChain对象作 为它
             * 的一个参数。在调用此对象的doFilter方法时,激活下一个相关的过滤器。如果没有另
             * 一个过滤器与servlet或JSP页面关联,则servlet或JSP页面被激活。
             */
        }
        public void destroy() {
        }
    }

    在web.xml中配置权限过滤器

    <!-- 进行权限验证 -->
        <filter>
            <filter-name>AuthFilter</filter-name>
            <filter-class>
                com.work.core.filter.AuthFilter
            </filter-class>
        </filter>   
        <filter-mapping>
            <filter-name>AuthFilter</filter-name>
            <url-pattern>/*</url-pattern>
        </filter-mapping>

     2、配置编码过滤器

    只需要导入spring.jar即可

    <filter>
      <filter-name>CharacterEncoding</filter-name>
     <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
      <init-param>
      <param-name>encoding</param-name>
      <param-value>UTF-8</param-value>
      </init-param>
      <init-param>
      <param-name>forceEncoding</param-name>
      <param-value>true</param-value>
      </init-param>
     </filter> 
     
     <filter>
      <filter-name>filterDispatcher</filter-name>
      <filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>
     </filter>
     <filter-mapping>
          <filter-name>CharacterEncoding</filter-name>
          <url-pattern>*.do</url-pattern>
     </filter-mapping>
      
     <filter-mapping>
      <filter-name>filterDispatcher</filter-name>
      <url-pattern>*.do</url-pattern>  
    </filter-mapping> 
  • 相关阅读:
    Python(3)---从迭代器到异步IO
    并发访问sqlite数据库出现databse is locked的错误的一个解决办法
    基础概念2
    (已解决)Arduino mega2560 R3插在电脑上没有反应
    <Android 基础(二)> BroadcastReceiver
    unicode字符和多字节字符的相互转换接口
    PHP中XML和数组互相转换的方法
    java网络编程—TCP(1)
    Java EE的十三个技术规范
    <Android 基础(一)> Service
  • 原文地址:https://www.cnblogs.com/duanxz/p/3158600.html
Copyright © 2020-2023  润新知