spring AOP 和自定义注解进行身份验证
Posted 小哥z
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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.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){ }
参考: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实现身份验证和springboot异常统一处理
spring boot spring security 基于自定义令牌的身份验证和自定义授权