在幾乎所有的web應(yīng)用中都需要對(duì)訪問者(用戶)進(jìn)行權(quán)限管理, 因?yàn)槲覀兿M承╉撁嬷粚?duì)特定的用戶開放, 以及某些操作只有符合身份的用戶才能進(jìn)行。這之中涉及到了身份驗(yàn)證和權(quán)限管理. 只有單用戶系統(tǒng)和多用戶單權(quán)限系統(tǒng)才不需要權(quán)限管理。 在本文中, 使用了基于組的權(quán)限管理, 并在Spring框架下利用HandlerInterceptorAdapter和Hibernate進(jìn)行實(shí)現(xiàn)。 User的結(jié)構(gòu)是:
public class User { private int id; private String name; private String password; private Set<String> groups = new HashSet<String>(); } |
UserGroup表: user:intgroup:String使用聯(lián)合主鍵, 在 Java中沒有對(duì)應(yīng)的類。 Hibernate映射文件是:
<hibernate-mapping auto-import="true" default-lazy="false"> ?。糲lass name="net.ideawu.User" table="User"> <cache usage="read-write" /> ?。糹d name="id" column="id"> ?。糶enerator class="native"/> ?。?id> <property name="name" column="name"/> ?。紁roperty name="password" column="password"/> ?。約et name="groups" table="UserGroup" cascade="save-update" lazy="false"> ?。糼ey column="user" /> ?。糴lement column="`group`" type="string" /> ?。?set> </class> </hibernate-mapping> |
一切的身份驗(yàn)證交給一個(gè)繼承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); // 找出資源所需要的權(quán)限, 即組名 if(group == null){ // 所請(qǐng)求的資源不需要保護(hù). return true; } // 如果已經(jīng)登錄, 一個(gè)User實(shí)例被保存在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", "授權(quán)失敗! 你不在 <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的應(yīng)用上下文配置文件中設(shè)置:
<bean id="authorizeInterceptor" class="net.ideawu.AuthorizeInterceptor"> ?。紁roperty name="groupMappings"> <value> ?。?-- Attach URL paths to group --> /admin/*=admin </value> ?。?property> </bean> <bean id="simpleUrlHandlerMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping"> ?。紁roperty name="interceptors"> <list> ?。紃ef bean="authorizeInterceptor" /> </list> ?。?property> ?。紁roperty name="mappings"> ?。紇alue> /index.do=indexController /browse.do=browseController /admin/removeArticle.do=removeArticleController ?。?value> ?。?property> </bean> |
注意到"/admin/*=admin", 所以/admin目錄下的所有資源只有在admin組的用戶才能訪問, 這樣就不用擔(dān)心普通訪客刪除文章了。使用這種方法, 你不需要在removeArticleController中作身份驗(yàn)證和權(quán)限管理, 一切都交給AuthorizeInterceptor。
|