1. 程式人生 > >修改struts2中UI標籤的進行許可權控制

修改struts2中UI標籤的進行許可權控制

最近在做學習S2SH時,有一個模組式許可權控制,就是對使用者的操作存在許可權分級操作,即不是所有的使用者都可以訪問全部資料。下面說一下這次我們的做法。

   1.所謂許可權控制,就是對URL地址的控制,使用者角色中不存在該許可權,那麼該url地址對使用者是不起反應的(使用者點選無反應),最好是不可見的。整體的思路就是這樣,通過對UI標籤的控制而達到對許可權的控制。

   2.我們使用的是struts2中的a標籤,而非使用簡單的html中a標籤。原因是在<s:a>標籤的原始碼中存在doStartTag()和doEndTag()方法.假設存在以下標籤:

<s:a action="user_delete.action?id=%{id}"  onClick="return delConfirm()">刪除</s:a>

那麼在執行doStartTag()方法之後,標籤會讀到<s:a action="user_delete.action?id=%{id}"  onClick="return delConfirm()">,並沒有將標籤資訊讀完! 在執行完doEndTag()方法之後,標籤會將剩下的配置讀完。所以要檢查是否存在許可權,需要在doEndTag()方法中增加自己的邏輯。

  3.下面來簡單介紹一下如下修改UI之<s:a>原始碼。在struts2-core原始碼包下找到META-INF資料夾(不出意外的話應該是最下面位置),開啟裡面的struts-tags.tld.通過搜尋<name>a</name>找到標籤中的對應的原始類org.apache.struts2.views.jsp.ui.AnchorTag,然後開啟該原始碼(打不開也沒關係,等會你拷我的原始碼就可以了。

因為我裝了GD-GUI外掛,建議打不開jar檔案的你也裝一下).在你的專案src下新建一個org.apache.struts2.views.jsp.ui的包,在包內新建一個AnchorTag類(是的,與上面的類一模一樣,原因很簡單,jvm會優先載入src下的class檔案,src下的class檔案找不到就去外部jar包中查詢),程式碼如下:

package org.apache.struts2.views.jsp.ui;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.jsp.JspException;

import org.apache.struts2.components.Anchor;
import org.apache.struts2.components.Component;

import com.it.entity.User;
import com.opensymphony.xwork2.util.ValueStack;

public class AnchorTag extends AbstractClosingTag {
	private static final long serialVersionUID = -1034616578492431113L;
	protected String href;
	protected String includeParams;
	protected String scheme;
	protected String action;
	protected String namespace;
	protected String method;
	protected String encode;
	protected String includeContext;
	protected String escapeAmp;
	protected String portletMode;
	protected String windowState;
	protected String portletUrlType;
	protected String anchor;
	protected String forceAddSchemeHostAndPort;

	public Component getBean(ValueStack stack, HttpServletRequest req, HttpServletResponse res) {
		return new Anchor(stack, req, res);
	}

	/**
	 * 自定義的程式碼
	 */
	@Override
	public int doEndTag() throws JspException {
		User user = (User) pageContext.getSession().getAttribute("user");
<span style="white-space:pre">		</span>//user.hasThisURLPrivilege(String url)是配對自己是否用於許可權
		if(user != null && user.hasThisURLPrivilege(action)){
			return super.doEndTag();
		}else{
			return EVAL_PAGE ; 
		}
	}

	protected void populateParams() {
		super.populateParams();

		Anchor tag = (Anchor) this.component;
		tag.setHref(this.href);
		tag.setIncludeParams(this.includeParams);
		tag.setScheme(this.scheme);
		tag.setValue(this.value);
		tag.setMethod(this.method);
		tag.setNamespace(this.namespace);
		tag.setAction(this.action);
		tag.setPortletMode(this.portletMode);
		tag.setPortletUrlType(this.portletUrlType);
		tag.setWindowState(this.windowState);
		tag.setAnchor(this.anchor);

		if (this.encode != null) {
			tag.setEncode(Boolean.valueOf(this.encode).booleanValue());
		}
		if (this.includeContext != null) {
			tag.setIncludeContext(Boolean.valueOf(this.includeContext)
					.booleanValue());
		}
		if (this.escapeAmp != null) {
			tag.setEscapeAmp(Boolean.valueOf(this.escapeAmp).booleanValue());
		}
		if (this.forceAddSchemeHostAndPort != null)
			tag.setForceAddSchemeHostAndPort(Boolean.valueOf(
					this.forceAddSchemeHostAndPort).booleanValue());
	}

	public void setHref(String href) {
		this.href = href;
	}

	public void setEncode(String encode) {
		this.encode = encode;
	}

	public void setIncludeContext(String includeContext) {
		this.includeContext = includeContext;
	}

	public void setEscapeAmp(String escapeAmp) {
		this.escapeAmp = escapeAmp;
	}

	public void setIncludeParams(String name) {
		this.includeParams = name;
	}

	public void setAction(String action) {
		this.action = action;
	}

	public void setNamespace(String namespace) {
		this.namespace = namespace;
	}

	public void setMethod(String method) {
		this.method = method;
	}

	public void setScheme(String scheme) {
		this.scheme = scheme;
	}

	public void setValue(String value) {
		this.value = value;
	}

	public void setPortletMode(String portletMode) {
		this.portletMode = portletMode;
	}

	public void setPortletUrlType(String portletUrlType) {
		this.portletUrlType = portletUrlType;
	}

	public void setWindowState(String windowState) {
		this.windowState = windowState;
	}

	public void setAnchor(String anchor) {
		this.anchor = anchor;
	}

	public void setForceAddSchemeHostAndPort(String forceAddSchemeHostAndPort) {
		this.forceAddSchemeHostAndPort = forceAddSchemeHostAndPort;
	}
}
  需要修改的方法就是在doTagEnd()中,存在於父類中。首先我們會獲取該使用者的資訊,在User存在的情況下,我們進行判斷,在使用者擁有該許可權時,執行
return super.doEndTag();
該方法的意思是:顯示該超連結的資訊,然後繼續執行後面的程式碼。當用戶不存在該許可權時,執行
return EVAL_PAGE ;
該方法的意思是:不顯示該超連結的資訊(就是意味著該標籤將不顯示於JSP檔案中了),然後繼續執行後面的程式碼。

   好了,我感覺我說清楚了,雖然這只是一個小知識,但是如果不使用的UI標籤去判斷是否存在許可權,那麼感覺程式碼不會像這樣簡潔了吧。。