欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Spring AOP實現功能權限校驗功能的示例代碼

 更新時間:2017年12月07日 09:05:19   作者:後雪寒  
本篇文章主要介紹了Spring AOP實現功能權限校驗功能的示例代碼,小編覺得挺不錯的,現在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧

實現功能權限校驗的功能有多種方法,其一使用攔截器攔截請求,其二是使用AOP拋異常。

首先用攔截器實現未登錄時跳轉到登錄界面的功能。注意這里沒有使用AOP切入,而是用攔截器攔截,因為AOP一般切入的是service層方法,而攔截器是攔截控制器層的請求,它本身也是一個處理器,可以直接中斷請求的傳遞并返回視圖,而AOP則不可以。

1.使用攔截器實現未登錄時跳轉到登錄界面的功能

1.1 攔截器SecurityInterceptor

package com.jykj.demo.filter;
import java.io.PrintWriter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import com.alibaba.fastjson.JSON;
import com.jykj.demo.util.Helper;
import com.jykj.demo.util.Result;

public class SecurityInterceptor implements HandlerInterceptor{
 @Override
 public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
   throws Exception {
  System.out.println("SecurityInterceptor:"+request.getContextPath()+","+request.getRequestURI()+","+request.getMethod());
  HttpSession session = request.getSession();
  if (session.getAttribute(Helper.SESSION_USER) == null) {
   System.out.println("AuthorizationException:未登錄!"+request.getMethod());
   if("POST".equalsIgnoreCase(request.getMethod())){
    response.setContentType("text/html; charset=utf-8"); 
    PrintWriter out = response.getWriter(); 
    out.write(JSON.toJSONString(new Result(false,"未登錄!")));
    out.flush();
    out.close();
   }else{
    response.sendRedirect(request.getContextPath()+"/login"); 
   }
   return false;
  } else {
   return true;
  }
 }

 @Override
 public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
   ModelAndView modelAndView) throws Exception {
  // TODO Auto-generated method stub
 }

 @Override
 public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
   throws Exception {
  // TODO Auto-generated method stub
 }
}

1.2.spring-mvc.xml(攔截器配置部分)

<!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the ${webappRoot}/resources directory -->
 <mvc:resources mapping="/resources/**" location="/resources/" />
<mvc:interceptors>
  <mvc:interceptor>
   <mvc:mapping path="/*"/> <!-- 攔截/ /test /login 等等單層結構的請求 --> 
   <mvc:mapping path="/**/*.aspx"/><!-- 攔截后綴為.aspx的請求 -->
   <mvc:mapping path="/**/*.do"/><!-- 攔截后綴為 .do的請求 -->
   <mvc:exclude-mapping path="/login"/>
   <mvc:exclude-mapping path="/signIn"/>
   <mvc:exclude-mapping path="/register"/>
   <bean class="com.jykj.demo.filter.SecurityInterceptor">
   </bean>
  </mvc:interceptor>
 </mvc:interceptors>

這里需要特別說明:攔截器攔截的路徑最好是帶有后綴名的,否則一些靜態(tài)的資源文件不好控制,也就是說請求最好有一個統(tǒng)一的格式如 .do 等等,這樣匹配與過濾速度會非??臁H绻贿@樣,例如 用 /** 來攔截所有的請求,則頁面渲染速度會非常慢,因為資源文件也被攔截了。

2.使用AOP實現功能權限校驗

對于功能權限校驗也可以類似地用攔截器來實現,只不過會攔截所有的請求,對不需要權限校驗的請求沒有很好的過濾功能,所以采用AOP指定攔截需要校驗的方法的方式來實現之。

2.1 切面類 PermissionAspect

package com.jykj.demo.filter;
import java.io.IOException;
import java.lang.reflect.Method;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import com.jykj.demo.annotation.ValidatePermission;
import com.jykj.demo.exception.AccessDeniedException;
import com.jykj.demo.service.SysUserRolePermService;
/**
 * 事件日志 切面,凡是帶有 @ValidatePermission 以及@ResponseBody注解 控制器 都要進行 功能權限檢查,
 * 若無權限,則拋出AccessDeniedException 異常,該異常將請求轉發(fā)至一個控制器,然后將異常結果返回
 * @author Administrator
 *
 */
public class PermissionAspect {
 @Autowired
 SysUserRolePermService sysUserRolePermService;
 public void doBefore(JoinPoint jp) throws IOException{
  System.out.println(
    "log PermissionAspect Before method: " + jp.getTarget().getClass().getName() + "." + jp.getSignature().getName());
  Method soruceMethod = getSourceMethod(jp);
  if(soruceMethod!=null){
   ValidatePermission oper = soruceMethod.getAnnotation(ValidatePermission.class);
   if (oper != null) {
    int fIdx = oper.idx();
    Object[] args = jp.getArgs();
    if (fIdx>= 0 &&fIdx<args.length){
     int functionId = (Integer) args[fIdx];
     String rs = sysUserRolePermService.permissionValidate(functionId);
     System.out.println("permissionValidate:"+rs);
     if(rs.trim().isEmpty()){
      return ;//正常
     }
    }
   }
  }
  throw new AccessDeniedException("您無權操作!");
 }
 private Method getSourceMethod(JoinPoint jp){
  Method proxyMethod = ((MethodSignature) jp.getSignature()).getMethod();
  try {
   return jp.getTarget().getClass().getMethod(proxyMethod.getName(), proxyMethod.getParameterTypes());
  } catch (NoSuchMethodException e) {
   e.printStackTrace();
  } catch (SecurityException e) {
   e.printStackTrace();
  }
  return null;
 }
}

2.2自定義注解ValidatePermission

package com.jykj.demo.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
 * @Descrption該注解是標簽型注解,被此注解標注的方法需要進行權限校驗
 */
@Target(value = ElementType.METHOD)
@Retention(value = RetentionPolicy.RUNTIME)
@Documented
public @interface ValidatePermission {
 /**
  * @Description功能Id的參數索引位置 默認為0,表示功能id在第一個參數的位置上,-1則表示未提供,無法進行校驗
  */
 int idx() default 0;
}

說明: AOP切入的是方法,不是某個控制器請求,所以不能直接返回視圖來中斷該方法的請求,但可以通過拋異常的方式達到中斷方法執(zhí)行的目的,所以在before通知中,如果通過驗證直接return返回繼續(xù)執(zhí)行連接點方法,否則拋出一個自定義異常AccessDeniedException來中斷連接點方法的執(zhí)行。該異常的捕獲可以通過系統(tǒng)的異常處理器(可以看做控制器)來捕獲并跳轉到一個視圖或者一個請求。這樣就達到攔截請求的目的。所以需要配置異常處理器。

2.3 spring-mvc.xml(異常處理器配置,以及aop配置)

<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
  <!-- <property name="defaultErrorView" value="rediret:/error"></property> -->
  <property name="exceptionMappings">
   <props>
    <!--<prop key="com.jykj.demo.exception.AuthorizationException">redirect:/login</prop>-->
    <prop key="com.jykj.demo.exception.AccessDeniedException">forward:/accessDenied</prop>
   </props>
  </property>
 </bean>
<bean id="aspectPermission" class="com.jykj.demo.filter.PermissionAspect" />
 <!-- 對帶有@ValidatePermission和ResponseBody注解的controller包及其子包所有方法執(zhí)行功能權限校驗 --> 
 <aop:config proxy-target-class="true"> 
  <aop:aspect ref="aspectPermission"> 
   <aop:pointcut id="pc" 
    expression="@annotation(com.jykj.demo.annotation.ValidatePermission) 
    and @annotation(org.springframework.web.bind.annotation.ResponseBody) 
    and execution(* com.jykj.demo.controller..*.*(..)) " /> 
   <aop:before pointcut-ref="pc" method="doBefore"/> 
  </aop:aspect> 
 </aop:config>

2.4 注解需要進行功能校驗的控制器請求

@RequestMapping(value = "/moduleAccess.do", method = RequestMethod.POST, produces="text/html;charset=utf-8")
 @ResponseBody
 @ValidatePermission
 public String moduleAccess(int fid,String action,FrmModule module) {
  System.out.println("fid:"+fid+",action:"+action);
  int rs = -1;
  try{
   if(Helper.F_ACTION_CREATE.equals(action)){
    rs = moduleService.access(module,Helper.DB_ACTION_INSERT);
    //module.setModuleid(rs);
    module = moduleService.selectByPrimaryKey(rs);
   }else if(Helper.F_ACTION_EDIT.equals(action)){
    rs = moduleService.access(module,Helper.DB_ACTION_UPDATE);
    module = moduleService.selectByPrimaryKey(module.getModuleid());
   }else if(Helper.F_ACTION_REMOVE.equals(action)){
    rs = moduleService.access(module,Helper.DB_ACTION_DELETE);
   }else{
    return JSON.toJSONString(new Result(false,"請求參數錯誤:action"));
   }
  }catch(Exception e){
   e.printStackTrace();
   return JSON.toJSONString(new Result(false,"操作失敗,出現異常,請聯(lián)系管理員!"));
  }
  if(rs<0){
   return JSON.toJSONString(new Result(false,"操作失敗,請聯(lián)系管理員!"));
  }
  return JSON.toJSONString(new Result(true,module));
 }

2.5 異常處理器將請求轉發(fā)到的控制器請求 forward:/accessDenied

@RequestMapping(value = "/accessDenied",produces = "text/html;charset=UTF-8")
@ResponseBody
public String accessDenied(){
 return JSON.toJSONString(new Result(false,"您沒有權限對此進行操作!"));
}

2.6 請求校驗不通過時 由上述的控制器返回 結果本身

如下所示:

{"info":"您沒有權限對此進行操作!","success":false}

2.7 功能校驗service 示例

/**
  * 校驗當前用戶在某個模塊的某個功能的權限
  * @param functionId
  * @return 空字符串表示 有權限 ,否則是錯誤信息
  * @throws Exception 
  */
 public String permissionValidate(int functionId){
  Object o = request.getSession().getAttribute(Helper.SESSION_USER);
  //if(o==null) throw new AuthorizationException(); 
  SysUser loginUser= (SysUser)o;
  if(loginUser.getUserid() == 1) return "";
  try{
   return mapper.permissionValidate(loginUser.getUserid(),functionId);
  }catch(Exception ex){
   ex.printStackTrace();
   return "數據庫操作出現異常!";
  }
 }

說明: 這里僅僅是對帶有@ValidatePermission和@ResponseBody注解的controller包及其子包所有方法進行切入,這樣肯定是不夠通用的,應該是對帶有@ValidatePermission的方法進行切入,在切面類中通過判斷該方法是否有@ResponseBody注解來拋出不一樣的異常,若帶有@ResponseBody注解則拋出上述的異常返回json字符串,
否則,應該拋出另一個自定義異常然后將請求重定向到一個合法的視圖如error.jsp .

通過客戶端發(fā)送 /moduleAccess.do 請求,該請求對應的方法同時具有@ValidatePermission和@ResponseBody,并且有功能Id參數fid,這樣AOP可以切入該方法,執(zhí)行doBefore通知,通過功能參數fid,對它結合用戶id進行權限校驗,若校驗通過直接返回,程序繼續(xù)執(zhí)行,否則拋出自定義異常AccessDeniedException,該異常由系統(tǒng)捕獲(需要配置異常處理器)并發(fā)出請求 forward:/accessDenied ,然后對應的控制器 /accessDenied 處理該請求返回一個包含校驗失敗信息的json給客戶端。這樣發(fā)送 /moduleAccess.do 請求,如果校驗失敗,轉發(fā)到了/accessDenied請求,否則正常執(zhí)行。繞了這么一個大圈子才實現它。

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。

相關文章

  • Java中Calendar時間操作常用方法詳解

    Java中Calendar時間操作常用方法詳解

    這篇文章主要為大家詳細介紹了Java中Calendar時間操作常用方法,calendar中set方法和靜態(tài)屬性帶來的一些坑,感興趣的小伙伴們可以參考一下
    2016-05-05
  • mybatis框架入門學習教程

    mybatis框架入門學習教程

    MyBatis是一個支持普通SQL查詢,存儲過程和高級映射的優(yōu)秀持久層框架。這篇文章主要介紹了mybatis框架入門學習教程,需要的朋友可以參考下
    2017-02-02
  • 基于Java反射的map自動裝配JavaBean工具類設計示例代碼

    基于Java反射的map自動裝配JavaBean工具類設計示例代碼

    這篇文章主要給大家介紹了關于基于Java反射的map自動裝配JavaBean工具類設計的相關資料,文中通過示例代碼介紹的非常詳細,對大家學習或者使用java具有一定的參考學習價值,需要的朋友們下面來一起看看吧
    2018-10-10
  • Java從服務端下載Excel模板文件的兩種方法

    Java從服務端下載Excel模板文件的兩種方法

    這篇文章主要為大家詳細介紹了Java從服務端下載Excel模板文件的兩種方法,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-08-08
  • IDEA集成git和使用步驟的實現方法

    IDEA集成git和使用步驟的實現方法

    這篇文章主要介紹了IDEA集成git和使用步驟的實現方法,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-03-03
  • Spring?Boot中@Import三種使用方式實例詳解

    Spring?Boot中@Import三種使用方式實例詳解

    這篇文章主要介紹了Spring?Boot中@Import三種使用方式,主要有引入普通類,引入importSelector的實現類及引入importBeanDefinitionRegister的實現類,結合實例代碼給大家講解的非常詳細,需要的朋友可以參考下
    2022-11-11
  • 解決IDEA?JDK9沒有module-info.java的問題

    解決IDEA?JDK9沒有module-info.java的問題

    這篇文章主要介紹了解決IDEA?JDK9沒有module-info.java的問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-01-01
  • 詳解Java?token主流框架之JWT

    詳解Java?token主流框架之JWT

    JWT(JSON?Web?Token)是一種基于JSON格式的輕量級的、用于身份認證的開放標準,它通過在用戶和服務器之間傳遞一個安全的、可靠的、獨立的JSON對象來進行身份驗證和授權,本文將詳細給大家介紹Java?token主流框架之JWT,需要的朋友可以參考下
    2023-05-05
  • 如何在Spring中使用編碼方式動態(tài)配置Bean詳解

    如何在Spring中使用編碼方式動態(tài)配置Bean詳解

    這篇文章主要給大家介紹了關于如何在Spring中使用編碼方式動態(tài)配置Bean的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2018-05-05
  • JAVA提高第七篇 類加載器解析

    JAVA提高第七篇 類加載器解析

    這篇文章主要為大家詳細介紹了JAVA提高第七篇類加載器的相關資料,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-10-10

最新評論