spring AOP 和自定义注解进行身份验证
一个SSH的项目(springmvc+hibernate),需要提供接口给app使用。首先考虑的就是权限问题,app要遵循极简模式,部分内容无需验证,用过滤器不能解决某些无需验证的方法 所以最终选择用AOP 解决。大致思路是使用自定义注解,在需要权限控制的方法前(controller层)使用注解然后使用AOP拦截访问的方法,判断当前用户是否登录了(判断是否携带了登录之后获取到的 token ),从而决定是否拦截。
开启切面代理
<!--aop配置,基于类的代理 -->
<!-- <aop:aspectj-autoproxy proxy-target-class="true"/>-->
<aop:aspectj-autoproxy/>
注意:1、一定要放在spring的配置文件中,不要单独新建一个文件
2、proxy-target-class属性值决定是基于接口的还是基于类的代理被创建。如果proxy-target-class 属性值被设置为true,那么基于类的代理将起作用(这时需要cglib库)。如果proxy-target-class属值被设置为false或者这个属性被省略,那么标准的JDK 基于接口的代理将起作用。
编写一个自定义注解
@Retention(RetentionPolicy.RUNTIME)//注解会在class中存在,运行时可通过反射获取
@Target(ElementType.METHOD)//目标是方法
@Documented
public @interface LoginRequired{ }
ElementType.MeTHOD 表示该自定义注解可以用在方法上RetentionPolicy.RUNTIME 表示该注解在代码运行时起作用
可以在自定义注解中加入一些默认方法
定义切面类验证权限
@Component
@Aspect
public class TokenInterceptor { private static final Logger logger = Logger.getLogger(TokenInterceptor.class); @Resource
private BllUserService bllUserService; @Pointcut("@annotation(org.jeecgframework.core.annotation.LoginRequired)")
public void serviceAspect() {
}
//环绕通知(特别适合做权限系统)
//@Before
@Around("serviceAspect()")
public Object checkPermission(ProceedingJoinPoint joinPoint) throws Throwable{
AjaxJson json=new AjaxJson();
// String methodName = joinPoint.getSignature().getName();
// Object target = joinPoint.getTarget();
// Method method = getMethodByClassAndName(target.getClass(), methodName); //得到拦截的方法
Object[] args = joinPoint.getArgs();
HttpServletRequest request=(HttpServletRequest)args[0];
if(!validate(request)){
//request.setAttribute("message", "您没有执行该操作权限");
json.setMsg("您没有执行该操作权限");
json.setSuccess(false);
return json;
}
return joinPoint.proceed();
}
private boolean validate(HttpServletRequest request)throws Exception {
// String token=request.getParameter("token");//根据前端传值进行修改
String token=request.getHeader("token");
if(StringUtil.isEmpty(token)){ }
Map<String, Object> resultMap=Jwt.validToken(token);
TokenState state=TokenState.getTokenState((String)resultMap.get("state"));
switch (state) {
case VALID:
//取出payload中数据,放入到request作用域中
request.setAttribute("data", resultMap.get("data"));
break;
case EXPIRED://暂时没做
case INVALID:
return false;
}
return true; } public void postHandle(HttpServletRequest request,
HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
} public void afterCompletion(HttpServletRequest request,
HttpServletResponse response, Object handler, Exception ex)
throws Exception {
}
@Aspect放在类头上,把这个类作为一个切面。
@Compenent注解标识其为Spring管理Bean,而@Aspect注解不能被Spring自动识别并注册为Bean,必须通过@Component注解来完成
注:这儿用了JWT做token验证,感兴趣的同学自行百度
TOKEN验证类
/**
* 校验token是否合法,返回Map集合,集合中主要包含 state状态码 data鉴权成功后从token中提取的数据
* 该方法在过滤器中调用,每次请求API时都校验
* @param token
* @return Map<String, Object>
*/
public static Map<String, Object> validToken(String token) {
Map<String, Object> resultMap = new HashMap<String, Object>();
try {
JWSObject jwsObject = JWSObject.parse(token);
Payload payload = jwsObject.getPayload();
JWSVerifier verifier = new MACVerifier(SECRET); if (jwsObject.verify(verifier)) {
JSONObject jsonOBj = payload.toJSONObject();
// token校验成功(此时没有校验是否过期)
resultMap.put("state", TokenState.VALID.toString());
// 若payload包含ext字段,则校验是否过期
if (jsonOBj.containsKey("ext")) {
long extTime = Long.valueOf(jsonOBj.get("ext").toString());
long curTime = new Date().getTime();
// 过期了
if (curTime > extTime) {
resultMap.clear();
resultMap.put("state", TokenState.EXPIRED.toString());
}
}
resultMap.put("data", jsonOBj); } else {
// 校验失败
resultMap.put("state", TokenState.INVALID.toString());
} } catch (Exception e) {
//e.printStackTrace();
// token格式不合法导致的异常
resultMap.clear();
resultMap.put("state", TokenState.INVALID.toString());
}
return resultMap;
}
配置拦截器
@RequestMapping(params = "physicalList")
@ResponseBody
@LoginRequired
public AjaxJson getPhysicalList(HttpServletRequest request){ }
测试
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="initial-scale=1, maximum-scale=1">
<title></title>
</head>
<body> <button type="button" onclick="getdata()">测试页面</button><br/>
<script type="text/javascript" src="js/jquery.min.js" ></script>
<script>
var token="123";
function getdata(){
$.ajax({
type:"post",
dataType:"json",
url:"",
headers:{
token:token//将token放到请求头中
},
// beforeSend: function(request) {
// request.setRequestHeader("token", token);
// },
success:function(data){
console.log(data);
$('body').append(JSON.stringify(data)); },
});
}
</script>
</body>
</html>

可以发现页面请求被拦截了
参考:http://blog.csdn.net/caomiao2006/article/details/51287206
http://www.jianshu.com/p/576dbf44b2ae
http://www.scienjus.com/restful-token-authorization/
spring AOP 和自定义注解进行身份验证的更多相关文章
- 利用Spring AOP和自定义注解实现日志功能
Spring AOP的主要功能相信大家都知道,日志记录.权限校验等等. 用法就是定义一个切入点(Pointcut),定义一个通知(Advice),然后设置通知在该切入点上执行的方式(前置.后置.环绕等 ...
- Spring aop 拦截自定义注解+分组验证参数
import com.hsq.common.enums.ResponseState;import com.hsq.common.response.ResponseVO;import org.aspec ...
- Spring Boot实现自定义注解
在Spring Boot项目中可以使用AOP实现自定义注解,从而实现统一.侵入性小的自定义功能. 实现自定义注解的过程也比较简单,只需要3步,下面实现一个统一打印日志的自定义注解: 1. 引入AOP依 ...
- 运用Spring Aop,一个注解实现日志记录
运用Spring Aop,一个注解实现日志记录 1. 介绍 我们都知道Spring框架的两大特性分别是 IOC (控制反转)和 AOP (面向切面),这个是每一个Spring学习视频里面一开始都会提到 ...
- ASP.NET Core 1.1 静态文件、路由、自定义中间件、身份验证简介
概述 之前写过一篇关于<ASP.NET Core 1.0 静态文件.路由.自定义中间件.身份验证简介>的文章,主要介绍了ASP.NET Core中StaticFile.Middleware ...
- ASP.NET Core 1.0 静态文件、路由、自定义中间件、身份验证简介
概述 ASP.NET Core 1.0是ASP.NET的一个重要的重新设计. 例如,在ASP.NET Core中,使用Middleware编写请求管道. ASP.NET Core中间件对HttpCon ...
- NET Core 1.1 静态文件、路由、自定义中间件、身份验证简介
NET Core 1.1 静态文件.路由.自定义中间件.身份验证简介 概述 之前写过一篇关于<ASP.NET Core 1.0 静态文件.路由.自定义中间件.身份验证简介>的文章,主要 ...
- Spring Boot系列——AOP配自定义注解的最佳实践
AOP(Aspect Oriented Programming),即面向切面编程,是Spring框架的大杀器之一. 首先,我声明下,我不是来系统介绍什么是AOP,更不是照本宣科讲解什么是连接点.切面. ...
- Spring Boot中自定义注解+AOP实现主备库切换
摘要: 本篇文章的场景是做调度中心和监控中心时的需求,后端使用TDDL实现分表分库,需求:实现关键业务的查询监控,当用Mybatis查询数据时需要从主库切换到备库或者直接连到备库上查询,从而减小主库的 ...
随机推荐
- Ubuntu16.04 install eclipse-jee-oxygen-R-linux-gtk-x86_64
下面如何在Ubuntu16.04 下面怎么下载Java EE并创建在桌面快捷上下载Java EE:eclipse下载Java EE官网:http://www.eclipse.org/downloads ...
- python 发送邮件,未完
def send_mail(): try: print "send mail..." # handle = smtplib.SMTP('smtp.163.com', 25) # h ...
- nodejs+express-实现文件上传下载管理的网站
Nodejs+Express-实现文件上传下载管理的网站 项目Github地址(对你有帮助记得给星哟):https://github.com/qcer/updo 后端:基于nodejs的express ...
- python xml sendEmail
使用python进行发送邮件,研究的主要是用smtplib这个包,具体代码如下,eg: #!/usr/bin/python #coding=utf-8 import smtplib from emai ...
- AlexNet 网络详解及Tensorflow实现源码
版权声明:本文为博主原创文章,未经博主允许不得转载. 1. 图片数据处理 2. 卷积神经网络 2.1. 卷积层 2.2. 池化层 2.3. 全链层 3. AlexNet 4. 用Tensorflow搭 ...
- 量化投资:第8节 A股市场的回测
作者: 阿布 阿布量化版权所有 未经允许 禁止转载 abu量化系统github地址(欢迎+star) 本节ipython notebook 之前的小节回测示例都是使用美股,本节示例A股市场的回测. 买 ...
- NIO FileChannel
NIO提供了比传统的文件访问更好的访问方法,NIO有两个优化的方法:一个是 FIleChannel.transferTo FileChannel.transferFrom,另一个是FileChanne ...
- quartz 定时任务
面试问到了,回答的不是很全面,丢人呀.研究过,用过的东西. 2年多没用,回忆一下: Quartz任务调度框架和Spring集成使用:定时执行一些任务 核心:调度器.任务和触发器. 调度器负责调度各个任 ...
- LeetCode 292. Nim Game (取物游戏)
You are playing the following Nim Game with your friend: There is a heap of stones on the table, eac ...
- 关于IntelliJ IDEA删除项目
刚开始使用IDEA . 自己创建项目玩,结果发现IDEA无法删除,我也是醉了,Eclipse直接右键 -> delete -> 勾选删除源文件 就删除了,IDEA死活没有找到删除选项... ...