基于SpringAop的鉴权功能
什么是 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的鉴权功能的更多相关文章
- 基于token机制鉴权架构
常见的鉴权方式有两种,一种是基于session,另一种是基于token方式的鉴权,我们来浅谈一下两种 鉴权方式的区别. 两种鉴权方式对比 session 安全性:session是基于cookie进行用 ...
- [原创]SpringSecurity控制授权(鉴权)功能介绍
1.spring security 过滤器链 spring security中的除了用户登录校验相关的过滤器,最后还包含了鉴权功能的过滤器,还有匿名资源访问的过滤器链,相关的图解如下: 2.控制授 ...
- YAPI接口自动鉴权功能部署详解
安装准备 以下操作,默认要求自己部署过yapi,最好是部署过yapi二次开发环境. 无论是选择在线安装或者是本地安装,都需要安装client工具. 1.yapi-cli:npm install yap ...
- 「快学springboot」集成Spring Security实现鉴权功能
Spring Security介绍 Spring Security是Spring全家桶中的处理身份和权限问题的一员.Spring Security可以根据使用者的需要定制相关的角色身份和身份所具有的权 ...
- Session, Token, OAuth 鉴权那些事儿
鉴权那些事 整体思路 无论什么样的服务, Web 服务总是不能绕开鉴权这个话题的, 通过有效的鉴权手段来保护网站数据, 来为特定用户提供服务. 整体来说, 有三种方式: Session-Cookie ...
- 认证鉴权与API权限控制在微服务架构中的设计与实现(四)
引言: 本文系<认证鉴权与API权限控制在微服务架构中的设计与实现>系列的完结篇,前面三篇已经将认证鉴权与API权限控制的流程和主要细节讲解完.本文比较长,对这个系列进行收尾,主要内容包括 ...
- EasyNVR摄像机网页H5全平台无插件直播流媒体播放服务二次开发之接口鉴权示例讲解
背景需求 EasyNVR的使用者应该都清楚的了解到,EasyNVR一个强大的功能就是可以进行全平台的无插件直播.主要原因在于rtsp协议的视频流(默认是需要插件才可以播放的)经由EasyNVR处理可以 ...
- 深入理解k8s中的访问控制(认证、鉴权、审计)流程
Kubernetes自身并没有用户管理能力,无法像操作Pod一样,通过API的方式创建/删除一个用户实例,也无法在etcd中找到用户对应的存储对象. 在Kubernetes的访问控制流程中,用户模型是 ...
- 【Spring Cloud & Alibaba 实战 | 总结篇】Spring Cloud Gateway + Spring Security OAuth2 + JWT 实现微服务统一认证授权和鉴权
一. 前言 hi,大家好~ 好久没更文了,期间主要致力于项目的功能升级和问题修复中,经过一年时间的打磨,[有来]终于迎来v2.0版本,相较于v1.x版本主要完善了OAuth2认证授权.鉴权的逻辑,结合 ...
随机推荐
- springcloudalibaba与nacos服务注册流程图
springboot + springcloud + springcloudalibaba + nacos 服务注册流程图: springboot ①WebApplicationContext ②st ...
- 从架构到部署,全面了解K3s
Kubernetes无处不在--开发者的笔记本.树莓派.云.数据中心.混合云甚至多云上都有Kubernetes.它已然成为现代基础设施的基础,抽象了底层的计算.存储和网络服务.Kubernetes隐藏 ...
- 深入理解 vue 中 scoped 样式作用域的规则
哈喽!大家好!我是木瓜太香,今天我们来聊一个 vue 的样式作用域的问题,通常我们开发项目的时候是要在 style 上加上 scoped 来起到规定组件作用域的效果的,所以了解他们的规则也是很有必要的 ...
- 关于Java代理那些事儿
代理是啥?就是代替你执行你持有的主要功能,并且能在你的基础之上完成一些其他的功能.代理的目的就是生成一个和原对象具有同样功能的对象.在Java中,代理是一种设计模式.在Spring的面向切面编程(AO ...
- 整理的网上的MySQL优化文章总结
MySQL优化 Linux优化 IO优化 调整Linux默认的IO调度算法. IO调度器的总体目标是希望让磁头能够总是往一个方向移动,移动到底了再往反方向走,这恰恰就是现实生活中的电梯模型,所以IO调 ...
- [LeetCode]Sql系列4
##题目1 626. 换座位 小美是一所中学的信息科技老师,她有一张 seat 座位表,平时用来储存学生名字和与他们相对应的座位 id. 其中纵列的 id 是连续递增的 小美想改变相邻俩学生的座位. ...
- mariadb 4
连接查询,视图,事物,索引,外键(第四章) 连接查询 --创建学生表 create table students ( id int unsigned not null auto_increment ...
- Jenkins+Git+Gitlab+Ansible实现持续集成自动化部署静态网站(6)
前言 在之前已经写了关于Git,Gitlab以及Ansible的两篇博客<Git+Gitlab+Ansible剧本实现一键部署Nginx–技术流ken>,<Git+Gitlab+An ...
- Debian、kali类虚拟机网络设置
Linux发行版分类 先说一下Linux发行版的分类,因为不同的发行版,各自设置的网络的方式就不相同, - 我常用的Linux发行版 -- Debian --- debian --- ubuntu - ...
- Spring 标签纸property
转载自https://www.cnblogs.com/zzb-yp/p/9968849.html Spring中XML文件配置Bean的简单示例,如下: <bean id="car&q ...