什么是 AOP

首先我们先了解一下什么是AOP,AOP(Aspect Orient Programming),直译过来就是面向切面编程。AOP是一种编程思想,是面向对象编程(OOP)的一种补充。面向对象编程将程序抽象成各个层次的对象,而面向切面编程是将程序抽象成各个切面。那么本次实现的鉴权功能就是将鉴权代码作为切面织入到需要使用鉴权功能的代码上.以下功能需要使用SpringAop的通知功能与自定义注解,对SpringAop及自定义注解不熟悉的同学可以先去了解一下

基于SpringAop通知实现鉴权

实现思路

基本实现思路就是

  • 编写自定义注解作为切点
  • 然后在切面类中编写鉴权逻辑代码
  • 最后在需要鉴权的方法前添加自定义注解

这样在调用添加了鉴权注解的方法时就是先执行鉴权切面类的代码来进行鉴权

鉴权切点类代码示例

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Authority {
AuthorityType value() default AuthorityType.Validate; FuncIdType[] funcIdTypes() default {}; ModuleIdType[] moduleIdTypes() default {};
}

鉴权切面类代码示例

@Aspect
@Component
public class AuthorityAspect {
private static Logger logger = LoggerFactory.getLogger(SystemLogAspect.class); // 日志切点
@Pointcut("@annotation(com.hzjd.jdmp.annotation.Authority)")
public void executeService() {
}
// 验证是否具有该功能的权限
private boolean validateFunc(FuncIdType[] funcIdTypes) {
HttpSession session = ActionStackManager.getSession();
SessionStackData sessionStackData = SessionStackData.getSessionStackData(session);
if (sessionStackData.getRl() == null) {
return false;
}
for (int i = 0; i < funcIdTypes.length; i++) {
if (sessionStackData.getRl().haveRight(funcIdTypes[i])) {
return true;
}
}
return false;
} // 验证是否具有该模块的权限
private boolean validateModule(ModuleIdType[] moduleIdTypes) {
HttpSession session = ActionStackManager.getSession();
SessionStackData sessionStackData = SessionStackData.getSessionStackData(session);
if (sessionStackData.getRm() == null) {
return false;
}
for (int i = 0; i < moduleIdTypes.length; i++) {
if (sessionStackData.getRm().haveRight(moduleIdTypes[i])) {
return true;
}
}
return false;
} private Object toError(Boolean responseBody) {
if (responseBody) {
Map<String, Object> map = new HashMap<String, Object>();
map.put("success", false);
map.put("msg", "您没有操作此功能的权限");
String json = JsonUtil.toJsonObject(map).toString();
HttpServletResponse response = ActionStackManager.getResponse();
response.setCharacterEncoding("UTF-8");
response.setContentType("application/json; charset=utf-8");
try {
response.getWriter().write(json);
} catch (IOException e) {
e.printStackTrace();
}
return null;
} else {
return "errauth";
}
} private Object toLogin() {
HttpServletResponse response = ActionStackManager.getResponse();
String loginUrl = ActionStackManager.getRequest().getContextPath() + "/index";
String str = "<script language='javascript'>alert('会话过期,请重新登录');" + "window.top.location.href='" + loginUrl
+ "';</script>";
response.setContentType("text/html;charset=UTF-8");// 解决中文乱码
PrintWriter writer;
try {
writer = response.getWriter();
writer.write(str);
writer.flush();
} catch (IOException e) {
}
return null;
} @Around(value = "executeService()")
public Object doAroundAdvice(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
Signature signature = proceedingJoinPoint.getSignature();
MethodSignature methodSignature = (MethodSignature) signature;
Method targetMethod = methodSignature.getMethod();
Method realMethod = proceedingJoinPoint.getTarget().getClass()
.getDeclaredMethod(signature.getName(), targetMethod.getParameterTypes());
Authority authority = targetMethod.getAnnotation(Authority.class);
Class<?> clazz = targetMethod.getClass();
logger.debug("realMethod:" + realMethod.getName());
logger.debug("realMethod Class:" + realMethod.getDeclaringClass().getSimpleName());
boolean pass = false;
boolean responseBody = targetMethod.isAnnotationPresent(ResponseBody.class);
if (clazz != null && targetMethod != null) {
if (authority != null) {
if (AuthorityType.NoValidate == authority.value()) {
logger.debug("标记为不验证,放行");
// 标记为不验证,放行
pass = true;
} else if (AuthorityType.NoAuthority == authority.value()) {
logger.debug("不验证权限,验证是否登录");
// 不验证权限,验证是否登录
pass = BaseSearchForm.getLoginUser() != null;
if (!pass) {
return toLogin();
}
} else {
if (BaseSearchForm.getLoginUser() != null) {
logger.debug("正在验证权限");
if (authority.funcIdTypes() != null && authority.funcIdTypes().length > 0) {
pass = validateFunc(authority.funcIdTypes());
}
if (!pass) {
if (authority.moduleIdTypes() != null && authority.moduleIdTypes().length > 0) {
pass = validateModule(authority.moduleIdTypes());
}
}
} else {
return toLogin();
}
}
}
}
if (!pass) {
return toError(responseBody);
} else {
logger.debug("验证权限通过");
}
Object obj = proceedingJoinPoint.proceed();
return obj;
}
}

实现方法示例

@RequestMapping(value = "/updateOwerPwd")
@SystemLogAnnotation
@Authority(value = AuthorityType.NoAuthority)
public String updateOwerPwd(ModelMap model, HttpServletRequest request, HttpServletResponse response)
throws Exception {
ActionStackManager.initNewData(model, request, response);
try {
HttpSession session = ActionStackManager.getRequest().getSession();
SysUser sysUser = SessionStackData.getSessionStackData(session).getSysUser();
if (sysUser == null) {
session.invalidate();
return forward("login");
}
sysUser = sysUserService.findById(sysUser.getUserid());
if (sysUser == null) {
session.invalidate();
return forward("login");
}
String oldpassword = getRequestParameter("oldpwd");
String password = getRequestParameter("pwd1");
if (!sysUser.getPassword().equals(MD5Utils.getBASE64MD5(oldpassword)))
return forwardError("旧密码输入不正确,修改密码失败!");
sysUser.setPassword(MD5Utils.getBASE64MD5(password));
if (!sysUserService.update(sysUser))
return forwardError("修改密码失败!");
return forward("includes/main");
} catch (Exception e) {
logError(e);
return forwardError(e);
} finally {
ActionStackManager.removeThreadData();
}
}

基于SpringAop的鉴权功能的更多相关文章

  1. 基于token机制鉴权架构

    常见的鉴权方式有两种,一种是基于session,另一种是基于token方式的鉴权,我们来浅谈一下两种 鉴权方式的区别. 两种鉴权方式对比 session 安全性:session是基于cookie进行用 ...

  2. [原创]SpringSecurity控制授权(鉴权)功能介绍

    1.spring security 过滤器链 ​ spring security中的除了用户登录校验相关的过滤器,最后还包含了鉴权功能的过滤器,还有匿名资源访问的过滤器链,相关的图解如下: 2.控制授 ...

  3. YAPI接口自动鉴权功能部署详解

    安装准备 以下操作,默认要求自己部署过yapi,最好是部署过yapi二次开发环境. 无论是选择在线安装或者是本地安装,都需要安装client工具. 1.yapi-cli:npm install yap ...

  4. 「快学springboot」集成Spring Security实现鉴权功能

    Spring Security介绍 Spring Security是Spring全家桶中的处理身份和权限问题的一员.Spring Security可以根据使用者的需要定制相关的角色身份和身份所具有的权 ...

  5. Session, Token, OAuth 鉴权那些事儿

    鉴权那些事 整体思路 无论什么样的服务, Web 服务总是不能绕开鉴权这个话题的, 通过有效的鉴权手段来保护网站数据, 来为特定用户提供服务. 整体来说, 有三种方式: Session-Cookie ...

  6. 认证鉴权与API权限控制在微服务架构中的设计与实现(四)

    引言: 本文系<认证鉴权与API权限控制在微服务架构中的设计与实现>系列的完结篇,前面三篇已经将认证鉴权与API权限控制的流程和主要细节讲解完.本文比较长,对这个系列进行收尾,主要内容包括 ...

  7. EasyNVR摄像机网页H5全平台无插件直播流媒体播放服务二次开发之接口鉴权示例讲解

    背景需求 EasyNVR的使用者应该都清楚的了解到,EasyNVR一个强大的功能就是可以进行全平台的无插件直播.主要原因在于rtsp协议的视频流(默认是需要插件才可以播放的)经由EasyNVR处理可以 ...

  8. 深入理解k8s中的访问控制(认证、鉴权、审计)流程

    Kubernetes自身并没有用户管理能力,无法像操作Pod一样,通过API的方式创建/删除一个用户实例,也无法在etcd中找到用户对应的存储对象. 在Kubernetes的访问控制流程中,用户模型是 ...

  9. 【Spring Cloud & Alibaba 实战 | 总结篇】Spring Cloud Gateway + Spring Security OAuth2 + JWT 实现微服务统一认证授权和鉴权

    一. 前言 hi,大家好~ 好久没更文了,期间主要致力于项目的功能升级和问题修复中,经过一年时间的打磨,[有来]终于迎来v2.0版本,相较于v1.x版本主要完善了OAuth2认证授权.鉴权的逻辑,结合 ...

随机推荐

  1. LC算法技巧总结(二):双指针和滑动窗口技巧

    我把双指针技巧再分为两类,一类是「快慢指针」,一类是「左右指针」.前者解决主要解决链表中的问题,比如典型的判定链表中是否包含环:后者主要解决数组(或者字符串)中的问题,比如二分查找. 一.快慢指针的常 ...

  2. 一文带你了解Sql优化

    我们后台开发人员每天都难免与数据库打交道,那么你在写sql语句的时候有注重到自己sql的效率吗?当你sql查询速度很慢的时候你有想过是你的sql语句造成的吗?看完这篇文章,我相信你会对sql优化有了一 ...

  3. flask学习,关于4.2.2 输出HTML代码报错的问题

    问题描述 今天在学习第四章表单时,创建form实例时访问实例属性时报错,即以下代码出错 form = LoginForm() print(form.username) RuntimeError: Wo ...

  4. archaius(3) 配置管理器

    基于上一节介绍的配置源,我们来继续了解配置管理器.配置源只是抽象了配置的获取来源,配置管理器是基于配置源的基础上对这些配置项进行管理.配置管理器的主要功能是将配置从目标位置加载到内存中,并且管理内存配 ...

  5. 类加载器ClassLoader

    上篇文章说到,Class类可以通过一个类的全限定名去加载类,那么底层是如何去加载的呢?这就是我们今天要聊的类加载器ClassLoader,其可以通过一个类的全限定名来获取描述此类的二进制字节流,也即是 ...

  6. JVM的整体结构

    整个jvm的运行流程图如上所示,首先需要进行加载class文件,然后使用类加载子系统将class翻译解析导入内存,在内存中分别导入到对应的运行时数据区,然后执行引擎开始执行,对于需要的数据在对应的区域 ...

  7. Java高级开发必会的50个性能优化的细节(珍藏版)

      在JAVA程序中,性能问题的大部分原因并不在于JAVA语言,而是程序本身.养成良好的编码习惯非常重要,能够显著地提升程序性能. ● 1. 尽量在合适的场合使用单例 使用单例可以减轻加载的负担,缩短 ...

  8. SpringBoot中的异步编程

    @Async 是什么 void test() { A(); B(); C(); } 复制代码 在没有Async的情况下,上面的方法是顺序执行的,也可以称为同步调用. B要在A执行完毕之后执行,C需要在 ...

  9. 国产化之路-统信UOS操作系统安装

    专题目录 国产化之路-统信UOS操作系统安装 国产化之路-国产操作系统安装.net core 3.1 sdk 国产化之路-安装WEB服务器 国产化之路-安装达梦DM8数据库 国产化之路-统信UOS + ...

  10. 深入了解Redis(6)-持久化原理

    Redis是一个内存数据库,数据保存在内存中.但我们都知道存储在内存中的数据会因为外部因素而丢失,所以Redis会把数据持久化到磁盘中,至于是如何持久化呢? 一.RDB 1.手动触发 save:该命令 ...