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>
可以发现页面请求被拦截了
参考: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