doFilter() 重写方法 httpRequest.getUserPrincipal() 总是返回 NullPoint 异常

Posted

技术标签:

【中文标题】doFilter() 重写方法 httpRequest.getUserPrincipal() 总是返回 NullPoint 异常【英文标题】:doFilter() overridden method httpRequest.getUserPrincipal() always return NullPoint Exception 【发布时间】:2019-04-17 00:57:10 【问题描述】:

我创建了 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 Exception。

当我尝试获取经过身份验证的用户时,它将返回 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>

【问题讨论】:

@dur SamlFilter 来自 keycloak-saml-servlet-filter-adapter 库。 那你就得切换了。先认证再访问。 【参考方案1】:

我不确定您使用的过滤器实现是否处理了下面的 spring 安全性所需的逻辑,但很明显 SecurityContextHolder 没有被填充,因为没有配置适配器来这样做。

Keycloak 提供了一个Spring Security Adapter,尝试使用它。它也将填充httpRequest.getUserPrincipal()

【讨论】:

以上是关于doFilter() 重写方法 httpRequest.getUserPrincipal() 总是返回 NullPoint 异常的主要内容,如果未能解决你的问题,请参考以下文章

SpringMVC过滤器Filter与拦截器Interceptor

jsp题库啥是serverlet过滤器?作用是?

Filter(过滤器)

Filter过滤器的基本使用方法

springsecurity添加过滤器怎么针对资源拦截

从 doFilter 方法设置 cookie