There are many ways to implement functional permission verification. One is to use an interceptor to intercept requests, and the other is to use AOP to throw exceptions.
First, use an interceptor to realize the function of jumping to the login interface when it is not logged in. Note that AOP is not used here, but interceptors are intercepted, because AOP generally enters the service layer method, and the interceptor intercepts the request from the controller layer. It is also a processor itself, which can directly interrupt the passing of the request and return the view, while AOP cannot.
1. Use the interceptor to realize the function of jumping to the login interface when it is not logged in
1.1 Interceptor SecurityInterceptor
package com.jykj.demo.filter;import java.io.PrintWriter;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;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: Not logged in!" +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,"Not logged in!"))); 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 (interceptor configuration part)
<!-- 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="/**"/> <!-- Intercept requests for single-layer structures such as /test /login --> <mvc:mapping path="/**/*.aspx"/><!-- Intercept requests with suffix .aspx --> <mvc:mapping path="/**/*.do"/><!-- Intercept requests with suffix .do --> <mvc:exclude-mapping path="/login"/> <mvc:exclude-mapping path="/signIn"/> <mvc:exclude-mapping path="/register"/> <bean> </bean> </mvc:interceptor> </mvc:interceptors>It is necessary to specify here: the path intercepted by the interceptor is preferably with a suffix name, otherwise some static resource files will be difficult to control, that is, the request should have a unified format such as .do, etc., so that the matching and filtering speed will be very fast. If this is not the case, for example using /** to intercept all requests, the page rendering speed will be very slow because the resource file is also intercepted.
2. Use AOP to implement functional permission verification
Function permission verification can also be implemented similarly with an interceptor, but it will intercept all requests and does not have a good filtering function for requests that do not require permission verification. Therefore, it is implemented by using AOP to specify the method of intercepting the required verification.
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;/** * Event log section, any controller with @ValidatePermission and @ResponseBody annotation must perform functional permission checks. * If there is no permission, an AccessDeniedException exception is thrown, which forwards the request to a controller, and then returns the exception result* @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 sorryMethod = getSourceMethod(jp); if(soruceMethod!=null){ ValidatePermission opera = sorryMethod.getAnnotation(ValidatePermission.class); if (oper != null) { int fIdx = opera.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 ;//Normal} } } } throw new AccessDeniedException("You do not have permission to operate!"); } 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 Custom annotation 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 This annotation is a tag-type annotation. The method annotated by this annotation requires permission verification*/@Target(value = ElementType.METHOD)@Retention(value = RetentionPolicy.RUNTIME)@Documentedpublic @interface ValidatePermission { /** * @Description The parameter index position of the function Id is 0 by default, indicating that the function id is at the position of the first parameter, and -1 means that it is not provided and verification cannot be performed */ int idx() default 0;}Note: AOP cuts into a method, not a request from a controller, so it cannot directly return to the view to interrupt the request of the method, but the purpose of interrupting the execution of the method can be achieved by throwing exceptions. Therefore, in the before notification, if you directly return the connection point method is returned through verification, otherwise a custom exception AccessDeniedException will be thrown to interrupt the execution of the connection point method. The capture of the exception can be captured and redirected to a view or a request through the system's exception handler (that can be regarded as a controller). This achieves the purpose of intercepting the request. Therefore, an exception processor needs to be configured.
2.3 spring-mvc.xml (exception processor configuration, and aop configuration)
<bean> <!-- <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" /> <!-- Perform function permission verification on all methods of the controller package and its subpackage with @ValidatePermission and ResponseBody annotations--> <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 Annotation of controller requests that require functional verification
@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,"Request parameter error: action")); } } catch(Exception e){ e.printStackTrace(); return JSON.toJSONString(new Result(false,"The operation failed, an exception occurred, please contact the administrator!")); } if(rs<0){ return JSON.toJSONString(new Result(false,"The operation failed, please contact the administrator!")); } return JSON.toJSONString(new Result(true,module)); }2.5 The controller request forward:/accessDenied by the exception handler forward:/accessDenied
@RequestMapping(value = "/accessDenied",produces = "text/html;charset=UTF-8")@ResponseBodypublic String accessDenied(){ return JSON.toJSONString(new Result(false,"You do not have permission to operate on this!"));}2.6 When the request verification fails, the above controller returns the result itself.
As shown below:
{"info":"You do not have permission to operate on this!","success":false}
2.7 Function verification service example
/** * Verify the permission of the current user in a certain function of a module* @param functionId * @return An empty string indicates permission, otherwise it is an error message* @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 "Exception occurred in database operation!"; } } Note: Here we are just cutting into all methods of the controller package and its subpackage with @ValidatePermission and @ResponseBody annotations. This is definitely not universal enough. We should cut into the method with @ValidatePermission. In the section class, we will throw different exceptions by judging whether the method has @ResponseBody annotations. If the above exception is thrown, the above exception is thrown and returned to the json string.
Otherwise, another custom exception should be thrown and the request is redirected to a legal view such as error.jsp.
Send /moduleAccess.do request through the client. The corresponding method of the request has both @ValidatePermission and @ResponseBody, and has the function Id parameter fid, so that AOP can enter the method, execute doBefore notification, and use the function parameter fid to verify it permissions in combination with the user id. If the verification is passed, the program will continue to execute it. Otherwise, a custom exception AccessDeniedException is thrown. The exception is caught by the system (the exception handler needs to be configured) and a request is issued forward:/accessDenied, and the corresponding controller/accessDenied handles the request and returns a json containing the verification failure information to the client. This sends the /moduleAccess.do request. If the verification fails, forward the /accessDenied request, otherwise it will be executed normally. It was realized after going around such a big circle.
The above is all the content of this article. I hope it will be helpful to everyone's learning and I hope everyone will support Wulin.com more.