aop方式校验登录的方式

由于登录是通用的模块, 所以需要写一个公共的类可以方便的调用

如果APP所有的应用都是需要登录才能进行访问的话,此时可以使用过滤器进行编写, 在访问之前拦截接口,校验是否有登录, 也可以使用SpringSecurity框架来进行实现

以下使用aop方式实现全局校验

第一步自定义注解类作为切点

package com.fish.pojo.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;

/**
 * 校验客户端登录标记
 */
@Documented//是 java 在生成文档时,是否显示该注解的开关。
@Retention(RetentionPolicy.RUNTIME)//注解不仅被保存到class文件中,jvm加载class文件之后,仍然存在
@Target({ElementType.TYPE,ElementType.METHOD})//用于描述方法
public @interface CheckClientOline {

}

第二步编写aop的管道接口(可以多实现该接口)

package com.fish.aop;

import org.aspectj.lang.JoinPoint;

/**
 * 切面管道接口
 */
public interface AopChannel {
	/**
	 * 执行
	 * @param joinPoint
	 * @throws Exception 
	 */
	public void exec(JoinPoint joinPoint) throws Exception;
}

实现切面接口(可以校验管理员等其他验证身份)

package com.fish.aop.channel;

import com.fish.aop.AopChannel;
import com.fish.common.aop.AopUtils;
import com.fish.common.security.SecurityUtils;
import com.fish.common.security.entity.LoginUser;
import com.fish.common.servlet.ServletUtils;
import com.fish.pojo.annotation.CheckClientOline;
import com.fish.pojo.exception.OffLineException;
import org.aspectj.lang.JoinPoint;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;

/**
 * 校验用户端用户是否在线
 */
public class CheckClientOlineChannel implements AopChannel{
	@Override
	public void exec(JoinPoint joinPoint) throws Exception {
		Class<?> type = AopUtils.getType(joinPoint);
		HttpServletRequest request = ServletUtils.getRequest();

		CheckClientOline checkOline = type.getAnnotation(CheckClientOline.class);

		LoginUser user = SecurityUtils.getHeaderUser(request, LoginUser.class);
		if (user!=null){
			request.setAttribute(SecurityUtils.APP_USER, user);
		}

		if(checkOline == null) {
			Method method = AopUtils.getMethod(joinPoint);
			checkOline = method.getAnnotation(CheckClientOline.class);
		}

		if(checkOline == null)
			return;

		if(user == null)
			throw new OffLineException("登录失效");
		if(user.getUserStatus() != LoginUser.getUserStatusDict().get("用户端"))
			throw new OffLineException("只有用户才可以访问此权限");
		request.setAttribute(SecurityUtils.APP_USER, user);
	}

}

编写aop切面配置类

package com.fish.config;

import com.alibaba.fastjson.JSON;
import com.fish.aop.AopChannel;
import com.fish.aop.channel.CheckAdminOlineChannel;
import com.fish.aop.channel.CheckClientOlineChannel;
import com.fish.aop.channel.CheckClientSignChannel;
import com.fish.common.servlet.ServletUtils;
import com.fish.dao.redis.RedissonDao;
import lombok.extern.slf4j.Slf4j;
import org.apache.log4j.Logger;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.InputStreamSource;
import org.springframework.stereotype.Component;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.List;


/**
 * aop切面
 * 
 * @author chenwei
 * @date 2019年6月28日 下午3:50:37
 */
@Aspect
@Component
public class ControllerAopConfig {

	private static final Logger log = Logger.getLogger(ControllerAopConfig.class);

	@Value("${controller.log.show.enable}")//是否需要打印日志的配置
	private boolean isShowControllerLog;

	@Autowired
	private RedissonDao redisson;
	private List<AopChannel> aopchannels = new ArrayList<AopChannel>(9) {
		private static final long serialVersionUID = -689595264093084192L;
		{
			add(new CheckAdminOlineChannel());//管理员
			add(new CheckClientOlineChannel());//客户端用户
			add(new CheckClientSignChannel());//签名
		}
	};
	
	/**
	 * 指定切入的路径
	 * @author chenwei
	 * @date 2019年6月28日 下午3:52:17
	 */
	@Pointcut("execution(public * com.fish.controller..*.*(..))")
	public void controllerAop() {
	}
	
	/**
	 * 在目标业务方法执行之前执行
	 * @param joinPoint
	 * @throws Exception
	 */
	@Before("controllerAop()")
	public void doBefore(JoinPoint joinPoint) throws Exception {
		printLog(joinPoint);
        //执行校验的方法
		for (AopChannel aopChannel : aopchannels) {
			aopChannel.exec(joinPoint);
		}
	}
	
	/**
	 * 在目标业务方法返回结果之后执行
	 * @param ret
	 * @throws Throwable
	 */
	 @AfterReturning(returning = "ret",pointcut = "controllerAop()")
	 public void doAfterReturning(Object ret) throws Throwable {
		 redisson.unlock();
	 }

	/**
	 * 打印日志
	 * @param joinPoint
	 */
	private void printLog(JoinPoint joinPoint) {
		if (!isShowControllerLog){
			return;
		}

		try {
			HttpServletRequest request = ServletUtils.getRequest();
			String methodName = joinPoint.getSignature().getName();
			String className = joinPoint.getTarget().getClass().getName();
			log.info("=====================new Request======================");
			log.info("-----logger aop"+log);
			log.info("Request URL:"+request.getRequestURL());

			Object[] args = joinPoint.getArgs();
			log.info("params: ");
			if (args!=null){
				for (Object arg : args) {
					if (
							arg instanceof ServletResponse ||
									arg instanceof ServletRequest ||
									arg instanceof InputStreamSource
					){
						//不打印
						continue;
					}else {
						log.info("        "+ JSON.toJSONString(arg));
					}
				}
			}

			log.info("UserKey:"+ request.getHeader("UserKey"));
			log.info("Class Method:"+className+"."+methodName+"()"+"From IP:"+request.getRemoteAddr());
			System.out.println(log);
			log.info("======================================================");
		}catch (Exception e){
//			e.printStackTrace();
		}
	}
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值