一个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 和自定义注解进行身份验证的更多相关文章

  1. 利用Spring AOP和自定义注解实现日志功能

    Spring AOP的主要功能相信大家都知道,日志记录.权限校验等等. 用法就是定义一个切入点(Pointcut),定义一个通知(Advice),然后设置通知在该切入点上执行的方式(前置.后置.环绕等 ...

  2. Spring aop 拦截自定义注解+分组验证参数

    import com.hsq.common.enums.ResponseState;import com.hsq.common.response.ResponseVO;import org.aspec ...

  3. Spring Boot实现自定义注解

    在Spring Boot项目中可以使用AOP实现自定义注解,从而实现统一.侵入性小的自定义功能. 实现自定义注解的过程也比较简单,只需要3步,下面实现一个统一打印日志的自定义注解: 1. 引入AOP依 ...

  4. 运用Spring Aop,一个注解实现日志记录

    运用Spring Aop,一个注解实现日志记录 1. 介绍 我们都知道Spring框架的两大特性分别是 IOC (控制反转)和 AOP (面向切面),这个是每一个Spring学习视频里面一开始都会提到 ...

  5. ASP.NET Core 1.1 静态文件、路由、自定义中间件、身份验证简介

    概述 之前写过一篇关于<ASP.NET Core 1.0 静态文件.路由.自定义中间件.身份验证简介>的文章,主要介绍了ASP.NET Core中StaticFile.Middleware ...

  6. ASP.NET Core 1.0 静态文件、路由、自定义中间件、身份验证简介

    概述 ASP.NET Core 1.0是ASP.NET的一个重要的重新设计. 例如,在ASP.NET Core中,使用Middleware编写请求管道. ASP.NET Core中间件对HttpCon ...

  7. NET Core 1.1 静态文件、路由、自定义中间件、身份验证简介

    NET Core 1.1 静态文件.路由.自定义中间件.身份验证简介   概述 之前写过一篇关于<ASP.NET Core 1.0 静态文件.路由.自定义中间件.身份验证简介>的文章,主要 ...

  8. Spring Boot系列——AOP配自定义注解的最佳实践

    AOP(Aspect Oriented Programming),即面向切面编程,是Spring框架的大杀器之一. 首先,我声明下,我不是来系统介绍什么是AOP,更不是照本宣科讲解什么是连接点.切面. ...

  9. Spring Boot中自定义注解+AOP实现主备库切换

    摘要: 本篇文章的场景是做调度中心和监控中心时的需求,后端使用TDDL实现分表分库,需求:实现关键业务的查询监控,当用Mybatis查询数据时需要从主库切换到备库或者直接连到备库上查询,从而减小主库的 ...

随机推荐

  1. 访问 IIS 元数据库失败

    问题: 访问 IIS 元数据库失败.说明: 执行当前 Web 请求期间,出现未处理的异常.请检查堆栈跟踪信息,以了解有关该错误以及代码中导致错误的出处的详细信息. 异常详细信息: System.Web ...

  2. KM算法的应用

    HDU2255 模板     难度x HDU2282 思维     难度XXx HDU3722 模板     难度X HDU3395 模版 HDU1533 最小值模型 难度x HDU2853 HDU3 ...

  3. Java视频扩展知识 线程池的了解

     Java视频扩展知识   线程池的了解 1.简单介绍: Jdk1.5之后加入了java.util.concurrent包,这个包中主要介绍java中线程以及线程池的使用.为我们在开发中处理线程的 ...

  4. Sql Server合并多行询数据到一行:使用自连接、FOR XML PATH('')、STUFF或REPLACE函数

    示例表 tb 数据如下 id value ----- 1 aa 1 bb 2 aaa 2 bbb 2 ccc SELECT id, [val] = ( SELECT [value] + ',' FRO ...

  5. dmesg和addr2line 定位 segfault

    程序长时间运行崩溃,但是没有保存core dump消息.可以用下面的方法定位出程序出错位置: 1. 用dmesg查找出错的代码段地址 ip 000000000041ccec 发生错误时指令的地址, s ...

  6. 页面固定DIV层CSS代码

    有时候为了用户体验更好些,网页设计师会把网站导航放在一个固定的DIV层里面,不随滚动条滚动.本方法是利用CSS,position:fixed属性来固定层,fixed是特殊的absolute,即fixe ...

  7. vim-ultisnips补全功能失效,无法识别解决办法

    昨天又给vim配了一堆插件 发现了一个这个问题,vim的ultisnips插件不能用了! 首先,我先查看插件是否正常运行了 :script 从一堆正在运行插件里找到ultisnips的名字,说明插件正 ...

  8. vue搭建项目前奏曲——vue-cli

    vue-cli是快速构建这个单页应用的脚手架,这个可是官方的.官方给的建议,如果你是初次尝试Vue,哪就老老实实用普通的书写引入js文件,这里牵扯太多的东西,例如webpack.Node.js.npm ...

  9. Linux入门(10)——Ubuntu16.04使用pip3和pip安装numpy,scipy,matplotlib等第三方库

    安装Python3第三方库numpy,scipy,matplotlib: sudo apt install python3-pip pip3 install numpy pip3 install sc ...

  10. 高性能 Java 缓存库 — Caffeine

    http://www.baeldung.com/java-caching-caffeine 作者:baeldung 译者:oopsguy.com 1.介绍 在本文中,我们来看看 Caffeine - ...