Tapestry最新版5.1.0.5教程(八):權(quán)限控制框架的實(shí)現(xiàn)-基礎(chǔ)篇
Posted on 2010-01-12 20:17 云自無(wú)心水自閑 閱讀(2862) 評(píng)論(0) 編輯 收藏 所屬分類(lèi): Java 、心得體會(huì) 、Spring Security 、TapestryTapestry中并沒(méi)有類(lèi)似于Spring Security這樣的專(zhuān)門(mén)的權(quán)限框架。對(duì)此Tapestry的作者Lewis認(rèn)為主要是用戶(hù)對(duì)于權(quán)限的要求實(shí)在太多變化了。他認(rèn)為很難抽象出一個(gè)通用的權(quán)限框架來(lái)滿足所有的用戶(hù),所以他干脆就不費(fèi)事去做這件事了。但其實(shí)我們很容易就能利用Tapestry已有的工具來(lái)完成類(lèi)似于SpringSecurity的功能。
本文主要介紹如何實(shí)現(xiàn)類(lèi)似于SpringSecurity的jsp tag的功能。在Tapestry中,利用Components實(shí)現(xiàn)這一點(diǎn)非常容易。
其基本原理是Tapestry5中一個(gè)頁(yè)面或者組件的渲染生成過(guò)程是基于一個(gè)狀態(tài)機(jī)和隊(duì)列完成的。這樣,渲染生成過(guò)程就被細(xì)分成了很多個(gè)小模塊,我們可以非常容易地覆寫(xiě)這些小模塊。具體內(nèi)容詳見(jiàn)官方文檔:http://tapestry.apache.org/tapestry5.1/guide/rendering.html。如果權(quán)限校驗(yàn)不通過(guò),我們就可以控制不顯示組件的內(nèi)容。
我們這里就是主要依賴(lài)這個(gè)過(guò)程來(lái)實(shí)現(xiàn)在頁(yè)面這一層面對(duì)權(quán)限進(jìn)行校驗(yàn)和控制。
代碼主要包含兩大部分,一個(gè)組件和一個(gè)用于權(quán)限控制的服務(wù)。
參考了Tapestry-Spring-Security的實(shí)現(xiàn),我也將組件命名為IfRole(當(dāng)然,我們也可以和Tapestry-Spring-Security一樣,也再生成一個(gè)IfLoggedIn組件)。權(quán)限控制的服務(wù)我命名為:AuthenticationService。
主要的實(shí)現(xiàn)思路:
將AuthenticationService申明為SessionState變量。這樣這個(gè)變量就可以在所有的頁(yè)面和組件之間很方便地共享了。一般情況下,是在登錄頁(yè)面對(duì)AuthenticationService進(jìn)行賦值,而在退出頁(yè)面清空AuthenticationService這個(gè)變量。
代碼(這部分代碼完全根據(jù)應(yīng)用的需求進(jìn)自行更改):
AuthenticationService的代碼:
public class AuthenticationService {
private List<String> privilegeList;
// privilegeList 的getter and setter

public boolean checkPermission(String ifNotGranted, String ifAllGranted,
String ifAnyGranted) {
if (((null == ifAllGranted) || "".equals(ifAllGranted))
&& ((null == ifAnyGranted) || "".equals(ifAnyGranted))
&& ((null == ifNotGranted) || "".equals(ifNotGranted))) {
return false;
}

if ((null != ifNotGranted) && !"".equals(ifNotGranted)) {
StringTokenizer st = new StringTokenizer(ifNotGranted, ",");
while (st.hasMoreTokens()) {
String value = st.nextToken();
if (privilegeList.contains(value)) {
return false;
}
}
}

if ((null != ifAllGranted) && !"".equals(ifAllGranted)) {
StringTokenizer st = new StringTokenizer(ifAllGranted, ",");
while (st.hasMoreTokens()) {
String value = st.nextToken();
if (!privilegeList.contains(value)) {
return false;
}
}
}

if ((null != ifAnyGranted) && !"".equals(ifAnyGranted)) {
StringTokenizer st = new StringTokenizer(ifAnyGranted, ",");
while (st.hasMoreTokens()) {
String value = st.nextToken();
if (privilegeList.contains(value)) {
return true;
}
}
return false;
}

return true;
}
}
IfRole的代碼(這個(gè)類(lèi)需要放在Components目錄下):
public class IfRole {
/**
* A comma-separated list of roles is supplied to one or more of the
* following parameters. If none are supplied, the default behavior is to
* forbid access. Behavior should be self-explanatory.
*/
@Parameter(required = false, defaultPrefix = "literal")
private String ifAllGranted;

@Parameter(required = false, defaultPrefix = "literal")
private String ifAnyGranted;

@Parameter(required = false, defaultPrefix = "literal")
private String ifNotGranted;

/**
* An alternate {@link Block} to render if the test parameter is false. The default, null, means
* render nothing in that situation.
*/
@Parameter(name = "else")
private Block elseBlock;

private boolean test;
@SessionState
private AuthenticationService auth;

private boolean checkPermission() {
return auth.checkPermission(ifNotGranted, ifAllGranted, ifAnyGranted);
}
void setupRender() {
test = checkPermission();
}

/**
* Returns null if the test method returns true, which allows normal
* rendering (of the body). If the test parameter is false, returns the else
* parameter (this may also be null).
*/
Object beginRender() {
return test ? null : elseBlock;
}

/**
* If the test method returns true, then the body is rendered, otherwise not. The component does
* not have a template or do any other rendering besides its body.
*/
boolean beforeRenderBody() {
return test;
}
}
本文主要介紹如何實(shí)現(xiàn)類(lèi)似于SpringSecurity的jsp tag的功能。在Tapestry中,利用Components實(shí)現(xiàn)這一點(diǎn)非常容易。
其基本原理是Tapestry5中一個(gè)頁(yè)面或者組件的渲染生成過(guò)程是基于一個(gè)狀態(tài)機(jī)和隊(duì)列完成的。這樣,渲染生成過(guò)程就被細(xì)分成了很多個(gè)小模塊,我們可以非常容易地覆寫(xiě)這些小模塊。具體內(nèi)容詳見(jiàn)官方文檔:http://tapestry.apache.org/tapestry5.1/guide/rendering.html。如果權(quán)限校驗(yàn)不通過(guò),我們就可以控制不顯示組件的內(nèi)容。
我們這里就是主要依賴(lài)這個(gè)過(guò)程來(lái)實(shí)現(xiàn)在頁(yè)面這一層面對(duì)權(quán)限進(jìn)行校驗(yàn)和控制。
代碼主要包含兩大部分,一個(gè)組件和一個(gè)用于權(quán)限控制的服務(wù)。
參考了Tapestry-Spring-Security的實(shí)現(xiàn),我也將組件命名為IfRole(當(dāng)然,我們也可以和Tapestry-Spring-Security一樣,也再生成一個(gè)IfLoggedIn組件)。權(quán)限控制的服務(wù)我命名為:AuthenticationService。
主要的實(shí)現(xiàn)思路:
將AuthenticationService申明為SessionState變量。這樣這個(gè)變量就可以在所有的頁(yè)面和組件之間很方便地共享了。一般情況下,是在登錄頁(yè)面對(duì)AuthenticationService進(jìn)行賦值,而在退出頁(yè)面清空AuthenticationService這個(gè)變量。
代碼(這部分代碼完全根據(jù)應(yīng)用的需求進(jìn)自行更改):
AuthenticationService的代碼:














































IfRole的代碼(這個(gè)類(lèi)需要放在Components目錄下):





















































示例:
1. 在登錄頁(yè)面:
@SessionState
private Authentication auth;
......
// if user name and password is valid:
auth.setPrivliegeList(.....);
2. 在需要權(quán)限控制的頁(yè)面模板中:
<t:ifRole ifAllGranted="admin">
administrator can see this block
</t:ifRole>