问题描述
要实现HMAC认证我做我自己的过滤器,供应商和令牌。
RestSecurityFilter:
To implement HMAC authentication I made my own filter, provider and token.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);
}
}
}
身份验证提供:
@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);
}
}
我不知道该怎么WebSecurityConfig配置与我的过滤器和认证提供每个请求进行身份验证。我想我需要创建@Bean初始化 RestSecurityFilter
。此外JavaDoc时 AbstractAuthenticationProcessingFilter
说,我需要将的AuthenticationManager
属性。我想AP preciate正与自定义过滤器,供应商和令牌的解决方案。
I don't know how to configure WebSecurityConfig to authenticate every request with my filter and Authentication Provider. I assume I need to create @Bean to initialize RestSecurityFilter
. Also JavaDoc for AbstractAuthenticationProcessingFilter
says I need to the authenticationManager
property. I would appreciate working solution with custom filter, provider and token.
推荐答案
我不熟悉Spring引导,但我看到了我的问题<一个您的评论href=\"http://stackoverflow.com/questions/21633555/how-to-inject-authenticationmanager-using-java-configuration-in-a-custom-filter?noredirect=1#comment49096937_21633555\">How要在自定义过滤器使用Java配置注入AuthenticationManager会
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 Security XML配置,你就这样来指定自定义RestSecurityFilter
In a traditional Spring Security XML configuration, you would specify your custom RestSecurityFilter like so
<http use-expressions="true" create-session="stateless" authentication-manager-ref="authenticationManager" entry-point-ref="restAuthenticationEntryPoint">
<custom-filter ref="restSecurityFilter" position="FORM_LOGIN_FILTER" />
</http>
更多信息http://docs.spring.io/spring-security/site/docs/4.0.1.RELEASE/reference/htmlsingle/#ns-custom-filters
这篇关于春天启动。 HMAC认证。如何添加自定义的AuthenticationProvider和验证过滤器?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!