如何在 Spring Security 中获取 permitAll 以不在 @Controller 对象中抛出 AuthenticationCredentialsNotFoundException?
Posted
技术标签:
【中文标题】如何在 Spring Security 中获取 permitAll 以不在 @Controller 对象中抛出 AuthenticationCredentialsNotFoundException?【英文标题】:How do I get permitAll in Spring Security to NOT throw AuthenticationCredentialsNotFoundException in @Controller object? 【发布时间】:2011-05-28 02:22:58 【问题描述】:我有一个控制器,它有很多动作,它指定了一个默认的类级别 @PreAuthorize 注释,但我想让任何人都可以执行其中一个动作(“显示”动作)。
@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...这会起作用,但这很愚蠢。我想将所有新闻稿操作保存在同一个控制器中。
感谢您的帮助!
【问题讨论】:
【参考方案1】:我猜你没有启用匿名身份验证过滤器。
如果你使用命名空间配置和auto-config = "true"
,它应该默认启用。如果你不使用自动配置,你可以启用匿名过滤为<security:anonymous />
。
【讨论】:
这是最好的答案 - 在此处查看详细信息docs.spring.io/spring-security/site/docs/current/reference/html/… 这个的java配置是什么?【参考方案2】:允许任何人访问控制器方法的正常方法是不使用任何 Spring Security 注释对其进行注释;即没有@PreAuthorize
没有@Secured
等。
您应该能够简单地从show()
方法中删除@PreAuthorize
,任何将注释留在该控制器中的其他方法上。无论您使用 show()
方法做什么,其他方法都将保持安全。
【讨论】:
这真的很糟糕,因为这意味着我必须指定 X 个相同的 @PreAuthorize 注释,而不是指定类级别的默认值,然后对每个控制器操作进行 X 测试以验证我没有忘记将它包含在除 show() 操作之外的所有操作中。这只是弹簧安全方面的糟糕设计。他们应该有一个“doNothing”命令来允许类级别的默认值正常工作:( 鉴于@PreAuthorize
注解的内容是一个Spring EL表达式,你能写一个总是返回true的表达式吗?即@PreAuthorize("true")
?我还没有尝试过,但这似乎是一种可能的解决方法......
值得一试;)但是不,不工作。哦,好吧......我有这么多控制器存在安全问题,我认为这对 Spring Security 来说太混乱了,以至于迫使开发人员分别测试每个操作而不使用类级别的默认值。我必须告诉他们解决这个问题,因为这对于大型应用程序来说很糟糕。
插件版本 2 更改了默认行为。现在一切都默认安全了!【参考方案3】:
随着 Spring Security 插件的更新版本(版本 2)更改默认设置。这意味着默认情况下所有控制器都是安全的(您需要登录才能看到它们)。删除 @Secured 根本不起作用,它仍然会保持安全。您可以更改此默认行为,但对我来说,新的默认行为是有意义的,因为它更安全。而且安全非常重要。
我只用
@Secured(['permitAll'])
适用于我的控制器,但它也应该适用于方法。
【讨论】:
这不是有效的Java,试试@Secured("permitAll")
以上是关于如何在 Spring Security 中获取 permitAll 以不在 @Controller 对象中抛出 AuthenticationCredentialsNotFoundException?的主要内容,如果未能解决你的问题,请参考以下文章
如何获取 Spring Security SessionRegistry?
如何在Grails 2单元测试中获取spring security提供的currentUser
如何使用 Spring Security 在代码中获取用户的授权凭据?
如何在 Spring Security 中测试 AuthenticationPrincipal 并获取 ID 令牌?
如何使用spring security在grails中获取所有当前登录用户的列表(包括rememberme cookie)