基於AOP實現權限管理:通過shiro認證身份和模擬授權認證

有記錄和總結的學習,纔是完整的學習。不能總是低頭忙於平臺項目的開發,更重要的是在學習過程中思考和總結,顆粒歸倉,一年之計在於秋。

 

身份認證和授權認證是權限管理中的核心模塊。本文講講通過安全框架shiro進行身份認證和模擬授權認證,並可以看到授權之後的效果。

 

認證

登錄模塊,在完成用戶名和密碼的匹配基礎上,查詢該用戶具有的操作權限,緩存到本地。

該權限系統是基於角色的RBAC模型。所以查詢該用戶具有的操作權限,其實是根據該用戶所具有的角色查詢的。

而緩存到本地,是爲了提高性能。基於AOP的實現,是在Struts和頁面端之間做權限驗證,用大帥的話是“在它們之間插一槓子”。每次訪問Action之前,判斷該用戶是否具有這個操作權限,只有具有操作權限才能訪問Action。當用戶登錄時,如果把該用戶具有的操作權限全部查詢出來,緩存到本地,以後只需要根據這個緩存做判斷即可,這樣遠比每次都到數據庫中查詢的效率要高得多。

 

用例子來說明

使用admin賬號登錄


登錄時需要做的事情:

1、用戶名和密碼的匹配

2、查詢該用戶具有的操作權限,緩存到本地

 

根據權限,顯示頁面

admin用戶,具有admin角色。

admin角色,具有對“用戶管理”的“添加”、“刪除”、“修改”的權限

所以,admin登錄後可看到的頁面時這樣的


 

使用test賬號登錄


 

根據權限,顯示頁面

test用戶,具有test角色。

test角色,只有對“用戶管理”的“添加”的權限

所以,test登錄後可看到的頁面時這樣的(只能看到添加按鈕,並且也只能執行查詢和添加操作)


 

由圖可看出,權限控制粒度到了頁面菜單及頁面中按鈕。

 

看看是如何實現的

java開源的海洋,我們要做什麼,幾乎都有現成的東西供我們使用,當然基於AOP實現的權限管理也不例外,比如我們可以使用apache shirospring security。我用的是apacheshiro,如果想學習,可參考之前的系列文章。

 

Authentication認證

@Override
protectedAuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authcToken)
throwsAuthenticationException {
 
//驗證 驗證碼
//........
 
//驗證 用戶名和密碼
UsernamePasswordTokentoken = (UsernamePasswordToken)authcToken;
 
//從數據庫中查詢用戶用信息
Useruser = userService.get(token.getUsername());
 
ShiroUsershiroUser = new ShiroUser(user.getUsername(), user.getRealname());
 
if(user != null) {
returnnew SimpleAuthenticationInfo(shiroUser,user.getPassword(),
ByteSource.Util.bytes(user.getPassword()),getName());
}

這相當於對 登錄用戶信息的匹配過程,只是這個匹配過程交給了shiro去完成。

Authentication認證之後,會進行Authorization認證,進而只能進行自己權限範圍內的操作。

 

模擬Authorization認證

@Override
protectedAuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
System.out.println("由於加入了緩存, 此處只會load一次:doGetAuthorizationInfo.................");
 
//得到doGetAuthenticationInfo 方法中傳入的憑證
ShiroUsershiroUser = (ShiroUser) principals.fromRealm(getName()).iterator().next();
 
StringuserName = shiroUser.getName();
 
if(StringUtils.equals("admin",userName)) {
 
SimpleAuthorizationInfoinfo = new SimpleAuthorizationInfo();
 
//這個就是頁面中<shiro:hasRole>標籤的name的值
info.addRole("admin");
 
//這個就是頁面中<shiro:hasPermission> 標籤的name的值
info.addStringPermission("user:view");
info.addStringPermission("user:add");
info.addStringPermission("user:edit");
info.addStringPermission("user:delete");
 
returninfo;
 
} elseif(StringUtils.equals("test", userName)) {
SimpleAuthorizationInfoinfo = new SimpleAuthorizationInfo();
 
//這個就是頁面中<shiro:hasRole>標籤的name的值
info.addRole("test");
 
//這個就是頁面中<shiro:hasPermission> 標籤的name的值
info.addStringPermission("user:view");
info.addStringPermission("user:add");
 
returninfo;
} else{
returnnull;
}
}


這裏的permission字符串就是權限標識,比如useradd”表示對user模塊具有add的權限。在shiro標籤和shiro註解中,就是通過這個標識來完成驗證的。

 

 

shiro標籤在頁面中的應用

jsp中,通過shiro標籤實現對用戶管理模塊的權限控制

<divclass="panelBar">
<ulclass="toolBar">
<shiro:hasPermission name="user:add">
<li><aclass="add" href="${contextPath}/user/preAddUser"target="dialog" rel="lookup2organization_add"mask="true" width="530"height="330"><span>添加</span></a></li>
</shiro:hasPermission>
 
<shiro:hasPermission name="user:delete">
<li><atitle="確實要刪除這些記錄嗎?" target="selectedTodo"rel="userIds" href="${contextPath}/user/delManyUser"class="delete"><span>刪除</span></a></li>
</shiro:hasPermission>
 
<shiro:hasPermission name="user:edit">
<li><aclass="edit"href="${contextPath}/user/preUpdateUser?userId={sid_user}"rel="lookup2organization_edit" target="dialog"mask="true" warn="請選擇一個用戶"><span>修改</span></a></li>
</shiro:hasPermission>
</ul>
</div>


 

shiro註解在action中的應用

java代碼中,通過shiro註解實現對用戶管理模塊的權限控制

通過shiro標籤,的確可以讓用戶只看到自己權限範圍之內的頁面元素,但這並不是很安全,因爲頁面端的這些輸入信息可以別篡改,就像做輸入驗證一樣,在頁面通過js驗證後,在java代碼還需要驗證一樣。

 

// 添加用戶
@RequiresPermissions("user:add")
publicvoid  add(){        
Stringmsg;
 
try {
userService.save(user);
msg=AjaxObject.newOk("添加成功").setNavTabId("userListView").toString();
}catch (ServiceException e) {
msg =AjaxObject.newError(e.getMessage()).setNavTabId("userListView").setCallbackType("").toString();
}
outMsg(msg);
}

 

授權認證,這裏是使用靜態數據來模擬的,如果想得到數據庫中的數據,涉及到RoleModulPermissionOrganization模塊,而我們項目組正在開發之中。。。後文會有講解,敬請期待。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章