spring-boot - doFilter() 重写方法 httpRequest.getUserPrincipal() 总是返回 NullPoint 异常
问题描述
我创建了 Spring Boot 应用程序。我使用了以下依赖项。Spring Boot 版本为 2.1.0.RELEASE
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
</dependencies>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-saml-servlet-filter-adapter</artifactId>
<version>4.5.0.Final</version>
</dependency>
安全配置类如下所示。
@EnableWebSecurity
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/actuator").authenticated();
http.headers().cacheControl().disable();
http.csrf().disable();
http.logout().logoutSuccessUrl("/assets/logout.html");
}
}
过滤器类如下所示:
@WebFilter(urlPatterns = "/*", initParams = {
@WebInitParam(
name = "keycloak.config.file",
value = "./config/saml.xml"
)})
public class SingleSignOnFilter extends SamlFilter {
private static final String loginGc = "/gc/";
private static final String logoutUrl = "/gc/assets/logout.html";
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain)throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) request;
HttpServletResponse httpResponse = (HttpServletResponse) response;
String requestPath = httpRequest.getRequestURI();
boolean needAuthentication = !requestPath.equals(logoutUrl);
boolean alreadyLoginGc = !requestPath.equals(loginGc);
if (needAuthentication) {
if (alreadyLoginGc) {
super.doFilter(request, response, chain);
} else {
httpResponse.setHeader("Cache-Control", "no-cache, no
store");
super.doFilter(request, response, chain);
}
} else {
chain.doFilter(request, response);
}
}
}
当我调用httpRequest.getUserPrincipal();
此方法时,它将返回 Nullpoint 异常。
当我试图获得经过身份验证的用户时,它会返回annonymousUser
。
Authentication auth = SecurityContextHolder.getContext()
.getAuthentication();
auth.getName();
Saml.xml 如下所示:
<keycloak-saml-adapter>
<SP entityID="https://localhost/gc" sslPolicy="NONE">
<PrincipalNameMapping policy="FROM_NAME_ID"/>
<IDP entityID="************************">
<SingleSignOnService requestBinding="POST"
validateResponseSignature="true"
bindingUrl="********************************"/>
<SingleLogoutService requestBinding="REDIRECT"
responseBinding="REDIRECT"
redirectBindingUrl="***************************"/>
<Keys>
<Key signing="true">
<CertificatePem>
-----BEGIN CERTIFICATE-----
##########################
###### Dummy Data ########
##########################
-----END CERTIFICATE-----
</CertificatePem>
</Key>
</Keys>
</IDP>
</SP>
</keycloak-saml-adapter>
解决方案
我不确定您正在使用的过滤器实现是否处理下面的弹簧安全所需的逻辑,但很明显SecurityContextHolder
没有填充,因为没有配置适配器来这样做。
Keycloak 提供了一个Spring Security Adapter,尝试使用它。它也会填充httpRequest.getUserPrincipal()
。
推荐阅读
- python - Python多行注释在终端中不起作用
- java - Maven 在 maven-remote-resources-plugin 上失败:查找远程资源清单时出错
- javascript - JS/React 多个 cookie
- ruby-on-rails - 如何接受参数并使用它们来创建子对象
- c# - libVLCSharp 无法创建 MediaList
- python - 我想将excel文件数据导入django数据库表,如何解决以下错误?
- java - 如何在其他按钮单击时获得隐形按钮
- oracle - 在 Oracle Apex 18.1 中,交互式网格不显示 HTML 表达式列
- java - Converting a List of POJO into List of some other POJO in Java Stream
- python - 如何使用do/while?