MyException - 我的异常网
当前位置:我的异常网» 软件架构设计 » 使用过滤器跟拦截器做访问权限限制

使用过滤器跟拦截器做访问权限限制

www.MyException.Cn  网友分享于:2014-08-07  浏览:0次
使用过滤器和拦截器做访问权限限制

Struts2项目通过使用Struts的if标签进行了session判断,使得未登录的用户不能看到页面,但是这 种现仅仅在view层进行,如果未登录用户直接在地址栏输入登录用户才能访问的地址,那么相应的action还是会执行,仅仅是不让用户看到罢了。这样显然是不好的,所以研究了一下Struts2的权限验证。

权限最核心的是业务逻辑,具体用什么技术来实现就简单得多。 
通常:用户与角色建立多对多关系,角色与业务模块构成多对多关系,权限管理在后者关系中。 
对权限的拦截,如果系统请求量大,可以用Struts2拦截器来做,请求量小可以放在filter中。但一般单级拦截还不够,要做到更细粒度的权限控制,还需要多级拦截。

    不大理解filter(过滤器)和interceptor(拦截器)的区别,遂google之。博文中有介绍:

1、拦截器是基于java的反射机制的,而过滤器是基于函数回调 。 
2、过滤器依赖与servlet容器,而拦截器不依赖与servlet容器 。 
3、拦截器只能对action请求起作用,而过滤器则可以对几乎所有的请求 起作用 。 
4、拦截器可以访问action上下文、值栈里的对象,而过滤器不能 。 
5、在action的生命周期中,拦截器可以多次被调用,而过滤器只能在容 器初始化时被调用一次 。

    为了学习决定把两种实现方式都试一下,然后再决定使用哪个。

权限验证的Filter实现:

web.xml代码片段

  

[html] view plaincopy
 
  1. <!-- authority filter 最好加在Struts2的Filter前面-->  
  2.   <filter>  
  3.     <filter-name>SessionInvalidate</filter-name>  
  4.     <filter-class>filter.SessionCheckFilter</filter-class>  
  5.     <init-param>  
  6.       <param-name>checkSessionKey</param-name>  
  7.       <param-value>loginName</param-value>  
  8.     </init-param>  
  9.     <init-param>  
  10.       <param-name>redirectURL</param-name>  
  11.       <param-value>/entpLogin.jsp</param-value>  
  12.     </init-param>  
  13.     <init-param>  
  14.       <param-name>notCheckURLList</param-name>  
  15.       <param-value>/entpLogin.jsp,/rois/loginEntp.action,/entpRegister.jsp,/test.jsp,/rois/registerEntp.action</param-value>  
  16.     </init-param>  
  17.   </filter>  
  18.   <!--过滤/rois命名空间下所有action  -->  
  19.   <filter-mapping>  
  20.     <filter-name>SessionInvalidate</filter-name>  
  21.     <url-pattern>/rois/*</url-pattern>  
  22.   </filter-mapping>  
  23.   <!--过滤/jsp文件夹下所有jsp  -->  
  24.   <filter-mapping>  
  25.     <filter-name>SessionInvalidate</filter-name>  
  26.     <url-pattern>/jsp/*</url-pattern>  
  27.   </filter-mapping>  



SessionCheckFilter.java代码

[java] view plaincopy
 
  1. package filter;  
  2. import java.io.IOException;  
  3. import java.util.HashSet;  
  4. import java.util.Set;  
  5. import javax.servlet.Filter;  
  6. import javax.servlet.FilterChain;  
  7. import javax.servlet.FilterConfig;  
  8. import javax.servlet.ServletException;  
  9. import javax.servlet.ServletRequest;  
  10. import javax.servlet.ServletResponse;  
  11. import javax.servlet.http.HttpServletRequest;  
  12. import javax.servlet.http.HttpServletResponse;  
  13. import javax.servlet.http.HttpSession;  
  14. /** 
  15.  * 用于检测用户是否登陆的过滤器,如果未登录,则重定向到指的登录页面 配置参数 checkSessionKey 需检查的在 Session 中保存的关键字 
  16.  * redirectURL 如果用户未登录,则重定向到指定的页面,URL不包括 ContextPath notCheckURLList 
  17.  * 不做检查的URL列表,以分号分开,并且 URL 中不包括 ContextPath 
  18.  */  
  19. public class SessionCheckFilter implements Filter {  
  20.   protected FilterConfig filterConfig = null;  
  21.   private String redirectURL = null;  
  22.   private Set<String> notCheckURLList = new HashSet<String>();  
  23.   private String sessionKey = null;  
  24.   @Override  
  25.   public void destroy() {  
  26.     notCheckURLList.clear();  
  27.   }  
  28.   @Override  
  29.   public void doFilter(ServletRequest servletRequest,  
  30.       ServletResponse servletResponse, FilterChain filterChain)  
  31.       throws IOException, ServletException {  
  32.     HttpServletRequest request = (HttpServletRequest) servletRequest;  
  33.     HttpServletResponse response = (HttpServletResponse) servletResponse;  
  34.     HttpSession session = request.getSession();  
  35.     if (sessionKey == null) {  
  36.       filterChain.doFilter(request, response);  
  37.       return;  
  38.     }  
  39.     if ((!checkRequestURIIntNotFilterList(request))  
  40.         && session.getAttribute(sessionKey) == null) {  
  41.       response.sendRedirect(request.getContextPath() + redirectURL);  
  42.       return;  
  43.     }  
  44.     filterChain.doFilter(servletRequest, servletResponse);  
  45.   }  
  46.   private boolean checkRequestURIIntNotFilterList(HttpServletRequest request) {  
  47.     String uri = request.getServletPath()  
  48.         + (request.getPathInfo() == null ? "" : request.getPathInfo());  
  49.     String temp = request.getRequestURI();  
  50.     temp = temp.substring(request.getContextPath().length() + 1);  
  51.     // System.out.println("是否包括:"+uri+";"+notCheckURLList+"=="+notCheckURLList.contains(uri));  
  52.     return notCheckURLList.contains(uri);  
  53.   }  
  54.   @Override  
  55.   public void init(FilterConfig filterConfig) throws ServletException {  
  56.     this.filterConfig = filterConfig;  
  57.     redirectURL = filterConfig.getInitParameter("redirectURL");  
  58.     sessionKey = filterConfig.getInitParameter("checkSessionKey");  
  59.     String notCheckURLListStr = filterConfig  
  60.         .getInitParameter("notCheckURLList");  
  61.     if (notCheckURLListStr != null) {  
  62.       System.out.println(notCheckURLListStr);  
  63.       String[] params = notCheckURLListStr.split(",");  
  64.       for (int i = 0; i < params.length; i++) {  
  65.         notCheckURLList.add(params[i].trim());  
  66.       }  
  67.     }  
  68.   }  
  69. }  


权限验证的Interceptor实现:

   使用Interceptor不需要更改web.xml,只需要对struts.xml进行配置

struts.xml片段

[html] view plaincopy
 
  1. <!-- 用户拦截器定义在该元素下 -->  
  2.     <interceptors>  
  3.       <!-- 定义了一个名为authority的拦截器 -->  
  4.       <interceptor name="authenticationInterceptor" class="interceptor.AuthInterceptor" />  
  5.       <interceptor-stack name="defualtSecurityStackWithAuthentication">  
  6.         <interceptor-ref name="defaultStack" />  
  7.         <interceptor-ref name="authenticationInterceptor" />  
  8.       </interceptor-stack>  
  9.     </interceptors>  
  10.     <default-interceptor-ref name="defualtSecurityStackWithAuthentication" />  
  11.     <!-- 全局Result -->  
  12.     <global-results>  
  13.       <result name="error">/error.jsp</result>  
  14.       <result name="login">/Login.jsp</result>  
  15.     </global-results>  
  16.     <action name="login" class="action.LoginAction">  
  17.       <param name="withoutAuthentication">true</param>  
  18.       <result name="success">/WEB-INF/jsp/welcome.jsp</result>  
  19.       <result name="input">/Login.jsp</result>  
  20.     </action>  
  21.     <action name="viewBook" class="action.ViewBookAction">  
  22.         <result name="sucess">/WEB-INF/viewBook.jsp</result>  
  23.     </action>  


AuthInterceptor.java代码

[java] view plaincopy
 
  1. package interceptor;  
  2. import java.util.Map;  
  3. import com.opensymphony.xwork2.Action;  
  4. import com.opensymphony.xwork2.ActionContext;  
  5. import com.opensymphony.xwork2.ActionInvocation;  
  6. import com.opensymphony.xwork2.interceptor.AbstractInterceptor;  
  7. public class AuthInterceptor extends AbstractInterceptor {  
  8.   private static final long serialVersionUID = -5114658085937727056L;  
  9.   private String sessionKey="loginName";  
  10.   private String parmKey="withoutAuthentication";  
  11.   private boolean excluded;  
  12.   @Override  
  13.   public String intercept(ActionInvocation invocation) throws Exception {  
  14.       
  15.     ActionContext ac=invocation.getInvocationContext();  
  16.     Map<?, ?> session =ac.getSession();  
  17.     String parm=(String) ac.getParameters().get(parmKey);  
  18.       
  19.     if(parm!=null){  
  20.       excluded=parm.toUpperCase().equals("TRUE");  
  21.     }  
  22.       
  23.     String user=(String)session.get(sessionKey);  
  24.     if(excluded || user!=null){  
  25.       return invocation.invoke();  
  26.     }  
  27.     ac.put("tip""您还没有登录!");  
  28.     //直接返回 login 的逻辑视图    
  29.         return Action.LOGIN;   
  30.   }  
  31. }  

 

 

使用自定义的default-interceptor的话有需要注意几点:

1.一定要引用一下Sturts2自带defaultStack。否则会用不了Struts2自带的拦截器。

2.一旦在某个包下定义了上面的默认拦截器栈,在该包下的所有 Action 都会自动增加权限检查功能。所以有可能会出现永远登录不了的情况。

解决方案:

1.像上面的代码一样,在action里面增加一个参数表明不需要验证,然后在interceptor实现类里面检查是否不需要验证

2.将那些不需要使用权限控制的 Action 定义在另一个包中,这个新的包中依然使用 Struts 2 原有的默认拦截器栈,将不会有权限控制功能。

3.Interceptor是针对action的拦截,如果知道jsp地址的话在URL栏直接输入JSP的地址,那么权限验证是没有效果滴!

解决方案:把所有page代码(jsp)放到WEB-INF下面,这个目录下的东西是“看不见”的

文章评论

为什么程序员都是夜猫子
为什么程序员都是夜猫子
总结2014中国互联网十大段子
总结2014中国互联网十大段子
程序员必看的十大电影
程序员必看的十大电影
不懂技术不要对懂技术的人说这很容易实现
不懂技术不要对懂技术的人说这很容易实现
“肮脏的”IT工作排行榜
“肮脏的”IT工作排行榜
程序员都该阅读的书
程序员都该阅读的书
程序员最害怕的5件事 你中招了吗?
程序员最害怕的5件事 你中招了吗?
Web开发人员为什么越来越懒了?
Web开发人员为什么越来越懒了?
看13位CEO、创始人和高管如何提高工作效率
看13位CEO、创始人和高管如何提高工作效率
Google伦敦新总部 犹如星级庄园
Google伦敦新总部 犹如星级庄园
 程序员的样子
程序员的样子
为啥Android手机总会越用越慢?
为啥Android手机总会越用越慢?
程序员和编码员之间的区别
程序员和编码员之间的区别
编程语言是女人
编程语言是女人
程序员眼里IE浏览器是什么样的
程序员眼里IE浏览器是什么样的
Java 与 .NET 的平台发展之争
Java 与 .NET 的平台发展之争
我跳槽是因为他们的显示器更大
我跳槽是因为他们的显示器更大
初级 vs 高级开发者 哪个性价比更高?
初级 vs 高级开发者 哪个性价比更高?
10个调试和排错的小建议
10个调试和排错的小建议
程序员周末都喜欢做什么?
程序员周末都喜欢做什么?
中美印日四国程序员比较
中美印日四国程序员比较
亲爱的项目经理,我恨你
亲爱的项目经理,我恨你
2013年美国开发者薪资调查报告
2013年美国开发者薪资调查报告
60个开发者不容错过的免费资源库
60个开发者不容错过的免费资源库
Java程序员必看电影
Java程序员必看电影
十大编程算法助程序员走上高手之路
十大编程算法助程序员走上高手之路
程序员的鄙视链
程序员的鄙视链
老美怎么看待阿里赴美上市
老美怎么看待阿里赴美上市
程序猿的崛起——Growth Hacker
程序猿的崛起——Growth Hacker
鲜为人知的编程真相
鲜为人知的编程真相
做程序猿的老婆应该注意的一些事情
做程序猿的老婆应该注意的一些事情
什么才是优秀的用户界面设计
什么才是优秀的用户界面设计
5款最佳正则表达式编辑调试器
5款最佳正则表达式编辑调试器
旅行,写作,编程
旅行,写作,编程
科技史上最臭名昭著的13大罪犯
科技史上最臭名昭著的13大罪犯
Web开发者需具备的8个好习惯
Web开发者需具备的8个好习惯
一个程序员的时间管理
一个程序员的时间管理
如何成为一名黑客
如何成为一名黑客
程序员应该关注的一些事儿
程序员应该关注的一些事儿
团队中“技术大拿”并非越多越好
团队中“技术大拿”并非越多越好
每天工作4小时的程序员
每天工作4小时的程序员
要嫁就嫁程序猿—钱多话少死的早
要嫁就嫁程序猿—钱多话少死的早
10个帮程序员减压放松的网站
10个帮程序员减压放松的网站
当下全球最炙手可热的八位少年创业者
当下全球最炙手可热的八位少年创业者
代码女神横空出世
代码女神横空出世
那些性感的让人尖叫的程序员
那些性感的让人尖叫的程序员
如何区分一个程序员是“老手“还是“新手“?
如何区分一个程序员是“老手“还是“新手“?
写给自己也写给你 自己到底该何去何从
写给自己也写给你 自己到底该何去何从
程序员的一天:一寸光阴一寸金
程序员的一天:一寸光阴一寸金
软件开发程序错误异常ExceptionCopyright © 2009-2015 MyException 版权所有