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默认的登陆页面,是如何跳转到登陆成功页面的?
如何配置 Spring Security 以允许在 JSP 页面中使用 hasPermission?