javascript
spring aop组件_安全性中的Spring AOP –通过方面控制UI组件的创建
spring aop組件
以下文章將顯示在我參與的一個(gè)項(xiàng)目中,我們?nèi)绾问褂肧pring的AOP來(lái)介紹一些與安全性相關(guān)的功能。 這樣的概念是,為了使用戶能夠看到某些UI組件,他需要具有一定級(jí)別的安全特權(quán)。 如果不滿足該要求,則不會(huì)顯示UIComponent。 讓我們看一下項(xiàng)目結(jié)構(gòu):
然后還有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>現(xiàn)在,讓我們看一下Spring應(yīng)用程序上下文中最有趣的幾行。 首先,我們擁有所有必需的模式-我認(rèn)為不需要對(duì)此進(jìn)行更深入的解釋。 然后我們有:
<aop:aspectj-autoproxy/>啟用@AspectJ支持。 接下來(lái)是
<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>首先,我們通過(guò)注釋打開(kāi)Spring配置。 然后,我們故意排除了由Spring本身將其初始化為Bean的方面。 為什么? 因?yàn)椤?
<bean class="pl.grzejszczak.marcin.aop.interceptor.SecurityInterceptor" factory-method="aspectOf"/>我們希望自己創(chuàng)建方面,并提供factory-method =” aspectOf”。 這樣,我們的方面將包含在我們的bean的自動(dòng)裝配過(guò)程中-因此,所有帶有@Autowired注釋的字段都將注入bean。 現(xiàn)在讓我們繼續(xù)執(zhí)行代碼:
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類正在模仿一種服務(wù),該服務(wù)將從數(shù)據(jù)庫(kù)或當(dāng)前應(yīng)用程序上下文中獲取當(dāng)前用戶信息。
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;} }這是一個(gè)簡(jiǎn)單的持有人類,其中包含有關(guān)當(dāng)前用戶角色的信息。
角色.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;} }角色是一個(gè)枚舉,它為管理員 , 作家或來(lái)賓定義了一個(gè)角色。
UIComponent.java
package pl.grzejszczak.marcin.aop.ui;public abstract class UIComponent {protected String componentName;protected String getComponentName() {return componentName;}}一些UI組件的具體實(shí)現(xiàn)的抽象。
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組件擴(kuò)展的示例,只有具有Admin或Guest角色的用戶才能看到。
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(); }定義可以創(chuàng)建此組件的角色的注釋。
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();} }給定擴(kuò)展UIComponent的對(duì)象類的工廠類將返回給定UIComponent的新實(shí)例。
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);} } 這是在執(zhí)行函數(shù)createComponent的切入點(diǎn)處定義的方面
UIFactory接口。 在“ 周圍” 建議中,存在一種邏輯,該邏輯首先檢查將什么樣的參數(shù)傳遞給方法createComponent(例如SomeComponentForAdminAndGuest.class)。 接下來(lái),將檢查此類是否使用SecurityAnnotation進(jìn)行注釋,如果是,它將檢查創(chuàng)建組件所需的角色類型。 然后,它檢查當(dāng)前用戶(從UserService到UserHolder的Roles)是否具有呈現(xiàn)組件所需的角色。 如果是這樣的話
調(diào)用thisJoinPoint.proceed(),實(shí)際上返回?cái)U(kuò)展UIComponent的類的對(duì)象。 現(xiàn)在讓我們對(duì)其進(jìn)行測(cè)試–這是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 單元測(cè)試顯示,對(duì)于給定的Admin角色,僅創(chuàng)建了前兩個(gè)組件,而對(duì)于其他兩個(gè),則返回null(由于用戶沒(méi)有適當(dāng)?shù)臋?quán)限)。 這就是在我們的項(xiàng)目中,我們?nèi)绾问褂肧pring的AOP創(chuàng)建一個(gè)簡(jiǎn)單的框架,該框架將檢查用戶是否可以創(chuàng)建給定的組件。 由于對(duì)各個(gè)方面進(jìn)行了編程,因此不必記住編寫任何與安全性相關(guān)的代碼,因?yàn)樗鼘樗瓿伞?
翻譯自: https://www.javacodegeeks.com/2013/04/spring-aop-in-security-controlling-creation-of-ui-components-via-aspects.html
spring aop組件
總結(jié)
以上是生活随笔為你收集整理的spring aop组件_安全性中的Spring AOP –通过方面控制UI组件的创建的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 使用Spock Mocks进行Grail
- 下一篇: 铁路 12306 回应假期车票秒光:不会