基于SpringMVC拦截器和注解实现controller中访问权限控制
SpringMVC的拦截器HandlerInterceptorAdapter对应提供了三个preHandle,postHandle,afterCompletion方法。
- preHandle在业务处理器处理请求之前被调用;
- postHandle在业务处理器处理请求执行完成后,生成视图之前执行;
- afterCompletion在DispatcherServlet完全处理完请求后被调用,可用于清理资源等;
所以要想实现自己的权限管理逻辑,需要继承HandlerInterceptorAdapter并重写其三个方法。
一、自定义拦截器配置方法
- 在sping的xml配置中可以用<mvc:interceptors>和<mvc:interceptor>来配置拦截器类(实现HandlerInterceptorAdapter)
- 在javaConfig中配置通过WebMvcConfiguration的实现类配置拦截器类(实现HandlerInterceptorAdapter)
二、示例
2.1、javaconfig中配置SpringMVC示例
1、新建一个springboot项目auth-demo2
2、权限校验相关的注解
package com.dxz.authdemo2.web.auth; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) public @interface Permission { /** 检查项枚举 */ PermissionEnum[] permissionTypes() default {}; /** 检查项关系 */ RelationEnum relation() default RelationEnum.OR; } package com.dxz.authdemo2.web.auth; import java.io.PrintWriter; import java.lang.annotation.Annotation; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.springframework.web.method.HandlerMethod; import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; /** * 权限检查拦截器 */ @Component public class PermissionCheckInterceptor extends HandlerInterceptorAdapter { /** 权限检查服务 */ @Autowired private PermissionCheckProcessor permissionCheckProcessor; @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { //Class<?> clazz = handler.getClass(); Class<?> clazz = ((HandlerMethod)handler).getBeanType(); System.out.println("PermissionCheckInterceptor.preHandle()" + clazz); for(Annotation a : clazz.getAnnotations()){ System.out.println(a); } if (clazz.isAnnotationPresent(Permission.class)) { Permission permission = (Permission) clazz.getAnnotation(Permission.class); return permissionCheckProcessor.process(permission, request, response); } return true; } public boolean preHandle2(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("uid") == 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("未登录!"); out.flush(); out.close(); }else{ response.sendRedirect(request.getContextPath()+"/login"); } return false; } else { return true; } } } package com.dxz.authdemo2.web.auth; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.stereotype.Component; @Component public class PermissionCheckProcessor { public boolean process(Permission permission, HttpServletRequest request, HttpServletResponse response) { PermissionEnum[] permissionTypes = permission.permissionTypes(); try { String uid = request.getParameter("uid"); if ("duanxz".equals(uid)) { System.out.println("认证成功"); return true; } else { System.out.println("认证失败"); return false; } } catch (Exception e) { return false; } } } package com.dxz.authdemo2.web.auth; public enum PermissionEnum { DEVELOPER_VALID, DEVELOPER_FREEZE; } package com.dxz.authdemo2.web.auth; public enum RelationEnum { OR, AND; }
3、SpringMVC拦截器配置
package com.dxz.authdemo2.web.auth; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; @Configuration public class WebMvcConfiguration extends WebMvcConfigurerAdapter { @Autowired PermissionCheckInterceptor permissionCheckInterceptor; @Override public void addInterceptors(InterceptorRegistry registry) { // addPathPatterns 用于添加拦截规则 // excludePathPatterns 用户排除拦截 // 映射为 user 的控制器下的所有映射 registry.addInterceptor(permissionCheckInterceptor).addPathPatterns("/admin/*").excludePathPatterns("/index", "/"); super.addInterceptors(registry); } }
4、测试controller
package com.dxz.authdemo2.web; import javax.servlet.http.HttpServletRequest; import org.springframework.stereotype.Controller; import org.springframework.ui.ModelMap; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.servlet.ModelAndView; import com.dxz.authdemo2.web.auth.Permission; import com.dxz.authdemo2.web.auth.PermissionEnum; @Controller @RequestMapping("/admin") @Permission(permissionTypes = { PermissionEnum.DEVELOPER_VALID }) public class AppDetailController { @RequestMapping(value="/appDetail", method = RequestMethod.GET) public String doGet(ModelMap modelMap, HttpServletRequest httpServletRequest) { //1. 业务操作,此处省略 System.out.println("appDetail.htm 处理中..."); return "appDetail"; } } package com.dxz.authdemo2.web; import javax.servlet.http.HttpServletRequest; import org.springframework.stereotype.Controller; import org.springframework.ui.ModelMap; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import com.dxz.authdemo2.web.auth.Permission; import com.dxz.authdemo2.web.auth.PermissionEnum; @Controller @RequestMapping("index") public class IndexController { @RequestMapping(method = RequestMethod.GET) public void doGet(ModelMap modelMap, HttpServletRequest httpServletRequest) { System.out.println("index"); } }
cotroller中的jsp文件appDetail.jsp
<html> <h1>appDetail</h1> </html>
启动类:
package com.dxz.authdemo2; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.Bean; import org.springframework.web.servlet.ViewResolver; import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer; import org.springframework.web.servlet.config.annotation.EnableWebMvc; import org.springframework.web.servlet.view.InternalResourceViewResolver; @EnableWebMvc @EnableAutoConfiguration @SpringBootApplication public class AuthDemo2Application { public static void main(String[] args) { SpringApplication.run(AuthDemo2Application.class, args); } // 配置JSP视图解析器 @Bean public ViewResolver viewResolver() { InternalResourceViewResolver resolver = new InternalResourceViewResolver(); resolver.setPrefix("/WEB-INF/views/"); resolver.setSuffix(".jsp"); return resolver; } }
结果:
访问:http://localhost:8080/admin/appDetail?uid=duanxz2
访问:http://localhost:8080/admin/appDetail?uid=duanxz
2.2、xml中配置SpringMVC示例
首先在springmvc.xml中加入自己定义的拦截器我的实现逻辑PermissionCheckInterceptor,如下: