当前位置: 首页 > 知识库问答 >
问题:

多身份验证提供程序--LDAP、JWT、Oauth2和Spring Boot应用程序中的基本身份验证

东郭腾
2023-03-14

现在,我们有了集成执行器。我希望我的执行器endpoint可以通过基本认证在浏览器中访问。

为此,我用@order(1)添加了WebSecurityConfigurerAdapter的一个实现。它在浏览器上工作得很好。但是,当我从angualar应用程序调用登录url时,它为/oauth/token url给出了401个未经授权的错误,因此我无法从ui应用程序登录。

任何帮助将感谢解决此错误。

类别:

    @Configuration
    @Order(1)
    public class FormLoginWebSecurityConfigurerAdapter extends 
          WebSecurityConfigurerAdapter {

    @Override
    protected void configure(final AuthenticationManagerBuilder auth) throws Exception {
    auth.inMemoryAuthentication().withUser("actuator") 
     .password(passwordEncoder().encode("actuator")).roles("ACTUATOR_ADMIN");
  }

    @Override
    protected void configure(final HttpSecurity http) throws Exception {
    http.antMatcher("/actuator/**").authorizeRequests().anyRequest().hasRole("ACTUATOR_ADMIN").and()
        .httpBasic();

  }

  @Bean
  public PasswordEncoder passwordEncoder() {
    return new BCryptPasswordEncoder();
  }

}

谢了。

共有1个答案

逄皓轩
2023-03-14

因此,我自己也遇到了这个问题(OAuth+Basic Auth),并最终选择了一条不同的道路,在Basic Auth部分中涉及更多,但最终它成功了。

首先,您需要实现自己的身份验证对象:

import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;

import java.util.Collection;
import java.util.Collections;

public class ActuatorAuthentication implements Authentication {

    private static final Object DUMMY = new Object();
    private static final String NAME = "Actuator Authenticated";
    private static final boolean AUTHENTICATED = true;

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        return Collections.emptyList();
    }

    @Override
    public Object getCredentials() {
        return DUMMY;
    }

    @Override
    public Object getDetails() {
        return DUMMY;
    }

    @Override
    public Object getPrincipal() {
        return DUMMY;
    }

    @Override
    public boolean isAuthenticated() {
        return authenticated;
    }

    @Override
    public void setAuthenticated(boolean b) throws IllegalArgumentException {
        throw new UnsupportedOperationException("Operation setAuthenticated not supported.");
    }

    @Override
    public String getName() {
        return NAME;
    }
}

我们将使用此方法与AutoConfiguredHealthEndpointGroup.isAuthorized()方法一起切换我们需要的行为,当我们配置了以下内容时:

management:
  endpoint:
    health:
      show-details: when_authorized

我们还将确保/health将返回基本的updown

其代码最终为:

import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.util.AntPathMatcher;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Base64;

public class ActuatorSecurityFilter extends OncePerRequestFilter {

    private static final String[] EXCLUDED_ENDPOINTS = {
            "/actuator/health/liveness",
            "/actuator/health/readiness",
            "/actuator/info"
    };

    private AntPathMatcher pathMatcher = new AntPathMatcher();

    private final String username;
    private final String password;
    
    public ActuatorSecurityFilter(String username, String password) {
        this.username = username;
        this.password = password;
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException {
        boolean authorized = false;

        String authorization = request.getHeader("Authorization");
        if (authorization != null) {
            // Authorization: Basic base64credentials
            String base64Credentials = authorization.substring("Basic".length()).trim();
            byte[] credDecoded = Base64.getDecoder().decode(base64Credentials);
            String credentials = new String(credDecoded, StandardCharsets.UTF_8);
            // credentials = username:password
            final String[] values = credentials.split(":", 2);

            if (values.length == 2 && username.equals(values[0]) && password.equals(values[1])) {
                authorized = true;
            }
        }

        // Handle specific non-auth vs. auth for actuator health
        if (pathMatcher.match("/actuator/health", request.getRequestURI())) {
            if (authorized) {
                // Utilize Dummy Authentication to show full details
                Authentication authentication = new ActuatorAuthentication();
                SecurityContextHolder.getContext().setAuthentication(authentication);
            } else {
                // Ensure no authentication is provided to show basic details if auth is incorrect
                SecurityContextHolder.getContext().setAuthentication(null);
            }
        } else if (!authorized) {
            response.sendError(401);
            return;
        }

        chain.doFilter(request, response);
    }

    @Override
    protected boolean shouldNotFilter(HttpServletRequest request) {
        for (String endpoint : EXCLUDED_ENDPOINTS) {
            if (pathMatcher.match(endpoint, request.getRequestURI())) {
                return true;
            }
        }
        return false;
    }

}

最后,我们希望将它与我们自己的配置类连接在一起:

import com.cantire.sps.application.filter.ActuatorSecurityFilter;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class ActuatorSecurityConfiguration {

    @Value("${actuator.username}")
    private String username;

    @Value("${actuator.password}")
    private String password;

    @Bean
    FilterRegistrationBean<ActuatorSecurityFilter> securityFilterRegistration() {
        FilterRegistrationBean<ActuatorSecurityFilter> registration = new FilterRegistrationBean<>();
        registration.setFilter(new ActuatorSecurityFilter(username, password));
        registration.addUrlPatterns("/actuator/*");
        return registration;
    }
}
actuator:
  username: monitor
  password: password
 类似资料:
  • 我正在尝试为正在进行的 spring-boot 项目实现身份验证和授权服务。我已经实现了一个基于 JPA 的身份验证提供程序,它工作正常。如何将 LDAP 身份验证提供程序添加到同一项目并根据用户身份验证类型在身份验证方法之间切换? 下面是我的代码 虽然我的LDAP证书是正确的,但它没有达到那个方法。如何从DB ex(LDAP、JPA、SSO)获取我的应用程序的身份验证方法,并执行相应的身份验证提

  • 我正在尝试使用OAuth2实现开发一个带有Spring Security性的rest api。但是如何删除基本身份验证呢。我只想向body发送用户名和密码,并在postman上获取令牌。 要删除基本身份验证,并从邮递员的get token中发送body标记中的用户名密码吗 我遇到了一些问题{"错误":"未经授权","error_description":"没有客户端身份验证。尝试添加适当的身份验证

  • 问题内容: 使用Passport.js是否可以为同一路由指定多个身份验证提供程序? 例如(在护照指南中),我可以在以下示例路线中使用本地策略以及Facebook和Twitter策略吗? 问题答案: Passport的中间件的构建方式使您可以在一个呼叫中使用多种策略。 但是,它是用OR顺序定义的。也就是说,只有在所有策略均未成功返回的情况下,它才会失败。 这是您将如何使用它: 换句话说,使用它的方法

  • 我正在使用SpringBoot开发具有微服务架构的Rest Backend。为了保护endpoint,我使用了JWT令牌机制。我正在使用Zuul API网关。 如果请求需要权限(来自JWT的角色),它将被转发到正确的微服务。Zuul api网关的“WebSecurityConfigrerAdapter”如下。 这样,我必须在这个类中编写每个请求授权部分。因此,我希望使用方法级安全性,即“Enabl

  • 我的问题是,我希望有两个身份验证提供商 之前:我有我的UserDetailServiceImpl,我根据数据库中的数据验证了用户的身份(不确定是哪个提供者) 现在:我使用了ActiveDirectoryLdapAuthentiation提供程序,如下所示 我成功了,所以我可以认证。 问题是: 我现在无法再使用数据库用户登录,现在只有LDAP。 未使用UserDetailsService,因此用户具

  • 我正在尝试在Spring身份验证服务器(Spring Security)中配置多个身份验证提供程序(主要和次要) 根据“身份验证”方法留档: 返回:包含凭据的完全经过身份验证的对象。如果AuthenticationProvider无法支持对传递的身份验证对象的身份验证,则可能返回null。在这种情况下,将尝试下一个支持提供的身份验证类的AuthenticationProvider。 如果身份验证失