修改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,然後開啟該原始碼(打不開也沒關係,等會你拷我的原始碼就可以了。
需要修改的方法就是在doTagEnd()中,存在於父類中。首先我們會獲取該使用者的資訊,在User存在的情況下,我們進行判斷,在使用者擁有該許可權時,執行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; } }
return super.doEndTag();
該方法的意思是:顯示該超連結的資訊,然後繼續執行後面的程式碼。當用戶不存在該許可權時,執行return EVAL_PAGE ;
該方法的意思是:不顯示該超連結的資訊(就是意味著該標籤將不顯示於JSP檔案中了),然後繼續執行後面的程式碼。
好了,我感覺我說清楚了,雖然這只是一個小知識,但是如果不使用的UI標籤去判斷是否存在許可權,那麼感覺程式碼不會像這樣簡潔了吧。。