2015-10-02 2 views
1

я определил этот класс аспект, который работает отлично за услуги (не разрешает доступ, если пользователь не имеет роли MANAGER, но нет restricton для контроллера (?)Spring AOP срез точек в контроллере

@Aspect 
public class DeviceAspect extends ServiceSupport { 


    @Pointcut("execution(* fo.belecam.services.client.ManageLicenseService.*(..))") 
    public void manage() { 
    } 

    @Pointcut("execution(* fo.belecam.services.client.AwardService.*(..))") 
    public void award() { 
    } 

    @Pointcut("execution(* fo.belecam.services.client.DeviceService.*(..))") 
    public void handleDeviceServiceMethod() { 
    } 

    @Pointcut("execution(* fo.belecam.controller.manage.ImportController.*(..))") 
    public void handleImportController() { 
    } 


    @Before("fo.belecam.services.aop.DeviceAspect.handleImportController() || fo.belecam.services.aop.DeviceAspect.handleDeviceServiceMethod() || fo.belecam.services.aop.DeviceAspect.manage() || fo.belecam.services.aop.DeviceAspect.award()") 
    @After ("fo.belecam.services.aop.DeviceAspect.handleImportController() || fo.belecam.services.aop.DeviceAspect.handleDeviceServiceMethod() || fo.belecam.services.aop.DeviceAspect.manage() || fo.belecam.services.aop.DeviceAspect.award()") 
    public void before(JoinPoint _jp) { 
     User user = getUser(); 
     if(user == null || user.getUserRole() != UserRole.MANAGER) { 
      throw new NoSufficientRoleException(user == null ? null : user.getUserRole(), UserRole.MANAGER); 
     } 
    } 

} 

и ImportController:

@SuppressWarnings("deprecation") 
public class ImportController extends AbstractFormController { 


    private String view; 

    private String successView; 

    @Autowired 
    protected UserService userService; 

    @Autowired 
    private ManageDeviceService manageDeviceService; 

    public String getView() { 
     return view; 
    } 

    public void setView(String view) { 
     this.view = view; 
    } 

    public String getSuccessView() { 
     return successView; 
    } 

    public void setSuccessView(String successView) { 
     this.successView = successView; 
    } 


    @Override 
    public ModelAndView processFormSubmission(final HttpServletRequest request, 
      HttpServletResponse response, Object command, BindException errors) 
      throws Exception { 

     final ModelAndView mav = new ModelAndView(getView()); 

     FileUploadCommand file = (FileUploadCommand)command; 

     MultipartFile multipartFile = file.getFile(); 

     if(multipartFile!=null && multipartFile.getSize()>0) { 
      Workbook workbook = Workbook.getWorkbook(multipartFile.getInputStream()); 
      DataCollector dataCollector = new XLSDataCollector(workbook, true); 
      final List<Application> applications = manageDeviceService.loadApplications (dataCollector.getDataCollection()); 
      List<ApplicationImporterError> importationErrors = manageDeviceService.validateApplications(applications); 
      savedApplications.add(manageDeviceService.getApplicationById(application.getId(), true)); 


     } 
     return mav; 
    } 

    @Override 
    public ModelAndView showForm(HttpServletRequest request, HttpServletResponse arg1, BindException errors) 
      throws Exception { 

     return new ModelAndView(getView()); 
    } 



    } 

    /** 
    * @param applications 
    * @param competentBody 
    * @return 
    * @throws Exception 
    */ 
    private List<Application> saveApplications(List<Application> applications,User user) throws Exception { 

     return manageDeviceService.saveImportedApplications (applications, user); 
    } 

    /** 
    * @param session 
    * @return 
    */ 
    public User getUser(HttpSession session) { 

     User user = (User) session.getAttribute(Const.SESSION_USER); 
     if (user == null) { 
      user = new User(); 
     } 
     return user; 
    } 
} 

Когда я вошел в UserRole.MANAGER метод ранее (JoinPoint _jp) вызывается, в противном случае не

Я вижу, метод перед тем (JoinPoint _jp) не вызывается, когда я просто вставить URL в браузере .... http://127.0.0.1:7001/devices/manage/import.do

+1

Вы отметили вопрос с помощью «spring-security», так почему бы вам не использовать Spring безопасности для этого? – zeroflagL

+0

Просто советую - я бы подумал о том, чтобы скрывать имена пакетов вашей компании в любом примерном коде, который вы предоставляете. –

+1

Не ответ, а просто другое предложение - поскольку ваши названные pointcuts находятся в том же классе, что и ваш метод '@ Before', вам не нужно полностью квалифицировать их в выражении pointcut -' @Before ("handleImportController() || handleDeviceServiceMethod() || и т. д.) должен работать и быть более кратким/читаемым. –

ответ

1

У меня была такая же проблема, когда совет для Репозитория работал, но рекомендаций для Контролера не было. Наконец я нашел решение. Короче говоря, вам нужно убедиться, что ваше определение AOP загружено в контексте Servlet, а не в другом контексте.

В моем случае определение Spring AOP определено в tools-config.xml. После переезда его здесь

<context-param> 
    <param-name>contextConfigLocation</param-name> 
    <param-value>classpath:spring/tools-config.xml</param-value> 
</context-param> 

<listener> 
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> 
</listener> 

к здесь,

<servlet> 
    <servlet-name>petclinic</servlet-name> 
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> 
    <init-param> 
     <param-name>contextConfigLocation</param-name> 
     <param-value>classpath:spring/mvc-core-config.xml, classpath:spring/tools-config.xml</param-value> 
    </init-param> 
    <load-on-startup>1</load-on-startup> 
</servlet> 

совет для контроллера работает.

1

Ограничение динамического прокси на основе АОП Spring является то, что он может посоветовать только публичные точки соединения - из документации:

http://docs.spring.io/spring/docs/current/spring-framework-reference/html/aop.html

Благодаря прокси на основе характера рамок АОП в Spring, защищенные методы по определению не перехватили, ни для JDK прокси (где это не применимо), ни для CGLIB прокси (там, где это технически возможно, но не рекомендуется для целей АОП). Как следствие, любой данный pointcut будет соответствовать только общедоступным методам! Если ваш перехват включает в себя защищенные/частные методы или даже конструкторы, рассмотрите использование родственного AspectJ, основанного на Spring, вместо основы AOP на основе прокси-сервера Spring. Это представляет собой другой способ использования АОП с различными характеристиками, поэтому перед принятием решения обязательно ознакомьтесь с плетением.

Ряд ваших методов контроллера, protected, поэтому, хотя контроллер зарегистрирован как Spring бина (предположительно) - непубличных методы не будут иметь в виду.

0

Проблема может заключаться в том, что сам объект контроллера вызывает методы, которые вы пытаетесь перехватить (они были защищены после всех первоначально), прямой вызов абстрактного контроллера на один из его методов переопределения. Как работает Spring AOP, он создает прокси-сервер вокруг вашего объекта, который перехватывает методы, но работает только в том случае, если этот метод вызывается извне через зависимую от Spring. Здесь не так - поскольку метод вызывается из своего собственного объекта, вызов обходит любые прокси-серверы, которые обертывают объект для «внешнего мира».

+0

, поэтому нет способа сделать это для контроллеров? –

+0

Попробуйте предлагаемые здесь решения: http://stackoverflow.com/questions/3310115/spring-aop-advice-on-annotated-controllers –

Смежные вопросы