如何使用 Spring Security 模拟身份验证和授权

Posted

技术标签:

【中文标题】如何使用 Spring Security 模拟身份验证和授权【英文标题】:How to mock authentication and authorization with Spring Security 【发布时间】:2020-03-15 08:10:10 【问题描述】:

我有一个 spring-boot REST API 应用程序。 REST 端点受 spring-security 保护。

这是spring-security的配置:

protected void configure(HttpSecurity httpSecurity) throws Exception 
    httpSecurity
            .exceptionHandling().authenticationEntryPoint(new CustomForbiddenErrorHandler())
            .and()

            .sessionManagement()
            .sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()

            .authorizeRequests()
            .antMatchers("/api/**").authenticated() // HTTP 403 if the request is not authenticated
            .antMatchers("/**").permitAll();

它工作正常。如果我在 HTTP 标头上没有授权令牌的情况下进行休息调用,我会返回正确的 HTTP 错误代码。

如果没有按顺序显示,我可以强制 spring 以某种方式添加一个自我身份验证令牌,这样我就可以在没有自己的访问管理系统的情况下进行 REST 调用吗?稍后安装。

我不是在问如何编写 JUnit 测试。我要问的是如何动态生成模拟身份验证令牌,如果不存在则将其添加到请求中。

【问题讨论】:

Spring Test & Security: How to mock authentication?的可能重复 【参考方案1】:

您可以覆盖现有的身份验证过滤器,或创建新的自定义过滤器,以检查请求是否包含不记名令牌。根据结果​​,您可以按原样处理请求,也可以使用您的自定义身份验证对象扩充请求。

查看OAuth2AuthenticationProcessingFilter,这会从传入请求中提取 OAuth2 令牌并使用它来填充 Spring Security 上下文。您可以覆盖其行为或创建一个新过滤器,使用您的模拟身份验证对象填充安全上下文。

下面是一个示例代码,可帮助您入门:

@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException 
    boolean debug = logger.isDebugEnabled();
    HttpServletRequest request = (HttpServletRequest)req;
    HttpServletResponse response = (HttpServletResponse)res;

    try 
        Authentication authentication = this.tokenExtractor.extract(request);
        if (Objects.isNull(authentication)) 
            final UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken("username", "password");

            authenticationToken.setDetails(Collections.singletonMap("user_uuid", userUuid.toString()));

            final OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(null, authenticationToken);

            // You can either ask your authenticatoin manager to authenticate these credentials or directly publish auth success event with your mock auth object.

            this.eventPublisher.publishAuthenticationSuccess(oAuth2Authentication);
            SecurityContextHolder.getContext().setAuthentication(oAuth2Authentication);

         else 
            request.setAttribute(OAuth2AuthenticationDetails.ACCESS_TOKEN_VALUE, authentication.getPrincipal());
            if (authentication instanceof AbstractAuthenticationToken) 
                AbstractAuthenticationToken needsDetails = (AbstractAuthenticationToken)authentication;
                needsDetails.setDetails(this.authenticationDetailsSource.buildDetails(request));
            

            Authentication authResult = this.authenticationManager.authenticate(authentication);
            if (debug) 
                logger.debug("Authentication success: " + authResult);
            

            this.eventPublisher.publishAuthenticationSuccess(authResult);
            SecurityContextHolder.getContext().setAuthentication(authResult);
        

【讨论】:

以上是关于如何使用 Spring Security 模拟身份验证和授权的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Spring Security 中将令牌转换为身份验证?

如何在 Spring Security 中使用 LDAP 身份验证创建令牌

如何使用spring security使用空密码进行基本身份验证?

如何在同一应用程序中使用 spring-sample 示例配置 Spring Security 基本身份验证和 SAML 身份验证

如何正确使用配置器类实现 Spring Security Ldap 身份验证?

如何将 OAuth 身份验证与 Spring Security 联系起来