`
zscomehuyue
  • 浏览: 401759 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

struts2拦截器实现权限控制

阅读更多
在使用struts2框架开发一个办公OA系统时候,需要使用到权限控制  
   
除了判定是否登陆之外,还必须对每个action的访问实现权限控制,因为如果用户登陆成功了,而且以前拥有某个权限的访问,记录下访问的action,而现在没有权限了,也能直接在地址栏输入action路径直接访问,这将使权限这一模块毫无用处。  
   
因为没有用到命名空间,这里对于涉及命名空间的没有控制  
   
解决思路:【先看这个,懂了以下代码就明白了】  
    我们知道struts2的拦截器可以很方便实现对action的访问拦截,先行判断然后再决定是否能够访问。我的实现方法是:  
    1.左侧菜单的树形每一列对应一个子模块,也对应一个权限控制ID,若是用户拥有权限,显示,没有,不显示  
    2.配置一个xml文件,包含所有权限ID以及其对应的子模块的action,由于某些模块可能使用相同的action,将存在同名的action配置【待会实现注意】  
    3.定义一个servlet,在web.xml中配置其启动优先,服务器启动加载  
    4.在servlet中,启动是使用插件读入xml文件内容,转化为一个hashmap,键值为action的name属性,value为对应权限id的组合字符串,以空格隔开  
    5.hashmap放入application  
    6.在struts.xml中定义拦截器的package,定义一个拦截器,配置拦截器栈,其他需要使用到拦截器的package在配置是使用extends这个拦截器package 
    7.用户登陆后从数据库查询权限,转为一个hashmap,权限id为键值【为了查询方便】,放入session  
    8.实现拦截器,从session中取用户权限,从application中取action映射权限ID的map,从拦截器的invocation中取此次访问的action在配置文件中的actionName  
      先判定是否登陆,否,转login.jsp  
      是,判定用户是否有访问此action的权限,否,跳到消息页,是,通过  
实现步骤:  
1.关于左侧菜单的显示,是标签和js等的内容,不再解释,这里主要是地址栏非法访问的控制  
2.配置xml文件  authority.xml,配置对应的权限id和其可使用的action【name属性为在struts.xml中配置action的name属性】  
<?xml version="1.0" encoding="UTF-8"?>  
<total>  
<!-- //卷库管理-->  
<authority id="18">  
<action name="addRecord"/>  
<action name="deleteRecord"/>  
<action name="updateRecord"/>  
<action name="getAllRecordList"/>  
<action name="getRecordContent"/>  
</authority>  
</total>  
3.定义servlet,启动加载配置  
  web.xml中  
  <servlet>  
   <servlet-name>InitBuild</servlet-name>  
   <servlet-class>interceptor.InitBuild</servlet-class>  
   <load-on-startup>1</load-on-startup>  
   </servlet>  
  对应servlet【省略package import等】  
public class InitBuild extends HttpServlet {  
public void init() throws ServletException {  
  try {  
   String path = this.getServletContext().getRealPath("/");//项目路径  
   this.getServletContext().setAttribute("path", path);  
   this.getServletContext().setAttribute("msg", "启动加载完毕");  
   //xml文件路径   
   String xmlPath = path+"WEB-INF/authority.xml";  
   this.getServletContext().setAttribute("xmlpath", xmlPath);  
   //调用方法,读入xml文件,转化为hashmap  
   this.getServletContext().setAttribute("authorityMap", InitXmlAuthorInfo.getAuthorityMap(xmlPath));  
    } catch (Exception e) {  
     e.printStackTrace();  
  } }}  
   
4.在3中调用的方法,主要读入xml文件,转为hashmap,这里是用dom4j  
import org.dom4j.Document;  
import org.dom4j.Element;  
import org.dom4j.io.SAXReader;  
public class InitXmlAuthorInfo {  
   
private static Document getDom(String xmlPath) {  
  try {  
   SAXReader reader = new SAXReader();  
   Document document = null;  
   document = reader.read(new File(xmlPath));  
   return document;  
  } catch (Exception e) {  
    e.printStackTrace();  
   return null;  
  }  
}  
   
public static HashMap<String,String> getAuthorityMap(String xmlPath)  
{  
  HashMap<String,String> authorityMap = new HashMap<String,String>();  
  Document document = getDom(xmlPath);  
  Element rootElm = document.getRootElement();  
  for (Iterator i = rootElm.elementIterator(); i.hasNext();) {  
   Element element = (Element) i.next();  
       
   String id = element.attributeValue("id");  
     
   List<Element> temp = element.elements();  
   for (int j = 0,length = temp.size();j<length; j++) {  
     String actionName = temp.get(j).attribute("name").getText();  
    //action是否重名  
    if(authorityMap.containsKey(actionName))  
    {  
      authorityMap.put(actionName,authorityMap.get(actionName)+" "+id);  
    }else{  
     authorityMap.put(actionName,id);  
    }  
     }  
   }  
  return authorityMap;  
}  
}  
5.配置拦截器和拦截器栈  struts.xml中配置  
   
<!-- 其他package必须extends此package -->  
<package name="authorityCheck" extends="struts-default">  
        <interceptors>  
        <!-- 在package中配置   注意,login不需要定义此拦截器,定义权限控制拦截器 -->  
          <interceptor name="authority" class="interceptor.AuthorizationInterceptor"/>  
        <!-- 定义含“权限检查拦截器”的拦截器栈,注意缺省的拦截器栈“defaultStack”要放在前面 -->  
          <interceptor-stack name="authorityStack">   
            <interceptor-ref name="defaultStack"></interceptor-ref>   
            <interceptor-ref name="authority"></interceptor-ref>   
          </interceptor-stack>   
        </interceptors>  
       
        <default-interceptor-ref name="authorityStack"></default-interceptor-ref>  
 
        <!-- 定义全局处理结果 未登录转到此页-->  
        <global-results>  
        <!-- 逻辑名为login的结果,映射到/login.jsp页面 -->  
        <result name="login">/login.jsp</result>  
        <!-- 无权限进行操作 -->  
        <result name="authorityDeny">/authorityMsg.jsp</result>  
        </global-results>  
</package>  
6.实现拦截器  
   
   package interceptor;  
import java.util.Iterator;  
import java.util.Map;  
import com.opensymphony.xwork2.Action;  
import com.opensymphony.xwork2.ActionInvocation;  
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;  
public class AuthorizationInterceptor extends AbstractInterceptor {  
@Override 
public String intercept(ActionInvocation invocation) throws Exception {  
  // 获取session   以及application  
  Map session = invocation.getInvocationContext().getSession();  
    
  //判定是否登陆了   未登录 打回登陆页面   用户登陆成功必须将UserID放入session  
  if(session.get("UserID") == null)  
  {  
   System.out.println("AUTHOR ERROR:未登录");  
   return Action.LOGIN;  
  }  
    
  Map application = invocation.getInvocationContext().getApplication();  
    
  //获取全局的权限列表   这个是前面服务器启动加载servlet时候放入application的  
  Map globalAuthorityMap = (Map)application.get("authorityMap");  
    
  //1.判不为空  
  //2.从session取用户权限列表  
  //3.取action的name  
  //4.根绝action的name取权限字符串  
  //5.切分,校验,某一个有就发,全部没有转发消息页面  
    
  //获取用户的权限列表   用户登陆成功将其拥有所有权限的id放入hashmap键值,整个放入session  
  Map userAuthorityMap = (Map)session.get("AuthMap");  
      
  //获取请求的action的name  
  String actionName = invocation.getProxy().getActionName();  
    
  String authorStr = (String)globalAuthorityMap.get(actionName);  
    
//切分,当初对于不同权限访问同一action配置空格隔开的字符串  
  String[] authorList = authorStr.split(" ");  
   for (int i = 0; i < authorList.length; i++) {  
    if(userAuthorityMap.containsKey(authorList[i]))  
   {  
    return invocation.invoke();  
   }  
   }  
  session.put("authorityMag", "对不起,您没有权限进行此操作");  
  return "authorityDeny";  
  }  
}  
7.其他package的配置  
  注,登陆注销的action不需要  
  <package name="record" extends="authorityCheck">  
   <action name="getRecordContent" class="com.oa.team4.action.RecordAction" 
   method="getRecordContent">  
   <result name="success">/record/edit_record.jsp</result>  
   </action>  
  </package>  
  
分享到:
评论
1 楼 Torero 2011-11-16  
请求的不是Action的Execute方法, 而是其他方法呢?
你的这种写法, 好像就有点牵强了吧?

举个例子来说, 用户管理的Action, 名称为:
public class UserAction implements Action {

	// 最普通的 Execute 方法
	public abstract String execute();

	//取得单个的 User
	public abstract String getUser();
	// 保存 User
	public abstract String saveUser();
	// 得到 符合条件的 User 集合
	public abstract String userList();
}

如果 struts 的 Action 设定是:
<action name="argTest" class="torero.test.UserAction" method="userList" >

这种情况下, 你的代码就应该是:
String authorStr = (String) globalAuthorityMap.get(actionName);
-->
String authorStr = (String) globalAuthorityMap.get(invokMethod);

相关推荐

Global site tag (gtag.js) - Google Analytics