在幾乎所有的web應用中都需要對訪問者(用戶)進行權限管理, 因為我們希望某些頁面只對特定的用戶開放, 以及某些操作只有符合身份的用戶才能進行。這之中涉及到了身份驗證和權限管理. 只有單用戶系統和多用戶單權限系統才不需要權限管理。
在本文中, 使用了基于組的權限管理, 并在spring框架下利用handlerinterceptoradapter和hibernate進行實現。
user的結構是:
public class user {
private int id;
private string name;
private string password;
private set<string> groups = new hashset<string>();
}
usergroup表:
user:intgroup:string使用聯合主鍵, 在java中沒有對應的類。
hibernate映射文件是:
<hibernate-mapping auto-import="true" default-lazy="false">
<class name="net.ideawu.user" table="user">
<cache usage="read-write" />
<id name="id" column="id">
<generator class="native"/>
</id>
<property name="name" column="name"/>
<property name="password" column="password"/>
<set name="groups" table="usergroup" cascade="save-update" lazy="false">
<key column="user" />
<element column="`group`" type="string" />
</set>
</class>
</hibernate-mapping>
一切的身份驗證交給一個繼承handlerinterceptoradapter的類來做:
import org.springframework.web.servlet.handler.handlerinterceptoradapter;
import org.springframework.web.util.urlpathhelper;
import org.springframework.util.antpathmatcher;
import org.springframework.util.pathmatcher;
...
public class authorizeinterceptor extends handlerinterceptoradapter {
private urlpathhelper urlpathhelper = new urlpathhelper();
private pathmatcher pathmatcher = new antpathmatcher();
private properties groupmappings;
/** * attach url paths to group. */
public void setgroupmappings(properties groupmappings) {
this.groupmappings = groupmappings;
}
public boolean prehandle(httpservletrequest request, httpservletresponse response, object handler) throws exception {
string url = urlpathhelper.getlookuppathforrequest(request);
string group = lookupgroup(url);
// 找出資源所需要的權限, 即組名
if(group == null){
// 所請求的資源不需要保護.
return true;
}
// 如果已經登錄, 一個user實例被保存在session中.
user loginuser = (user)request.getsession().getattribute("loginuser");
modelandview mav = new modelandview("system/authorizeerror");
if(loginuser == null){
mav.addobject("errormsg", "你還沒有登錄!");
throw new modelandviewdefiningexception(mav);
}else{
if(!loginuser.getgroups().contains(group)){
mav.addobject("errormsg", "授權失敗! 你不在 <b>" + group + "</b> 組!");
throw new modelandviewdefiningexception(mav);
} return true;
}
}
/* * 查看
org.springframework.web.servlet.handler.abstracturlhandlermapping.lookuphandler()
* ant模式的最長子串匹配法.
*/
private string lookupgroup(string url){
string group = groupmappings.getproperty(url);
if (group == null) {
string bestpathmatch = null;
for (iterator it = this.groupmappings.keyset().iterator();it.hasnext();) {
string registeredpath = (string) it.next();
if (this.pathmatcher.match(registeredpath, url) && (bestpathmatch == null || bestpathmatch.length() <= registeredpath.length())) {
group = this.groupmappings.getproperty(registeredpath);
bestpathmatch = registeredpath;
}
}
}
return group;
}
}
下面我們需要在spring的應用上下文配置文件中設置:
<bean id="authorizeinterceptor" class="net.ideawu.authorizeinterceptor">
<property name="groupmappings">
<value>
<!-- attach url paths to group -->
/admin/*=admin
</value>
</property>
</bean>
<bean id="simpleurlhandlermapping" class="org.springframework.web.servlet.handler.simpleurlhandlermapping">
<property name="interceptors">
<list>
<ref bean="authorizeinterceptor" /> </list>
</property>
<property name="mappings">
<value>
/index.do=indexcontroller /browse.do=browsecontroller /admin/removearticle.do=removearticlecontroller
</value>
</property>
</bean>
注意到"/admin/*=admin", 所以/admin目錄下的所有資源只有在admin組的用戶才能訪問, 這樣就不用擔心普通訪客刪除文章了。使用這種方法, 你不需要在removearticlecontroller中作身份驗證和權限管理, 一切都交給authorizeinterceptor。