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

通过扩展WebSecurityConfigurerAdapter,如何构造具有自定义身份验证逻辑的configure

武博艺
2023-03-14
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

@Configuration
public class OktaOAuth2WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/health").permitAll()
                .anyRequest().authenticated()
                .and()
                .oauth2ResourceServer().jwt();

        http.cors();

        Okta.configureResourceServer401ResponseBody(http);

    }
}
import com.okta.spring.boot.oauth.Okta;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

@Configuration
public class OktaOAuth2WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/health").permitAll()
                .anyRequest().authenticated()
                .and()
                /*add something there*/

        http.cors();


    }
}

我的想法是重写身份验证提供程序,在提供程序中,点击okta内省endpoint,这会工作吗???

共有1个答案

贺懿轩
2023-03-14

我不使用Okta,所以我不知道它到底是如何工作的。但我有两个假设:

  • 每个请求的授权标头中都包含accessToken
  • 您向${baseUrl}/v1/introspect发出POST请求,它将回答您true或false,以指示accessToken是否有效

考虑到这两个假设,如果我必须手动实现自定义安全逻辑身份验证,我将执行以下步骤:

  • 注册并实现CustomAuthenticationProvider
  • 添加筛选器以从请求中提取访问令牌

正在注册自定义身份验证提供程序:

// In OktaOAuth2WebSecurityConfig.java
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    auth.authenticationProvider(customAuthenticationProvider());
}

@Bean
CustomAuthenticationProvider customAuthenticationProvider(){
    return new CustomAuthenticationProvider();
}

自定义身份验证提供者:

public class CustomAuthenticationProvider implements AuthenticationProvider {

private static final Logger logger = LoggerFactory.getLogger(CustomAuthenticationProvider.class);

@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
    logger.debug("Authenticating authenticationToken");
    OktaTokenAuthenticationToken auth = (OktaTokenAuthenticationToken) authentication;
    String accessToken = auth.getToken();

    // You should make a POST request to ${oktaBaseUrl}/v1/introspect
    // to determine if the access token is good or bad

    // I just put a dummy if here

    if ("ThanhLoyal".equals(accessToken)){
        List<GrantedAuthority> authorities = Collections.singletonList(new SimpleGrantedAuthority("USER"));
        logger.debug("Good access token");
        return new UsernamePasswordAuthenticationToken(auth.getPrincipal(), "[ProtectedPassword]", authorities);
    }
    logger.debug("Bad access token");
    return null;
}

@Override
public boolean supports(Class<?> clazz) {
    return clazz == OktaTokenAuthenticationToken.class;
}
// Still in OktaOAuth2WebSecurityConfig.java
@Override
protected void configure(HttpSecurity http) throws Exception {
    http
            .addFilterAfter(accessTokenExtractorFilter(), UsernamePasswordAuthenticationFilter.class)
            .authorizeRequests().anyRequest().authenticated();
            // And other configurations

}

@Bean
AccessTokenExtractorFilter accessTokenExtractorFilter(){
    return new AccessTokenExtractorFilter();
}
public class AccessTokenExtractorFilter extends OncePerRequestFilter {

private static final Logger logger = LoggerFactory.getLogger(AccessTokenExtractorFilter.class);

@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
    logger.debug("Filtering request");
    Authentication authentication = getAuthentication(request);
    if (authentication == null){
        logger.debug("Continuing filtering process without an authentication");
        filterChain.doFilter(request, response);
    } else {
        logger.debug("Now set authentication on the request");
        SecurityContextHolder.getContext().setAuthentication(authentication);
        filterChain.doFilter(request, response);
    }
}

private Authentication getAuthentication(HttpServletRequest request) {
    String accessToken = request.getHeader("Authorization");
    if (accessToken != null){
        logger.debug("An access token found in request header");
        List<GrantedAuthority> authorities = Collections.singletonList(new SimpleGrantedAuthority("USER"));
        return new OktaTokenAuthenticationToken(accessToken, authorities);
    }

    logger.debug("No access token found in request header");
    return null;
}

我在这里上传了一个简单的项目供您参考:https://github.com/mrloyal/spring-security-custom-authentication

工作原理:

  • AccessTokenExtractorFilter位于UsernamePasswordAuthenticationFilter之后,后者是Spring Security的默认筛选器
  • 请求到达,上面的筛选器从中提取accessToken并将其放置在SecurityContext中
  • 稍后,AuthenticationManager调用AuthenticationProvider对请求进行身份验证。在这种情况下,调用CustomAuthenticationProvider

在我的REST API中,我只是向客户机响应401 HTTP状态代码。

// CustomAuthenticationEntryPoint
@Override
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {
    response.reset();
    response.setStatus(401);
    // A utility method to add CORS headers to the response
    SecUtil.writeCorsHeaders(request, response);
}

Spring的LoginurlAuthenticationEntryPoint会将用户重定向到登录页面(如果配置了登录页面)。

因此,如果您想将未经身份验证的请求重定向到Okta的登录页面,您可以使用AuthenticationEntryPoint。

 类似资料:
  • 我已经用LDAP用户联盟配置了KeyClope。当用户想要登录到应用程序时,他会被重定向到KeyClope登录页面,输入uid/pwd,并使用LDAP绑定进行身份验证。 这还不足以满足我的需求,因为我想实现一些自定义身份验证逻辑,例如: 我如何将自己的身份验证逻辑包含到KeyClope中?

  • 问题内容: 这是我的情况: 一个Web应用程序对许多应用程序执行某种SSO 登录的用户,而不是单击链接,该应用就会向正确的应用发布包含用户信息(名称,pwd [无用],角色)的帖子 我正在其中一个应用程序上实现SpringSecurity以从其功能中受益(会话中的权限,其类提供的方法等) 因此,我需要开发一个 自定义过滤器 -我猜想-能够从请求中检索用户信息,通过自定义 DetailsUserSe

  • 问题内容: 我可以使用Google帐户在AppEngine中对用户进行身份验证的方式非常好。 但是,我需要使用 自定义的身份验证登录系统 。 我将有一个AppUsers表,其中包含用户名和加密密码。 我阅读了有关gae会话的内容,但在启动应用安全性方面需要帮助。 如何跟踪经过身份验证的用户会话?设置cookie? 初学者。 问题答案: 您可以使用cookie来做到这一点……其实并不难。您可以使用C

  • 我在spring MVC项目中实现了一个自定义身份验证提供程序。在我自己的重载authenticate()方法中,我实现了自己的身份验证,其中我构造了自己的UserPasswordAuthenticationToken()并返回对象。 现在,上述对象“UserPasswordAuthentictionToken”中的用户ID被匿名化,密码为null,权限设置为授予该用户的权限。 问题: 这是否会导

  • 问题内容: 我正在为Angular 5应用程序创建API。我想使用JWT进行身份验证。 我想使用Spring Security提供的功能,以便我可以轻松地使用角色。 我设法禁用基本身份验证。但是使用时我仍然会收到登录提示。 我只想输入403而不是提示。因此,通过检查令牌标题的“事物”(是否是过滤器?)来覆盖登录提示。 我只想在将返回JWT令牌的控制器中进行登录。但是我应该使用哪种Spring Se

  • 我正在为Angular 5应用程序创建API。我希望使用JWT进行身份验证。 我希望使用spring security提供的特性,以便能够轻松地处理角色。 我只想在返回JWT令牌的控制器中进行的登录。但是我应该使用什么Spring Securitybean来检查用户凭据呢?我可以构建自己的服务和存储库,但我希望尽可能使用spring security提供的特性。 这个问题的简短版本只是: 我如何自