權限攔截
思路解析
一.閱讀本篇之前,可以先提前瞭解小編在之前寫過的登錄攔截的那篇博客。有助於更好的理解本篇權限攔截。
二.權限攔截思路解析:獲取用戶訪問路徑uri
1.首先遍歷所有的權限判斷其中是否包含該uri,如果不包含則不需要攔截(比如:userController/login )比如這個登錄方法的路徑訪問時就不需要攔截,即我們只攔截所有權限裏的路徑,因此在數據庫編寫路權限徑時注意區分大小寫,及不能漏掉要攔截的權限路徑。如果包含則需要判斷該用戶是否有對應權限。
2.當所有的權限包含該uri時,判斷該用戶的權限列表是否有對應權限。如有則說明該用戶訪問的路徑他有權利去訪問和之後的相關操作,不需要攔截。如果用戶權限列表沒有該uri說明用戶不具備此權限,需要攔截該用戶。
3.當需要攔截該用戶時,就和登錄攔截很相似,需要判斷是不是ajax請求並返回相應提示信息給用戶。
準備工作
如上所述,權限攔截需要如下“工具”:
1.permissionListAll 所有的權限列表
public List<Permission> queryPermissionList() {
return permissionRepository.findAll();
}
通過JpaRepository接口自帶的查詢方法查出所有權限列表。
2.permissionListByUserId 用戶的權限列表
@Query(nativeQuery = true,value = "select DISTINCT tp.* FROM t_user_role_new tur LEFT JOIN t_role_permission_new trp ON tur.roleId = trp.roleId LEFT JOIN t_permission_new tp on trp.permissionId = tp.id where tur.userId = ?1")
List<Permission> findPermissionListByUserId(Integer userId);
爲了提高性能小編是通過三表聯查獲得用戶權限:通過用戶id查詢,用戶_角色關聯表左聯角色_權限關聯表左聯權限表,通過三表聯查查詢到該用戶id對應的所有權限。
3.String uri = request.getRequestURI(); 用戶訪問的地址欄路徑。(URI,統一資源標誌符(Uniform Resource Identifier, URI),表示的是web上每一種可用的資源,如 HTML文檔、圖像、視頻片段、程序等都由一個URI進行定位的。)
具體實現
新建一個PermissionInterceptor基礎HandlerInterceptorAdapter並重寫preHandle方法。
package com.fh.interceptor;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import com.fh.model.Permission;
import com.fh.util.JsonUtil;
public class PermissionInterceptor extends HandlerInterceptorAdapter{
@SuppressWarnings("unchecked")
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
HttpSession session = request.getSession();
/*
* 登陸成功後login方法已經將permissionListByUserId,
* permissionListAll放入session裏,所以我們只需要從session中取出即可
*/
List<Permission> permissionListByUserId = (List<Permission>) session.getAttribute("permissionListByUserId");
List<Permission> permissionListAll = (List<Permission>) session.getAttribute("permissionListAll");
String uri = request.getRequestURI();// 類似於userController/addUser
if(StringUtils.isBlank(uri)) {//如果uri爲空則不需要攔截
return true;
}
boolean contains = false;
/*
* 立一個flag(contains) 若flag(contains)爲true表明所有權限包含該uri,
* 一旦包含即可break提高代碼性能。
*/
if(permissionListAll != null && permissionListAll.size() > 0) {
for (Permission permission : permissionListAll) {
if(StringUtils.isNotBlank(permission.getUrl()) && uri.contains(permission.getUrl())) {
contains = true;
break;
}
}
}
if(contains == false) {//若flag(contains)爲false表明所有權限列表如果不包含則不需要攔截
return true;
}else {//表明所有權限permissionListAll包含該uri,就需要進一步驗證用戶權限是否包含
boolean hasPermission = false;
/*
* 當所有的權限包含該uri時,判斷該用戶的權限列表是否有對應權限。
* 如有則說明該用戶訪問的路徑他有權利去訪問和之後的相關操作,不需要攔截。
* 如果用戶權限列表沒有該uri說明用戶不具備此權限,需要攔截該用戶。
*
*/
if(permissionListByUserId != null && permissionListByUserId.size() > 0) {
for (Permission permission : permissionListByUserId) {
if(StringUtils.isNotBlank(permission.getUrl()) && uri.contains(permission.getUrl())) {
hasPermission = true;
break;
}
}
}
if(hasPermission == true) {//在permissionListAll裏邊,且有用戶權限。允許用戶訪問。
return true;
}else {//用戶權限列表沒有該uri說明用戶不具備此權限,需要攔截該用戶
String header = request.getHeader("X-Requested-With");
//根據請求頭部判斷是不是ajax請求
if(StringUtils.isNotBlank(header) && header.equals("XMLHttpRequest")) {
//是ajax請求就要給前端頁面一個信號,在前端頁面判斷後可以再彈出提示信息,跳到指定頁面
Map<String, Object> result = new HashMap<String, Object>();
result.put("code", 2000);
JsonUtil.outJson(response, result);
}else {//不是ajax請求可以直接重定向到指定頁面
response.sendRedirect(request.getServletContext().getContextPath()+"/no-permission.jsp");
}
return false;
}
}
}
}
springMVC.xml配置
<mvc:interceptor>
<mvc:mapping path="/**" />
/*
*配置白名單,放開靜態資源
*/
<mvc:exclude-mapping path="/js/**" />
<mvc:exclude-mapping path="/bootstrap/**" />
<bean class="com.fh.interceptor.PermissionInterceptor"></bean>
</mvc:interceptor>
寫在最後
本篇爲小編和人理解所作,如有錯誤請聯繫小編進行修改或刪除。