我正在编写一个几乎完全受登录保护的网站(我正在使用Spring Security)。但是有些页面没有受到保护(主页,登录页面,注册页面,忘记密码页面......)以及我想要实现的目标是:
redirectTo
注释元素中指定的页面)当然我想避免将它放在每个控制器方法中:
if(loggedIn())
{
// Redirect
}
else
{
// Return the view
}
因此我想使用AOP。
我创建了注释@NonSecured
,我编写了以下方面:
@Aspect
public class LoggedInRedirectAspect
{
@Autowired
private UserService userService;
@Around("execution(@my.package.annotation.NonSecured * *(..))")
public void redirect(ProceedingJoinPoint point) throws Throwable
{
System.out.println("Test");
point.proceed();
}
}
示例注释方法:
@Controller
@RequestMapping("/")
public class HomeController
{
@NonSecured(redirectTo = "my-profile")
@RequestMapping(method = RequestMethod.GET)
public String index(Model model,
HttpServletRequest request) throws Exception
{
// Show home page
}
}
applicationContext.xml重要位:
<context:annotation-config />
<context:component-scan base-package="my.package" />
<tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true" />
<bean id="loggedInRedirectAspect" class="my.package.aspect.LoggedInRedirectAspect" />
<aop:aspectj-autoproxy proxy-target-class="true">
<aop:include name="loggedInRedirectAspect" />
</aop:aspectj-autoproxy>
问题是方面中的方法redirect(...)
永远不会被调用。 一般来说方面工作正常,实际上会调用方面中的以下方法:调用以下建议,但不会调用控制器方法。
@Around("execution(* *(..))")
public void redirect(ProceedingJoinPoint point) throws Throwable
{
point.proceed();
}
我的切入点是否有问题?
谢谢。
更新:此问题中的最后一个片段被调用,但仍未调用控制器方法。
答案 0 :(得分:6)
@satoshi,我认为您遇到的问题是因为您使用的是Spring-AOP,它只能为具有接口的bean创建AOP代理 - 在您的情况下,控制器没有接口。
修复可能是使用AspectJ使用编译时/加载时编织,并且不使用Spring AOP OR在类路径中使用cglib jar并强制基于cglib的代理创建:
<aop:aspectj-autoproxy proxy-target-class="true"/>
更新: 编译时编织可以使用maven插件完成,showWeaveInfo配置将准确显示已编织的类:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<version>1.0</version>
<dependencies>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.6.10</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjtools</artifactId>
<version>1.6.10</version>
</dependency>
</dependencies>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>test-compile</goal>
</goals>
</execution>
</executions>
<configuration>
<outxml>true</outxml>
<verbose>true</verbose>
<showWeaveInfo>true</showWeaveInfo>
<aspectLibraries>
<aspectLibrary>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
</aspectLibrary>
</aspectLibraries>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
答案 1 :(得分:0)
通常我会使用拦截器而不是用于此目的的方面。例如,创建一个RequestInitializeInterceptor,它将检查安全主体并相应地重定向。对于这项工作来说,方面是一种矫枉过正。对于特定控制器的每个请求,拦截器将充当前端控制器,并决定是否允许传输请求。
public class RequestInitializeInterceptor extends HandlerInterceptorAdapter {
// Obtain a suitable logger.
private static Log logger = LogFactory
.getLog(RequestInitializeInterceptor.class);
/**
* In this case intercept the request BEFORE it reaches the controller
*/
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response, Object handler) throws Exception {
try {
logger.info("Intercepting: " + request.getRequestURI());
// Your logic to redirect accordingly
if (userAuthenticated) {
response.sendRedirect(URL);
return false;
}
return true;
} catch (SystemException e) {
logger.info("request update failed");
return false;
}
}
}
希望这有帮助。
答案 2 :(得分:0)
对我有用的内容,请检查以下几点:
aspectjweaver.jar
在classpath(版本1.6.8或更高版本)@Aspect
和@Component
Java配置:
@Configuration
@ComponentScan("io.mc.springaspects")
@EnableAspectJAutoProxy
public class SpringConfiguration {
}
方面:
@Aspect
@Component
public class AnnotationAspect {
...
}
的Maven:
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.9</version>
</dependency>