简体   繁体   English

春季启动。 HMAC认证。 如何添加自定义AuthenticationProvider和身份验证过滤器?

[英]Spring Boot. HMAC authentication. How to add custom AuthenticationProvider and Authentication filter?

To implement HMAC authentication I made my own filter, provider and token. 为了实现HMAC身份验证,我创建了自己的过滤器,提供者和令牌。 RestSecurityFilter: RestSecurityFilter:

public class RestSecurityFilter extends AbstractAuthenticationProcessingFilter {
private final Logger LOG = LoggerFactory.getLogger(RestSecurityFilter.class);

private AuthenticationManager authenticationManager;

public RestSecurityFilter(String defaultFilterProcessesUrl) {
    super(defaultFilterProcessesUrl);
}

public RestSecurityFilter(RequestMatcher requiresAuthenticationRequestMatcher) {
    super(requiresAuthenticationRequestMatcher);
}

@Override
public Authentication attemptAuthentication(HttpServletRequest req, HttpServletResponse response) throws AuthenticationException, IOException, ServletException {
    AuthenticationRequestWrapper request = new AuthenticationRequestWrapper(req);

    // Get authorization headers
    String signature = request.getHeader("Signature");
    String principal = request.getHeader("API-Key");
    String timestamp = request.getHeader("timestamp");
    if ((signature == null) || (principal == null) || (timestamp == null))
    unsuccessfulAuthentication(request, response, new BadHMACAuthRequestException("Authentication attempt failed! Request missing mandatory headers."));


    // a rest credential is composed by request data to sign and the signature
    RestCredentials credentials = new RestCredentials(HMACUtils.calculateContentToSign(request), signature);

    // Create an authentication token
    return new RestToken(principal, credentials, Long.parseLong(timestamp));
}

@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
    LOG.debug("Filter request: " + req.toString());
    HttpServletRequest request = (HttpServletRequest) req;
    HttpServletResponse response = (HttpServletResponse) res;

    chain.doFilter(request, response);

    Authentication authResult;

    try {
        authResult = attemptAuthentication(request, response);
        if (authResult == null)
            unsuccessfulAuthentication(request, response, new BadHMACAuthRequestException("Authentication attempt failed !"));

    } catch (InternalAuthenticationServiceException failed) {
        LOG.error("An internal error occurred while trying to authenticate the user.", failed);
        unsuccessfulAuthentication(request, response, failed);
    } catch (AuthenticationException failed) {
        // Authentication failed
        unsuccessfulAuthentication(request, response, failed);
    }
}
}

Authentication provider: 认证提供者:

@Component
public class RestAuthenticationProvider implements AuthenticationProvider {
private final Logger LOG = LoggerFactory.getLogger(RestAuthenticationProvider.class);

private ApiKeysService apiKeysService;

@Autowired
public void setApiKeysService(ApiKeysService apiKeysService) {
    this.apiKeysService = apiKeysService;
}

@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
    RestToken restToken = (RestToken) authentication;

    // api key (aka username)
    String principal = restToken.getPrincipal();

    LOG.info("Authenticating api key: '" + principal + "'");

    // check request time, 60000 is one minute
    long interval = Clock.systemUTC().millis() - restToken.getTimestamp();
    if ((interval < 0) && (interval > 60000))
        throw new BadHMACAuthRequestException("Auth Failed: old request.");

    // hashed blob
    RestCredentials credentials = restToken.getCredentials();

    // get secret access key from api key
    ApiKey apiKey = apiKeysService.getKeyByName(principal).orElseThrow(() -> new NotFoundException("Key not found for: '" + principal + "'"));
    String secret = apiKey.getApiKey();

    // calculate the hmac of content with secret key
    String hmac = HMACUtils.calculateHMAC(secret, credentials.getRequestData());
    LOG.debug("Api Key '{}', calculated hmac '{}'");

    // check if signatures match
    if (!credentials.getSignature().equals(hmac)) {
        throw new BadHMACAuthRequestException("Auth Failed: invalid HMAC signature.");
    }

    return new RestToken(principal, credentials, restToken.getTimestamp(), apiKeysService.getPermissions(apiKey));
}

@Override
public boolean supports(Class<?> authentication) {
    return RestToken.class.equals(authentication);

}
}

I don't know how to configure WebSecurityConfig to authenticate every request with my filter and Authentication Provider. 我不知道如何配置WebSecurityConfig来使用我的过滤器和身份验证提供程序对每个请求进行身份验证。 I assume I need to create @Bean to initialize RestSecurityFilter . 我假设我需要创建@Bean来初始化RestSecurityFilter Also JavaDoc for AbstractAuthenticationProcessingFilter says I need to the authenticationManager property. 另外, AbstractAuthenticationProcessingFilter JavaDoc说我需要authenticationManager属性。 I would appreciate working solution with custom filter, provider and token. 我希望使用自定义过滤器,提供程序和令牌的工作解决方案

I'm not familiar with Spring Boot, but I saw your comment on my question How To Inject AuthenticationManager using Java Configuration in a Custom Filter 我不熟悉Spring Boot,但是我看到你对我的问题的评论如何在自定义过滤器中使用Java配置注入AuthenticationManager

In a traditional Spring Security XML configuration, you would specify your custom RestSecurityFilter like so 在传统的Spring Security XML配置中,您可以像这样指定自定义RestSecurityFilter

<http use-expressions="true" create-session="stateless" authentication-manager-ref="authenticationManager" entry-point-ref="restAuthenticationEntryPoint">
       <custom-filter ref="restSecurityFilter" position="FORM_LOGIN_FILTER" />
</http>

More information http://docs.spring.io/spring-security/site/docs/4.0.1.RELEASE/reference/htmlsingle/#ns-custom-filters 更多信息http://docs.spring.io/spring-security/site/docs/4.0.1.RELEASE/reference/htmlsingle/#ns-custom-filters

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Spring Security自定义身份验证 - AuthenticationProvider与UserDetailsS​​ervice - Spring Security Custom Authentication - AuthenticationProvider vs UserDetailsService 在自定义身份验证过滤器上处理Spring Boot上的错误 - Handle error on Spring Boot at custom authentication filter CORS 允许自定义身份验证过滤器 | Spring开机 - CORS allowed custom authentication filter | Spring boot Spring boot 自定义身份验证过滤器未应用 - Spring boot Custom authentication filter is not applied Spring 引导应用程序具有两个身份验证。 AuthenticationManager bean 问题 - Spring boot app with two authentication. AuthenticationManager beans problem Spring Security AuthenticationProvider-扩展身份验证 - Spring Security AuthenticationProvider - extends Authentication 如何在Spring Boot中配置自定义身份验证和授权? - How to configure Custom Authentication and Authorization in spring boot? 如何在春季启动时配置自定义AccessDecisionManager和自定义AuthenticationProvider - How to configure custom AccessDecisionManager and custom AuthenticationProvider in spring boot Spring 引导 - 不使用 WebSecurityConfigurerAdapter 的自定义身份验证过滤器 - Spring Boot - Custom Authentication Filter without using the WebSecurityConfigurerAdapter 如何在 Spring Security 中创建自定义身份验证过滤器? - How to create a custom authentication filter in Spring Security?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM