安全性中的Spring AOP –通过方面控制UI组件的创建

以下文章将显示在我参与的一个项目中,我们如何使用Spring的AOP来介绍一些与安全性相关的功能。 这样的概念是为了使用户能够看到一些UI组件,他需要具有一定级别的安全特权。 如果不满足该要求,则不会显示UIComponent。 让我们看一下项目结构:

然后还有aopApplicationContext.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:context="http://www.springframework.org/schema/context"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:aop="http://www.springframework.org/schema/aop"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsdhttp://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsdhttp://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.1.xsdhttp://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"><aop:aspectj-autoproxy /><context:annotation-config /><context:component-scan base-package="pl.grzejszczak.marcin.aop"><context:exclude-filter type="annotation" expression="org.aspectj.lang.annotation.Aspect"/></context:component-scan><bean class="pl.grzejszczak.marcin.aop.interceptor.SecurityInterceptor" factory-method="aspectOf"/> </beans>

现在,让我们看一下Spring应用程序上下文中最有趣的几行。 首先,我们拥有所有必需的模式-我认为不需要对此进行更深入的解释。 然后我们有:

<aop:aspectj-autoproxy/>

启用@AspectJ支持。 接下来是

<context:annotation-config />
<context:component-scan base-package="pl.grzejszczak.marcin.aop"><context:exclude-filter type="annotation" expression="org.aspectj.lang.annotation.Aspect"/>
</context:component-scan>

首先,我们通过注释打开Spring配置。 然后,我们故意排除了由Spring本身将其初始化为Bean的方面。 为什么? 因为…

<bean class="pl.grzejszczak.marcin.aop.interceptor.SecurityInterceptor" factory-method="aspectOf"/>

我们希望自己创建方面,并提供factory-method =” aspectOf”。 这样,我们的方面将包含在我们的bean的自动装配过程中-因此,所有带有@Autowired注释的字段都将注入bean。 现在让我们继续执行代码:

UserServiceImpl.java

package pl.grzejszczak.marcin.aop.service;import org.springframework.stereotype.Service;import pl.grzejszczak.marcin.aop.type.Role;
import pl.grzejszczak.marcin.aop.user.UserHolder;@Service
public class UserServiceImpl implements UserService {private UserHolder userHolder;@Overridepublic UserHolder getCurrentUser() {return userHolder;}@Overridepublic void setCurrentUser(UserHolder userHolder) {this.userHolder = userHolder;}@Overridepublic Role getUserRole() {if (userHolder == null) {return null;}return userHolder.getUserRole();}
}

UserServiceImpl类正在模仿一种服务,该服务将从数据库或当前应用程序上下文中获取当前用户信息。

UserHolder.java

package pl.grzejszczak.marcin.aop.user;import pl.grzejszczak.marcin.aop.type.Role;public class UserHolder {private Role userRole;public UserHolder(Role userRole) {this.userRole = userRole;}public Role getUserRole() {return userRole;}public void setUserRole(Role userRole) {this.userRole = userRole;}
}

这是一个简单的持有人类,其中包含有关当前用户角色的信息。

角色.java

package pl.grzejszczak.marcin.aop.type;public enum Role {ADMIN("ADM"), WRITER("WRT"), GUEST("GST");private String name;private Role(String name) {this.name = name;}public static Role getRoleByName(String name) {for (Role role : Role.values()) {if (role.name.equals(name)) {return role;}}throw new IllegalArgumentException("No such role exists [" + name + "]");}public String getName() {return this.name;}@Overridepublic String toString() {return name;}
}

角色是一个枚举,它为管理员作家来宾定义了一个角色。

UIComponent.java

package pl.grzejszczak.marcin.aop.ui;public abstract class UIComponent {protected String componentName;protected String getComponentName() {return componentName;}}

一些UI组件的具体实现的抽象。

SomeComponentForAdminAndGuest.java

package pl.grzejszczak.marcin.aop.ui;import pl.grzejszczak.marcin.aop.annotation.SecurityAnnotation;
import pl.grzejszczak.marcin.aop.type.Role;@SecurityAnnotation(allowedRole = { Role.ADMIN, Role.GUEST })
public class SomeComponentForAdminAndGuest extends UIComponent {public SomeComponentForAdminAndGuest() {this.componentName = "SomeComponentForAdmin";}public static UIComponent getComponent() {return new SomeComponentForAdminAndGuest();}
}

此组件是UI组件扩展的示例,只有拥有AdminGuest角色的用户才能看到。

SecurityAnnotation.java

package pl.grzejszczak.marcin.aop.annotation;import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;import pl.grzejszczak.marcin.aop.type.Role;@Retention(RetentionPolicy.RUNTIME)
public @interface SecurityAnnotation {Role[] allowedRole();
}

定义可以创建此组件的角色的注释。

UIFactoryImpl.java

package pl.grzejszczak.marcin.aop.ui;import org.apache.commons.lang.NullArgumentException;
import org.springframework.stereotype.Component;@Component
public class UIFactoryImpl implements UIFactory {@Overridepublic UIComponent createComponent(Class<? extends UIComponent> componentClass) throws Exception {if (componentClass == null) {throw new NullArgumentException("Provide class for the component");}return (UIComponent) Class.forName(componentClass.getName()).newInstance();}
}

给定扩展UIComponent的对象类的工厂类将返回给定UIComponent的新实例。

SecurityInterceptor.java

package pl.grzejszczak.marcin.aop.interceptor;import java.lang.annotation.Annotation;
import java.lang.reflect.AnnotatedElement;
import java.util.Arrays;
import java.util.List;import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;import pl.grzejszczak.marcin.aop.annotation.SecurityAnnotation;
import pl.grzejszczak.marcin.aop.service.UserService;
import pl.grzejszczak.marcin.aop.type.Role;
import pl.grzejszczak.marcin.aop.ui.UIComponent;@Aspect
public class SecurityInterceptor {private static final Logger LOGGER = LoggerFactory.getLogger(SecurityInterceptor.class);public SecurityInterceptor() {LOGGER.debug("Security Interceptor created");}@Autowiredprivate UserService userService;@Pointcut("execution(pl.grzejszczak.marcin.aop.ui.UIComponent pl.grzejszczak.marcin.aop.ui.UIFactory.createComponent(..))")private void getComponent(ProceedingJoinPoint thisJoinPoint) {}@Around("getComponent(thisJoinPoint)")public UIComponent checkSecurity(ProceedingJoinPoint thisJoinPoint) throws Throwable {LOGGER.info("Intercepting creation of a component");Object[] arguments = thisJoinPoint.getArgs();if (arguments.length == 0) {return null;}Annotation annotation = checkTheAnnotation(arguments);boolean securityAnnotationPresent = (annotation != null);if (securityAnnotationPresent) {boolean userHasRole = verifyRole(annotation);if (!userHasRole) {LOGGER.info("Current user doesn't have permission to have this component created");return null;}}LOGGER.info("Current user has required permissions for creating a component");return (UIComponent) thisJoinPoint.proceed();}/*** Basing on the method's argument check if the class is annotataed with* {@link SecurityAnnotation}* * @param arguments* @return*/private Annotation checkTheAnnotation(Object[] arguments) {Object concreteClass = arguments[0];LOGGER.info("Argument's class - [{}]", new Object[] { arguments });AnnotatedElement annotatedElement = (AnnotatedElement) concreteClass;Annotation annotation = annotatedElement.getAnnotation(SecurityAnnotation.class);LOGGER.info("Annotation present - [{}]", new Object[] { annotation });return annotation;}/*** The function verifies if the current user has sufficient privilages to* have the component built* * @param annotation* @return*/private boolean verifyRole(Annotation annotation) {LOGGER.info("Security annotation is present so checking if the user can use it");SecurityAnnotation annotationRule = (SecurityAnnotation) annotation;List<Role> requiredRolesList = Arrays.asList(annotationRule.allowedRole());Role userRole = userService.getUserRole();return requiredRolesList.contains(userRole);}
}

这是在执行函数createComponent的切入点处定义的方面
UIFactory接口。 在“ 环绕” 建议中,存在一种逻辑,该逻辑首先检查将什么样的参数传递给方法createComponent(例如SomeComponentForAdminAndGuest.class)。 接下来,检查此类是否用SecurityAnnotation进行注释,如果是,它将检查创建组件所需的角色类型。 然后,它检查当前用户(从UserService到UserHolder的Roles)是否具有呈现组件所需的角色。 如果是这样的话 调用thisJoinPoint.proceed(),实际上返回扩展UIComponent的类的对象。 现在让我们对其进行测试-SpringJUnit4ClassRunner来了

AopTest.java

package pl.grzejszczak.marcin.aop;import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;import pl.grzejszczak.marcin.aop.service.UserService;
import pl.grzejszczak.marcin.aop.type.Role;
import pl.grzejszczak.marcin.aop.ui.SomeComponentForAdmin;
import pl.grzejszczak.marcin.aop.ui.SomeComponentForAdminAndGuest;
import pl.grzejszczak.marcin.aop.ui.SomeComponentForGuest;
import pl.grzejszczak.marcin.aop.ui.SomeComponentForWriter;
import pl.grzejszczak.marcin.aop.ui.UIFactory;
import pl.grzejszczak.marcin.aop.user.UserHolder;@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:aopApplicationContext.xml" })
public class AopTest {@Autowiredprivate UIFactory uiFactory;@Autowiredprivate UserService userService;@Testpublic void adminTest() throws Exception {userService.setCurrentUser(new UserHolder(Role.ADMIN));Assert.assertNotNull(uiFactory.createComponent(SomeComponentForAdmin.class));Assert.assertNotNull(uiFactory.createComponent(SomeComponentForAdminAndGuest.class));Assert.assertNull(uiFactory.createComponent(SomeComponentForGuest.class));Assert.assertNull(uiFactory.createComponent(SomeComponentForWriter.class));}
}

和日志:

pl.grzejszczak.marcin.aop.interceptor.SecurityInterceptor:26 Security Interceptor created
pl.grzejszczak.marcin.aop.interceptor.SecurityInterceptor:38 Intercepting creation of a component
pl.grzejszczak.marcin.aop.interceptor.SecurityInterceptor:48 Argument's class - [[class pl.grzejszczak.marcin.aop.ui.SomeComponentForAdmin]]
pl.grzejszczak.marcin.aop.interceptor.SecurityInterceptor:54 Annotation present - [@pl.grzejszczak.marcin.aop.annotation.SecurityAnnotation(allowedRole=[ADM])]
pl.grzejszczak.marcin.aop.interceptor.SecurityInterceptor:57 Security annotation is present so checking if the user can use it
pl.grzejszczak.marcin.aop.interceptor.SecurityInterceptor:70 Current user has required permissions for creating a component
pl.grzejszczak.marcin.aop.interceptor.SecurityInterceptor:38 Intercepting creation of a component
pl.grzejszczak.marcin.aop.interceptor.SecurityInterceptor:48 Argument's class - [[class pl.grzejszczak.marcin.aop.ui.SomeComponentForAdminAndGuest]]
pl.grzejszczak.marcin.aop.interceptor.SecurityInterceptor:54 Annotation present - [@pl.grzejszczak.marcin.aop.annotation.SecurityAnnotation(allowedRole=[ADM, GST])]
pl.grzejszczak.marcin.aop.interceptor.SecurityInterceptor:57 Security annotation is present so checking if the user can use it
pl.grzejszczak.marcin.aop.interceptor.SecurityInterceptor:70 Current user has required permissions for creating a component
pl.grzejszczak.marcin.aop.interceptor.SecurityInterceptor:38 Intercepting creation of a component
pl.grzejszczak.marcin.aop.interceptor.SecurityInterceptor:48 Argument's class - [[class pl.grzejszczak.marcin.aop.ui.SomeComponentForGuest]]
pl.grzejszczak.marcin.aop.interceptor.SecurityInterceptor:54 Annotation present - [@pl.grzejszczak.marcin.aop.annotation.SecurityAnnotation(allowedRole=[GST])]
pl.grzejszczak.marcin.aop.interceptor.SecurityInterceptor:57 Security annotation is present so checking if the user can use it
pl.grzejszczak.marcin.aop.interceptor.SecurityInterceptor:66 Current user doesn't have permission to have this component created
pl.grzejszczak.marcin.aop.interceptor.SecurityInterceptor:38 Intercepting creation of a component
pl.grzejszczak.marcin.aop.interceptor.SecurityInterceptor:48 Argument's class - [[class pl.grzejszczak.marcin.aop.ui.SomeComponentForWriter]]
pl.grzejszczak.marcin.aop.interceptor.SecurityInterceptor:54 Annotation present - [@pl.grzejszczak.marcin.aop.annotation.SecurityAnnotation(allowedRole=[WRT])]
pl.grzejszczak.marcin.aop.interceptor.SecurityInterceptor:57 Security annotation is present so checking if the user can use it
pl.grzejszczak.marcin.aop.interceptor.SecurityInterceptor:66 Current user doesn't have permission to have this component created

单元测试表明,对于给定的Admin角色,仅创建了前两个组件,而对于其他两个,则返回null(由于用户没有适当的权限)。 这就是在我们的项目中,我们如何使用Spring的AOP创建一个简单的框架,该框架将检查用户是否可以创建给定的组件。 由于对这些方面进行了编程,因此不必记住编写任何与安全相关的代码,因为它将为他完成。

参考: 安全性中的Spring AOP –通过我们的JCG合作伙伴 Marcin Grzejszczak(位于Blog上)上的代码瘾君子博客来控制UI组件的创建 。

翻译自: https://www.javacodegeeks.com/2013/04/spring-aop-in-security-controlling-creation-of-ui-components-via-aspects.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/368795.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

模拟生物自然进化的基因遗传算法

基因遗传算法&#xff08;Genetic Algorithm&#xff0c;GA&#xff09;是一种通过模拟生物进化过程来寻找最优解的优化算法。它是一种常见的启发式搜索算法&#xff0c;常用于优化、搜索和机器学习等领域。 生物基因遗传 生物的基因遗传是指父母通过基因传递给子代的过程。基因…

CSS学习笔记11 CSS背景

background-color&#xff1a;背景色 前面我们经常用background-color这个属性来设置元素的背景色&#xff0c;例如下面这条css可将段落的背景色设置为灰色 p {background-color: gray;} 如果想要元素的背景色向外延伸&#xff0c;则只需增加内边距即可 background-color可以为…

linux 文件的目录,Linux文件及目录管理

第七列&#xff1a;文件或目录名。名以 . 开头表示为隐藏文件或隐藏目录2.2 修改文件目录或者权限改变文件所属用户组&#xff1a;chgrpchgrp [-R] 用户组 文件或目录 ...[-R]&#xff1a;递归修改该目录下所有文件和目录&#xff1b;改变文件所有者&#xff1a;chownchown [-R…

套接字(linux相关)

前言&#xff1a;略 一、前因 一切从tcp、udp开始。 众所周知&#xff0c;网络模型一般有两种模型&#xff0c;一种为OSI概念模型&#xff08;七层&#xff09;&#xff0c;另一种为TCP/IP网络模型&#xff08;四层&#xff09;。 TCP/IP应用层对应OSI的应用层、显示层、会话层…

linux查看进程运行日志文件,【Linux】常用指令、ps查看进程、kill杀进程、启动停止tomcat命令、查看日志、查看端口、find查找文件...

1.说出 10 个 linux 常用的指令1) ls 查看目录中的文件2)cd /home 进入 / home 目录&#xff1b;cd .. 返回上一级目录&#xff1b;cd ../.. 返回上两级目录3)mkdir dir1 创建一个叫做 dir1 的目录4)rmdir dir1 删除一个叫做 dir1 的目录 (只能删除空目录)5)rm -f file1 删除一…

Java PDF库

最近&#xff0c;我有一项任务是选择一些Java PDF库用于PDF生成。 但这不是一个简单的任务。 我想到的第一件事是iText。 众所周知Java库具有良好的声誉。 但是...有一些塞子。 iText 5版是在AGPL许可下发布的。 即&#xff0c;如果我们想在商业产品中使用iText&#xff0c;则必…

前端工程师必备的几个实用网站

一、配色类网站 http://colorhunt.co 这个网站给我们提供了很多的配色方案&#xff0c;我们直接使用就OK了。使用方法也很简单&#xff0c;鼠标移动到对应的颜色上&#xff0c;我们就可以看到颜色的十六进制码&#xff0c;复制这个颜色到工具里就可以使用了。 https://webgra…

linux 修改jmeter内存溢出,jmeter本机内存溢出如何修改?

websocket连接过程中内存溢出&#xff0c;本机配置的内存最大和最小设置的512&#xff1b;一、后台返回二、结果树返回&#xff1a;Thread Name: 线程组 1-9Sample Start: 2017-09-11 13:59:49 CSTLoad time: 9006Connect Time: 0Latency: 0Size in bytes: 0Sent bytes:0Header…

JSF:在传统组件和时尚性能杀手之间进行选择

这篇博客文章起源于一个大型Web应用程序中的性能问题。 每个人都优化Java代码&#xff0c;但似乎没有人尝试优化JavaScript代码。 奇怪&#xff0c;因为在客户端有很多改进的空间。 我会说&#xff0c;甚至比服务器端还要多。 我们将分析可编辑的JSF标准组件&#xff08;有时称…

JS之 if语句函数 对接事件动作 函数更改css css对接需要换妆的区id或class

if 函数的实现步骤: function 名字() 指定id , 指定开关(display: none or block) if else 构成逻辑 控制开关 决定在哪里安置一个灯泡, 指定一个id给某个标签 把开关用电线连着灯泡, 安装开关 # id名称{ 属性1 赋值, 属性 2 赋值 , 属性3 赋值 } 所有的赋值都可以成为一…

小型Hadoop集群的Ganglia配置和一些故障排除

Ganglia是一个针对大型集群的开源&#xff0c;可扩展且分布式的监视系统。 它收集&#xff0c;汇总并提供数十种与计算机相关的指标&#xff08;例如CPU&#xff0c;内存&#xff0c;存储&#xff0c;网络使用情况&#xff09;的时序视图。 您可以在UC Berkeley Grid上看到Gang…

margin赋值为负值的几种效果(负值像素,负值百分数)

1、margin-top为负值像素 margin-top为负值像素&#xff0c;偏移值相对于自身&#xff0c;其后元素受影响&#xff0c;见如下代码&#xff1a; 1 <!DOCTYPE html>2 <html lang"zh">3 <head>4 <meta charset"UTF-8" />5 &…

File如何转换成MultipartFile

MutipartFile是spring里面定义的接口&#xff0c;它封装了用户在上传图片时所包含的所有信息&#xff0c;但是有些时候我们要将file转换成MutipartFile&#xff0c;才能在保持原有代码逻辑的情况下方便代码的调整&#xff0c;但是file不能直接转换成MutipartFile&#xff0c;现…

Vue 进阶教程之:详解 v-model

分享 Vue 官网教程上关于 v-model 的讲解不是十分的详细&#xff0c;写这篇文章的目的就是详细的剖析一下&#xff0c; 并介绍 Vue 2.2 v-model改进的地方&#xff0c;然后穿插的再说点 Vue 的小知识。在 Vue 中&#xff0c;有许多方法和 Angular 相似&#xff0c;这主要是因…

linux 无密码登录另一台服务器,ECS Linux服务器ssh免密码登录另外一台服务器的具体设置...

若有多台linux服务器&#xff0c;为方便起见&#xff0c;服务器之前可设置免密码ssh登录&#xff0c;具体操作参考如下所示&#xff1a;1 、登录其中一个服务器&#xff0c;执行ssh-keygen -t rsa&#xff0c;按3次回车&#xff0c;将会生成公钥和私钥文件id_rsa和id_rsa.pub&a…

Spring 3.2 @ControllerAdvice批注的异常处理

不久前&#xff0c;我写了一个博客&#xff0c;概述了如何将Spring示例代码升级到3.2版&#xff0c;并演示了其中的一些小“陷阱”。 从那以后&#xff0c;我一直在仔细阅读Spring 3.2的新功能列表&#xff0c;尽管它不包含任何革命性的新更改&#xff0c;但我怀疑Spring的家伙…

DOM元素属性值如果设置为对象

结论&#xff1a;内部会调用toString方法&#xff0c;将设置的对象转换为字符串添加给相应的属性&#xff1b; 这个问题呢&#xff0c;是通过jQuery的each方法中&#xff0c;回调函数的this指向问题而来&#xff1b; 我们知道&#xff0c;回调函数中的this如果指向的是基本数据…

纯CSS3美化单选按钮radio

这种纯CSS3美化单选按钮radio的方法适用于以下情况&#xff1a; 1、可兼容IE9以上&#xff0c;需要兼容IE8的要写IE的hack把样式去掉 2、只支持单选按钮radio&#xff0c;因为单选按钮选中样式的圆圈可以用CSS做出来&#xff0c;但是复选按钮checkbox的选中效果对勾就需要图片…

【洛谷】【二分答案+最短路】P1462 通往奥格瑞玛的道路

在艾泽拉斯大陆上有一位名叫歪嘴哦的神奇术士&#xff0c;他是部落的中坚力量有一天他醒来后发现自己居然到了联盟的主城暴风城在被众多联盟的士兵攻击后&#xff0c;他决定逃回自己的家乡奥格瑞玛 题目背景【题目描述&#xff1a;】 在艾泽拉斯&#xff0c;有n个城市。编号为1…

训练残骸模式– Java 8中的改进实现

Venkat Subramaniam在今天的演讲中提到了有关“级联方法”模式或“火车残骸”模式的内容&#xff0c;如下所示&#xff1a; >someObject.method1().method2().method3().finalResult()很少有人会将此与构建器模式相关联&#xff0c;但事实并非如此。 无论如何&#xff0c;让…