Spring Security - Unable to Autowire UserDetailsService in DaoAuthenticationProvider

白昼怎懂夜的黑 提交于 2021-01-29 06:07:52

问题


In my usecase I don't have a User DB table to authenticate the user password. I am using HMAC signature which client sends in API request. On server side I calculate the same HMAC signature and just need to match them for successful authentication.

So I was thinking on using DaoAuthenticationProvider which Spring Security provides, without writing own custom provider class.

Following are all the files I have. My Spring boot application does not build when I @Autowired private UserDetailsService userDetailsService. Am I missing something?

RESTSecurityConfig

@Configuration
@EnableWebSecurity
@Order(1)
public class RESTSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private UserDetailsService userDetailsService;      // <---- build fails when I try to autowire

    @Bean
    public RESTSecurityFilter authenticationFilter() throws Exception {
        RESTSecurityFilter authenticationFilter = new RESTSecurityFilter("/");
        authenticationFilter.setAuthenticationManager(authenticationManagerBean());
        return authenticationFilter;
    }

    @Bean
    public DaoAuthenticationProvider authenticationProvider() {
        DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
        provider.setUserDetailsService(userDetailsService);
        return provider;
    }

    
    @Autowired
    public void configAuthentication(AuthenticationManagerBuilder auth) {
        auth.authenticationProvider(authenticationProvider());
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {          
        http.authorizeRequests().anyRequest().authenticated().and().addFilterBefore(authenticationFilter(),
                UsernamePasswordAuthenticationFilter.class);
    }
}

RESTSecurityFilter

public class RESTSecurityFilter extends AbstractAuthenticationProcessingFilter {

private static final Logger log = LoggerFactory.getLogger(RESTSecurityFilter.class);
private static final String ACCESS_KEY_PARAMETER_NAME = "x-access-key";
private static final String SIGNATURE_PARAMETER_NAME = "x-signature";
private static final String NONCE_PARAMETER_NAME = "x-nonce";
private static final String TIMESTAMP_PARAMETER_NAME = "x-timestamp";
private static final String SECRET_KEY = "xxxxxxxxxxxxxxxxx";

protected RESTSecurityFilter(String defaultFilterProcessesUrl) {
    super(defaultFilterProcessesUrl);
}

@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
        throws AuthenticationException, IOException, ServletException {
    String accessKey = getHeaderValue(request, ACCESS_KEY_PARAMETER_NAME);
    String signature = getHeaderValue(request, SIGNATURE_PARAMETER_NAME);
    String nonce = getHeaderValue(request, NONCE_PARAMETER_NAME);
    String timestamp = getHeaderValue(request, TIMESTAMP_PARAMETER_NAME);       
    String message = accessKey + ":" + nonce + ":" + timestamp;
    String hashSignature = null;
    try {
        hashSignature = HMacUtility.calculateHmac(message, SECRET_KEY);
        log.info("hashSignature : {}", hashSignature);
    }
    catch (InvalidKeyException | SignatureException | NoSuchAlgorithmException e) {
        e.printStackTrace();
    }

    AbstractAuthenticationToken authRequest = createAuthenticationToken(accessKey,
            new RESTCredentials(signature, hashSignature));

    // Allow subclasses to set the "details" property
    setDetails(request, authRequest);

    return this.getAuthenticationManager().authenticate(authRequest);
}

@Override
protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain,
        Authentication authResult) throws IOException, ServletException {
    super.successfulAuthentication(request, response, chain, authResult);
    chain.doFilter(request, response);
}

private String getHeaderValue(HttpServletRequest request, String headerParameterName) {
    return (request.getHeader(headerParameterName) != null) ? request.getHeader(headerParameterName) : "";
}

private AbstractAuthenticationToken createAuthenticationToken(String apiKeyValue, RESTCredentials restCredentials) {
    return new RESTAuthenticationToken(apiKeyValue, restCredentials);
}

protected void setDetails(HttpServletRequest request, AbstractAuthenticationToken authRequest) {
    authRequest.setDetails(authenticationDetailsSource.buildDetails(request));
}

@Override
protected boolean requiresAuthentication(HttpServletRequest request, HttpServletResponse response) {
    return true;
}
}

RESTCredentials

public final class RESTCredentials {
    private String requestSalt;
    private String secureHash;
    private RESTCredentials() {}

    public RESTCredentials(String requestSalt, String secureHash) {
        this.requestSalt = requestSalt;
        this.secureHash = secureHash;
    }

    public String getRequestSalt() {
        return requestSalt;
    }

    public String getSecureHash() {
        return secureHash;
    }
}

RESTAuthenticationToken

public class RESTAuthenticationToken extends UsernamePasswordAuthenticationToken {    
    private static final long serialVersionUID = 1L;

    public RESTAuthenticationToken(Object principal, Object credentials) {
        super(principal, credentials);
    }

    public RESTAuthenticationToken(Object principal, Object credentials,
            Collection<? extends GrantedAuthority> authorities) {
        super(principal, credentials, authorities);
    }    
}

Is there a simple and efficient way to Authenticate API in filter without the provider? I have "signature" and "hashSignature" both in filter so just want to compare them and return the API json response if both of them match.

Thanks

来源:https://stackoverflow.com/questions/64082698/spring-security-unable-to-autowire-userdetailsservice-in-daoauthenticationprov

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!