一个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. Ionic3学习笔记(二)主题化

    本文为原创文章,转载请标明出处 目录 CSS实用属性 文本相关 位置相关 padding & margin 自定义颜色 平台样式 覆写Ionic Sass变量 RTL支持 1. CSS实用属性 ...

  2. Thirft框架快速入门

    Thrift介绍1.什么是thrift?thrift早期由facebook内部团队开发,主要用于实现跨语言间的方法调用,属于远程方法调用的一种,后开源纳入apache中,成为了apache thrif ...

  3. php根据ip段以及子网掩码,判断某ip是否处于某子网下

        为了检测客户端ip是否位于指定的网络里(如防火墙过滤有时候需要用到这个技术),有如下方法: 1.第一种 public function netMatch($client_ip, $server ...

  4. ASP.NET没有魔法——ASP.NET MVC 与数据库大集合

    ASP.NET没有魔法——ASP.NET与数据库 ASP.NET没有魔法——ASP.NET MVC 与数据库之MySQL ASP.NET没有魔法——ASP.NET MVC 与数据库之ORM ASP.N ...

  5. asp.net调用Lodop实现页面打印或局部打印,可进行打印设置或预览

    <%@ Page Language="C#" AutoEventWireup="true" CodeFile="WebPrint.aspx.cs ...

  6. sqlite3基本相关使用

    闲来无事,复习和总结了一下之前学习到的关于sqlite3数据库的相关知识: [1] sqlite3的安装:1.离线安装:sudo dpkg -i *.deb2.在线安装:sudo apt-get in ...

  7. Cosmos OpenSSD--greedy_ftl1.2.0(三)

    我们来假设模拟一个小型的模型来分析写和垃圾回收的过程 假设只有一个die,4个block,每个block4个page,每个page8KB 那么PageMap就是Page[0][0]到Page[0][1 ...

  8. 正则和grep——再做正则就去死

    grep 文本过滤工具 基本正则表达式 grep 语法 基本正则表达式的元字符 次数匹配 位置锚定 分组 扩展正则表达式 基本正则表达式的元字符 次数匹配 位置锚定 分组 或者 grep的介绍 lin ...

  9. 用source语句引用mysql文件的细节注意

    今天在使用 mysql数据库的时候,创建 数据表的时候出现了很多的小问题,今天一天花费了大量的时间去解决这些问题.首先就是一些小的细节,在文本编辑器上编辑好了SQL语句,然后转移到mysql的命令行中 ...

  10. 写了一个bug,最后却变成了feature,要不要修呢?

    事情是这样子的,前不久接到一个需求,为一个游戏开发礼包码功能 通常一款游戏运营期间会搞各种各样的活动吸引玩家,其中最常见的就是发放礼包,  玩家可以通过礼包码兑换礼包. 用礼包码兑换礼包有个一限制,游 ...