Spring Security:如何在公共页面中识别用户已通过身份验证

Posted

技术标签:

【中文标题】Spring Security:如何在公共页面中识别用户已通过身份验证【英文标题】:Spring Security: how to recognize, in a public page, that a user is authenticated 【发布时间】:2021-08-13 13:22:02 【问题描述】:

我有一个简单的 Spring Boot Web 应用程序,由 2 个页面组成:

网址为https://example.com/ 的主页(可免费访问) 网址为https://example.com/secure/page.html 的安全页面(需要登录才能访问)

在主页中,我正在打印访问用户的名字(如果他/她已经通过身份验证)或说明该页面由匿名用户访问的句子

就身份验证而言,我正在使用 Keycloak。

这里是 Spring Security 配置:

@Override
protected void configure(HttpSecurity http) throws Exception 
    http
    .authorizeRequests()
    .antMatchers("/secure/**")
    .authenticated()
    .and()
    .csrf().requireCsrfProtectionMatcher(keycloakCsrfRequestMatcher())
    .and()
    .sessionManagement()
    .sessionAuthenticationStrategy(sessionAuthenticationStrategy())
    .and()
    .addFilterBefore(keycloakPreAuthActionsFilter(), LogoutFilter.class)
    .addFilterBefore(keycloakAuthenticationProcessingFilter(), BasicAuthenticationFilter.class)
    .addFilterBefore(keycloakAuthenticatedActionsFilter(), BasicAuthenticationFilter.class)
    .addFilterAfter(keycloakSecurityContextRequestFilter(), SecurityContextHolderAwareRequestFilter.class)
    .exceptionHandling().authenticationEntryPoint(authenticationEntryPoint())
    .and()
    .logout()
    .addLogoutHandler(keycloakLogoutHandler())
    .logoutUrl("/sso/logout").permitAll()
    .logoutSuccessUrl("/");

如果用户已经通过身份验证,问题是主页显示他是匿名的,因为Principal 始终是null

但是,如果用户在返回主页时进入安全页面(并且 Keycloak 允许他进入,因为他已经过身份验证),则该页面包含 - 正确 - 他的名字。

我的配置哪里错了?

似乎 Spring Security 不会检查非安全页面上的身份验证。有没有办法告诉 Spring Security 检查每个页面(安全和非安全)?

提前感谢您的支持。

【问题讨论】:

【参考方案1】:

解决此问题的方法是将/** 添加到安全上下文/处理中(使用permitAll())。

艺术就是正确地去做:

Multiple antMatchers in Spring security(第一个蚂蚁匹配者获胜!!,https://www.google.com/search?q=spring+security+permitall+not+working) http://blog.florian-hopf.de/2017/08/spring-security.html

所以在这种情况下:

 http
  .authorizeRequests()
  .antMatchers("/secure/**").authenticated()
  .antMatchers("/**").pernmitAll()
  .and()...

...应该在“允许的区域”中填写(匿名)Principal(即/**(!) ...并离开secure/**受限!;)。


对于核心/标题问题(一旦填满校长),我认为答案已经给出:

在这里(口头):https://***.com/a/26117007/592355 在这里(带代码):https://***.com/a/57054816/592355

..如果你使用Spring Security (JSP) TaglibsisAnonymous()很方便,否则(默认情况下)你只需要检查hasRole('ROLE_ANONYMOUS')(Ref)

【讨论】:

感谢您的宝贵建议。我实施了建议的解决方案,实际上,Principal 现在填充了ROLE_ANONYMOUS 并且不再为空。然而,这不是问题的解决方案,因为如果已经登录的用户访问主页(公共),则在他进入安全页面之前,它将被识别为anonymous。从此,他得到了应有的认可。如果 .permitAll() 存在,Spring Security 似乎不会检查 SSO 系统。我还能尝试什么?非常感谢您的支持。 sry,如果我没看错,但是当他“进入主页”时,他是如何“登录”的?有点像鸡蛋的问题!? (我倾向于鸡蛋;)...是的,使用此解决方案,您只能匿名或经过身份验证....并且由于您只需要在安全区域(根据要求)进行身份验证,因此每个“进入”家庭的用户页面将是匿名的!...直到他(访问安全区域并)登录...(然后返回主页,以他的名字欢迎他;) 虽然,我是 xerx593,化身......我不能指望任何网站在我登录之前知道这一点......(这可以通过“cookie”实现)...... . 用户已通过身份验证,因为他登录了 SSO 系统下的另一个应用程序。所以,我希望当他到达主页时,Spring Security 能够立即识别他,而无需进入安全页面(一切都按预期工作)。非常感谢您的时间。 谢谢,现在对我来说更有意义了!是的,这听起来像:SSO 未正确配置/主体不会被填充... ... -> baeldung.com/… ;)

以上是关于Spring Security:如何在公共页面中识别用户已通过身份验证的主要内容,如果未能解决你的问题,请参考以下文章

Spring Security - 公共页面重定向到使用无效会话 ID 登录

如何阻止 Spring Security 创建新会话?

Spring Security 使用非spring默认的登陆页面,是如何跳转到登陆成功页面的?

如何配置 Spring Security 以允许在 JSP 页面中使用 hasPermission?

如何使用 Spring MVC、Spring Security 和 FreeMarker 在每个页面上显示用户名

如何使用自定义登录页面纠正 Spring Security 异常?