基于SpringMVC拦截器和注解实现controller中访问权限控制

SpringMVC的拦截器HandlerInterceptorAdapter对应提供了三个preHandle,postHandle,afterCompletion方法。

  1. preHandle在业务处理器处理请求之前被调用;
  2. postHandle在业务处理器处理请求执行完成后,生成视图之前执行;
  3. afterCompletion在DispatcherServlet完全处理完请求后被调用,可用于清理资源等;

所以要想实现自己的权限管理逻辑,需要继承HandlerInterceptorAdapter并重写其三个方法。

一、自定义拦截器配置方法

  1. 在sping的xml配置中可以用<mvc:interceptors>和<mvc:interceptor>来配置拦截器类(实现HandlerInterceptorAdapter)
  2. 在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,如下:

复制代码
<!--配置拦截器, 多个拦截器,顺序执行 -->  
<mvc:interceptors>    
    <mvc:interceptor>    
        <!-- 匹配的是url路径, 如果不配置或/**,将拦截所有的Controller -->  
        <mvc:mapping path="/" />  
        <mvc:mapping path="/user/**" />  
        <mvc:mapping path="/test/**" />  
        <bean class="com.dxz.authdemo2.web.auth.PermissionCheckInterceptor"></bean>    
    </mvc:interceptor>  
    <!-- 当设置多个拦截器时,先按顺序调用preHandle方法,然后逆序调用每个拦截器的postHandle和afterCompletion方法 -->  
</mvc:interceptors> 
复制代码

  

 
 

SpringMVC的拦截器HandlerInterceptorAdapter对应提供了三个preHandle,postHandle,afterCompletion方法。

  1. preHandle在业务处理器处理请求之前被调用;
  2. postHandle在业务处理器处理请求执行完成后,生成视图之前执行;
  3. afterCompletion在DispatcherServlet完全处理完请求后被调用,可用于清理资源等;

所以要想实现自己的权限管理逻辑,需要继承HandlerInterceptorAdapter并重写其三个方法。

一、自定义拦截器配置方法

  1. 在sping的xml配置中可以用<mvc:interceptors>和<mvc:interceptor>来配置拦截器类(实现HandlerInterceptorAdapter)
  2. 在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,如下:

复制代码
<!--配置拦截器, 多个拦截器,顺序执行 -->  
<mvc:interceptors>    
    <mvc:interceptor>    
        <!-- 匹配的是url路径, 如果不配置或/**,将拦截所有的Controller -->  
        <mvc:mapping path="/" />  
        <mvc:mapping path="/user/**" />  
        <mvc:mapping path="/test/**" />  
        <bean class="com.dxz.authdemo2.web.auth.PermissionCheckInterceptor"></bean>    
    </mvc:interceptor>  
    <!-- 当设置多个拦截器时,先按顺序调用preHandle方法,然后逆序调用每个拦截器的postHandle和afterCompletion方法 -->  
</mvc:interceptors> 
复制代码

  

猜你喜欢

转载自www.cnblogs.com/exmyth/p/10742392.html