Springboot中自定义注解Annotation和拦截器实现权限管理


一般情况下请求的资源分三种:1.不需要登录就可以访问,2.登录后才能访问,3.登录后并且需要权限才能访问

本例中自定义的注解都是放在controller的方法上的,

@GreenPath对应第一种

@Auth对应第三种


1、pom.xml

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-aop</artifactId>
</dependency>


2、自定义注解

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * @description 权限验证的注解类
 * 
 * @Inherited:在使用此自定义注解时,如果注解在类上面时,子类会自动继承此注解,否则,子类不会继承此注解。这里一定要记住,使用Inherited声明出来的注解,只有在类上使用时才会有效,对方法,属性等其他无效。
 * @Target:表示此注解可以放置的位置。常见的位置有:TYPE=枚举或注解上,FIELD=字段上,METHOD=方法上,PARAMETER=函数形参列表中,CONSTRUCTOR=构造函数上,LOCAL_VARIABLE=局部变量上                                                                                                        等等其他位置。
 * @Retention:此注解的生命周期。常见的有:SOURCE=源码时期;CLASS=字节码时期(已编译);RUNTIME=运行时期,通常是用这个的时候要多。 
 * @Documentd:生成注解文档。
 */
@Inherited
@Target(ElementType.METHOD)
@Documented
@Retention(RetentionPolicy.RUNTIME)
public @interface Auth {  // 使用spring的@AliasFor别名

	String[] value() default "";// 权限标识

	boolean auth() default true;// 默认为鉴权
}
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
 
@Inherited
@Target(ElementType.METHOD)
@Documented
@Retention(RetentionPolicy.RUNTIME)
public @interface GreenPath {
}



3、拦截器

在controller中使用

@RequestMapping("/emailList")
@Auth(value={"email:emailList"})
public String emailList(HttpServletRequest request){
	return "emailList" ;
}


/**
 * 跳转到登录页面
 * @return
 */
@GreenPath
@RequestMapping(value={"/index","/",""})
public String indexPage(HttpSession session){
	
	return "login" ;
}


拦截器

import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import com.meihaocloud.manage.common.utils.EHcache;
import com.meihaocloud.manage.common.utils.IPUtils;
import com.meihaocloud.manage.common.utils.WebUtil;
import com.meihaocloud.manage.common.vo.Auth;
import com.meihaocloud.manage.common.vo.Constant;
import com.meihaocloud.manage.common.vo.ErrorEnum;
import com.meihaocloud.manage.common.vo.GreenPath;
import com.meihaocloud.manage.common.vo.Result;
import com.meihaocloud.manage.system.domain.SysUser;
import com.meihaocloud.manage.system.service.SysUserService;

/**
 * @author 008
 * @Date  2019年1月21日 下午10:41:38
 * @Desc  springmvc 拦截器,在MVCConfig 里面配置
 */
@Component
public class AuthInterruptor implements HandlerInterceptor {
	private static final Log log = LogFactory.getLog(AuthInterruptor.class) ;
	
	@Autowired
	private SysUserService userService ;
	
	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {
		
		/**
		 * 在此可以统计一些请求信息,referer,userAgent , ip等
		 */
		String uri = request.getRequestURI();
		String referer = request.getHeader("Referer") == null ? request.getHeader("referer") : request.getHeader("Referer");
		String ip = IPUtils.getClientIP(request);
		String userAgent = request.getHeader("User-Agent") == null ? request.getHeader("user-agent") : request.getHeader("User-Agent");
		
		StringBuffer buf = new StringBuffer() ;
		buf.append("uri=").append(uri).append("  |  ")
			.append("ip=").append(ip).append("  |  ")
			.append("referer=").append(referer).append("  |  ")
			.append("userAgent=").append(userAgent) ;
		
		log.info("request-info : "+ buf.toString());
		
		if(uri.endsWith("/error")){
			request.getRequestDispatcher("/404").forward(request, response) ;
			return false ;
		}
		
		// 如果不是映射到方法直接通过
        if (!(handler instanceof HandlerMethod)) {
            return true;
        }
        HandlerMethod handlerMethod = (HandlerMethod) handler;
        GreenPath greenPath = handlerMethod.getMethodAnnotation(GreenPath.class);
        if(greenPath != null) { // GreenPath , 不需要登录
        	return true ;
        }
        
		HttpSession session = request.getSession();
		SysUser user = (SysUser) session.getAttribute(Constant.sysUserName);
		if(user == null ){ //没有session,用户没有登录
			if(WebUtil.isAjaxRequest(request)){//ajax请求
				log.info(" isAjaxRequest  ... ");
				Result result = new Result(ErrorEnum.SESSION_TIMEOUT.getCode(),ErrorEnum.SESSION_TIMEOUT.getMsg());
				WebUtil.writeMsg(response, result);
			} else {
				log.info(" getRequestDispatcher  ... ");
				request.getRequestDispatcher("/manage").forward(request, response);
			}
			return false ;
		}
		// 经过研究发现,只有当GET请求是请求静态文件时(在spring配置文件里会配置静态文件的URI),
		// handler的实际类型会是DefaultServletHttpRequestHandler,此时强制转换就会报错。
		
		Auth auth = handlerMethod.getMethodAnnotation(Auth.class);
		if (auth != null && auth.auth()) {// 进行权限校验
			
			// 对当前访问的权限进行校验
			boolean b = authPermission(request, auth);
			if (!b) {
				log.info("无权访问资源 。。。");
				if(WebUtil.isAjaxRequest(request)){//ajax请求
					log.info(" isAjaxRequest  ... ");
					Result result = new Result(ErrorEnum.NO_PERMISSION.getCode(),ErrorEnum.NO_PERMISSION.getMsg());
					WebUtil.writeMsg(response, result);
				} else {
					log.info("getRequestDispatcher  ... ");
					request.getRequestDispatcher("/403").forward(request, response);
				}
				return false;
			}
		}
		return true;
	}

	@SuppressWarnings("unchecked")
	private boolean authPermission(HttpServletRequest request, Auth auth) {
		String[] action = auth.value();
		if(action.length == 0){ //加了@Auth ,但没有权限标识 , 返回false,鉴权失败
			log.info("加了@Auth,但没有权限标识符 ,   可能写漏了 " +  request.getRequestURI());
			return false ;
		}
		
		List<String> permission = null ;
		//获取所有权限
		Object obj = EHcache.get(Constant.permission);
		if(obj == null) {
			//获取所有权限 , 保存到EHCache
			// log.info("查询权限。。。");
			SysUser user = (SysUser) request.getSession().getAttribute(Constant.sysUserName);
			permission = userService.findAllPermission(user.getUserId());
			EHcache.put(Constant.permission, permission);
		}else {
			permission = (List<String>)obj ;
		}
		// log.info(Arrays.toString(action) + " , permission : " + permission);
		
		for (int i = 0; i < action.length; i++) {
			if(!permission.contains(action[i])){ // 有多个权限标识符时,   只有用户没有其中一个权限,鉴权失败,返回false
				return false ;
			}
		}
		return true;
	}

	
	/**
     * 该方法将在Controller执行之后,返回视图之前执行,modelAndView表示请求Controller处理之后返回的Model和View对象,所以可以在
     * 这个方法中修改modelAndView的属性,从而达到改变返回的模型和视图的效果。
     */
	@Override
	public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
			ModelAndView modelAndView) throws Exception {
	}

	@Override
	public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
			throws Exception {
	}

}


拦截器配置

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import com.meihaocloud.manage.common.Auth.AuthInterruptor;
/**
 * jdk8使用 implements WebMvcConfigurer, 接口可以有default方法
 * jdk8一下使用extends WebMvcConfigurerAdapter
 */
@Configuration
public class MVCConfig implements WebMvcConfigurer { //extends WebMvcConfigurerAdapter
	@Override
	public void addInterceptors(InterceptorRegistry registry) {
		registry
			.addInterceptor(new AuthInterruptor())
			.addPathPatterns("/**")
			.excludePathPatterns("/static/**")
			.excludePathPatterns("/css/**")
			.excludePathPatterns("/fonts/**")
			.excludePathPatterns("/img/**")
			.excludePathPatterns("/js/**")
			.excludePathPatterns("/layui/**")
			.excludePathPatterns("/rsa/**")
			.excludePathPatterns("/treeview/**")
			.excludePathPatterns("/wangEditor/**")
			.excludePathPatterns("/ueditor/**")
			;//登录页
	}
	
	/**
     * 配置静态资源
     */
	@Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/");
        registry.addResourceHandler("/templates/**").addResourceLocations("classpath:/templates/");
    }
	
}




springboot 注解 拦截器

2020.11.18 00:25

https://www.meihaocloud.com.com/306.html , 欢迎转载,请在文章页标出原文连接 !


Copyright © 2020 千夕网 联系站长

粤公网安备 44030302001408号 粤ICP备19099833号-1