如何让Spring Security中的permitAll不在@Controller对象中抛出AuthenticationCredentialsNotFoundException?

时间:2010-12-20 05:53:11

标签: exception authentication controller authorization spring-security

我有一个控制器,它有很多动作,它指定了一个默认的类级别@PreAuthorize注释,但我想让任何人进入其中一个动作(“show”动作)。

@RequestMapping("/show/{pressReleaseId}")
@PreAuthorize("permitAll")
public ModelAndView show(@PathVariable long pressReleaseId) {
    ModelAndView modelAndView = new ModelAndView(view("show"));

    modelAndView.addObject("pressRelease",
        sysAdminService.findPressRelease(pressReleaseId));

    return modelAndView;
}

不幸的是,Spring Security引发了这个异常:

org.springframework.security.authentication.AuthenticationCredentialsNotFoundException: An Authentication object was not found in the SecurityContext
    at org.springframework.security.access.intercept.AbstractSecurityInterceptor.credentialsNotFound(AbstractSecurityInterceptor.java:321)
    at org.springframework.security.access.intercept.AbstractSecurityInterceptor.beforeInvocation(AbstractSecurityInterceptor.java:195)
    at org.springframework.security.access.intercept.aopalliance.MethodSecurityInterceptor.invoke(MethodSecurityInterceptor.java:64)

如何让Spring Security不抛出此异常?我只是想让任何人进入 - 未经过身份验证的用户和经过身份验证的用户 - 每个人。

我唯一的解决办法就是将这个方法完全放在另一个控制器中,而根本没有@PreAuthorize ...这会起作用,但那是愚蠢的。我想在同一个控制器中保留我的所有新闻稿动作。

感谢您的帮助!

3 个答案:

答案 0 :(得分:10)

我猜您没有启用匿名身份验证过滤器。

如果使用命名空间配置和auto-config = "true",则默认情况下应启用它。如果您不使用自动配置,则可以将匿名过滤器设置为<security:anonymous />

答案 1 :(得分:3)

允许任何人访问控制器方法的常规方法是使用任何Spring Security注释对其进行注释;即没有@PreAuthorize没有@Secured等。

您应该能够从@PreAuthorize方法中删除show(),任何将注释留在该控制器中的其他方法上。无论您使用show()方法做什么,其他方法都将保持安全。

答案 2 :(得分:3)

默认情况下,spring安全插件的更新版本(版本2)已更改。这意味着默认情况下所有控制器都是安全的(您需要登录才能看到它们)。删除@Secured根本不起作用,它仍将保持安全。您可以更改此默认行为,但对我来说,新的默认行为是有意义的,因为它更安全。安全性非常重要。

我只使用

@Secured(['permitAll'])

对于我的控制器,但它也适用于方法。