spring AOP 和自定义注解进行身份验证

本文内容纲要:

- 开启切面代理

- 编写一个自定义注解

- 定义切面类验证权限

- TOKEN验证类

- 配置拦截器

- 测试

一个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>

Image

可以发现页面请求被拦截了

参考:http://blog.csdn.net/caomiao2006/article/details/51287206

http://www.jianshu.com/p/576dbf44b2ae

http://www.scienjus.com/restful-token-authorization/

本文内容总结:开启切面代理,编写一个自定义注解,定义切面类验证权限,TOKEN验证类,配置拦截器,测试,

原文链接:https://www.cnblogs.com/magic101/p/7732016.html

以上是 spring AOP 和自定义注解进行身份验证 的全部内容, 来源链接: utcz.com/z/296907.html

回到顶部