1. 程式人生 > >shiro真正專案中的實戰應用核心程式碼!!!

shiro真正專案中的實戰應用核心程式碼!!!

歡迎轉載!!!請註明出處!!!

說道shiro的學習之路真是相當坎坷,網上好多人發的帖子全是簡單的demo樣例,核心程式碼根本沒有,在學習過程中遇到過N多坑。

經過自己的努力,終於整出來了,等你整明白之後發現,確實沒那麼難,只是沒人告訴你,自己去想向確實不好辦,只能通過看原始碼加上自己猜想,不斷嘗試。

直接看主題。我就直接說受權這了,不說認證登入了,這種帖子n多個,我要說的是真正的核心程式碼!!!含金量超高!!!歡迎轉載!請註明出處!!!

首先看先自定義的Realm:

        /**
	 * 授權查詢回撥函式, 進行鑑權但快取中無使用者的授權資訊時呼叫.
	 */
	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
		SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
		//獲取用的id
		String userId = ((User)principals.getPrimaryPrincipal()).getUserId();
		//查詢對應使用者的角色集合
		List<RoleR> roleList=userService.getRoleList(userId);
		List<Menu> menuList=null;
		List<String> roleAllList = new ArrayList<String>();
		List<String> resourceList = new ArrayList<String>();
		for (RoleR role : roleList) {
			roleAllList.add(role.getRoleId()+"");
			//查詢對應角色的對應許可權集合
			menuList=userService.getMenuList(role.getRoleId());
			for (Menu menu : menuList) {
				if(StringUtils.isNotBlank(menu.getPermission())){
					resourceList.add(menu.getPermission());
				}
			}
		}
		//賦角色
		info.addRoles(roleAllList);
		//賦許可權
		info.addStringPermissions(resourceList);
		return info;
	}
可能都見過這個方法,但是你們知道什麼時候呼叫嗎?

我來揭祕:

@RequestMapping("getProductList")
	@ResponseBody
	@RequiresPermissions("product:list")//這是是核心
	public String getProductList(Integer offset,Integer limit,Product product){
		page.setStrat(offset);
		page.setPagecount(limit);
		page.setObj(product);
		productService.getProductList(page);
		Map map=new HashMap();
		map.put("total", page.getPagesumcount());
		map.put("rows", page.getList());
		Gson gson=new Gson();
		String str=gson.toJson(map);
		return str;
	}
只要你訪問後臺的方法上面有
@RequiresPermissions
這個註解,那麼此時shiro回去訪問
doGetAuthorizationInfo
這個方法,然後回去驗證當前使用者是否有次許可權,如果沒有就回拋會授權異常

但是使用者是看不到的,怎麼辦?這時候就要用另外一個方法,進行全域性異常捕獲。

沒錯就是用
@ControllerAdvice和@ExceptionHandler(value={UnauthorizedException.class})
    @ResponseStatus(HttpStatus.UNAUTHORIZED)這些註解結合使用。用來捕獲所有控制層拋來的制定異常

然後在轉到制定的錯誤提示頁面提示使用者相關錯誤資訊,如果你們用了aop攔截了controller並且是環繞通知,這時候有個坑,是捕獲不到錯誤的。

    /**
     * 沒有許可權 異常
     * <p/>
     * 後續根據不同的需求定製即可
     */
    @ExceptionHandler(value={UnauthorizedException.class})
    @ResponseStatus(HttpStatus.UNAUTHORIZED)
    public ModelAndView processUnauthenticatedException(NativeWebRequest request, UnauthorizedException e){
        System.out.println("-----------------------------------------------------");
        ModelAndView mv = new ModelAndView();
        mv.addObject("errorInfo", e);
        mv.setViewName("unauthorized");
        return mv;
    }


原因因為aop攔截後丟擲了更大的異常,而你捕獲的是未授權,所以要重新丟擲未授權


不僅僅是許可權控制,也可以角色控制,一樣的用法

接下來就是前臺js的許可權控制


		<div id="toolbar" class="btn-group">
		<shiro:hasPermission name="product:insert">
			<button id="btn_add" type="button" class="btn btn-primary" onclick="addProduct()">
				<span class="glyphicon glyphicon-plus" aria-hidden="true"></span>新增
			</button>
		</shiro:hasPermission>
		<shiro:hasPermission name="product:deletes">
			<button id="btn_delete" type="button" class="btn btn-warning" onclick="delProductAll()">
				<span class="glyphicon glyphicon-remove" aria-hidden="true"></span>刪除
			</button>
		</shiro:hasPermission>
		<shiro:hasPermission name="product:insert">
			<button id="btn_delete" type="button" class="btn btn-success" onclick="updateAllProduct()">
				<span class="glyphicon glyphicon-remove" aria-hidden="true"></span>批量修改圖片
			</button>
		</shiro:hasPermission>
		<shiro:hasPermission name="product:excel">
			<button id="btn_delete" type="button" class="btn btn-success" onclick="exportExcel()">
				<span class="glyphicon glyphicon-remove" aria-hidden="true"></span>匯出Excel
			</button>
		</shiro:hasPermission>
		<shiro:hasPermission name="product:xml">
			<button id="btn_delete" type="button" class="btn btn-success" onclick="exportXml()">
				<span class="glyphicon glyphicon-remove" aria-hidden="true"></span>匯出Xml
			</button>
		</shiro:hasPermission>
		</div>

如果當前使用者符合這些許可權,按鈕就可以顯示,前天要引入shiro標籤庫

<%@ taglib prefix="shiro" uri="http://shiro.apache.org/tags" %> 

下面是我的許可權表的大致結構:

這是Realm的下載地址: