问题描述
我正在尝试为我的微服务应用程序的所有REST API实现基于HMAC的身份验证(以了解有关HMAC refer this的更多信息)。我已经在Spring安全代码下面实现了,但是无法使该应用程序与Spring Security一起使用。
@Configuration
@EnableWebSecurity
@Order(1)
public class RESTSecurityConfig extends WebSecurityConfigurerAdapter {
@Bean
public RESTSecurityFilter authenticationFilter() throws Exception {
RESTSecurityFilter authenticationFilter = new RESTSecurityFilter("/");
authenticationFilter.setAuthenticationManager(authenticationManagerBean());
return authenticationFilter;
}
@Bean
public RESTAuthenticationProvider authenticationProvider() {
RESTAuthenticationProvider provider = new RESTAuthenticationProvider();
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;
}
}
RESTAuthenticationProvider
public class RESTAuthenticationProvider extends AbstractUserDetailsAuthenticationProvider {
private static final Logger log = LoggerFactory.getLogger(RESTAuthenticationProvider.class);
@Autowired
private UserSecurityService userSecurityService;
@Override
protected void additionalAuthenticationChecks(UserDetails userDetails,UsernamePasswordAuthenticationToken authentication) throws AuthenticationException {
RESTAuthenticationToken token = (RESTAuthenticationToken) authentication;
if (token != null) {
if (authentication.getCredentials() == null) {
log.debug("Authentication Failed: no credentials provided");
throw new BadCredentialsException(messages.getMessage("badCredentials","Bad credentials"));
}
RESTCredentials restCredentials = (RESTCredentials) authentication.getCredentials();
log.info("==========userDetails.getpassword() = {}",userDetails.getpassword());
log.info("=============restCredentials.getRequestSalt() = {}",restCredentials.getRequestSalt());
log.info("=============restCredentials.getSecureHash() = {}",restCredentials.getSecureHash());
// Check if signature and hashSignature matches and return API response
} else {
throw new AuthenticationCredentialsNotFoundException(
messageformat.format("Expected Authentication Token object of type {0},but instead received {1}",RESTAuthenticationToken.class.getSimpleName(),authentication.getClass().getSimpleName()));
}
}
@Override
protected UserDetails retrieveUser(String apiKey,UsernamePasswordAuthenticationToken authentication)
throws AuthenticationException {
log.info("Loading user by apikey = {}",apiKey);
UserDetails loadedUser;
try {
loadedUser = userSecurityService.getUserByApiKey(apiKey);
log.info("########### Loaded user = {}",loadedUser);
} catch (UsernameNotFoundException notFound) {
throw notFound;
}
if (loadedUser == null) {
throw new AuthenticationServiceException("UserSecurityServiceImpl returned null,which is an interface contract violation");
}
return loadedUser;
}
}
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);
}
}
UserSecurityRepository
public interface UserSecurityRepository {
UserDetails getUserByUsername(String username);
UserDetails getUserByApiKey(String apiKey);
}
UserSecurityService
@Service
public interface UserSecurityService extends UserDetailsService {
UserDetails getUserByApiKey(String apiKey);
}
有没有提供程序的简单有效的方法来在过滤器中对API进行身份验证吗?我已经在过滤器中向用户发送了“签名”和“ hashSignature”,所以只想比较它们,如果两者匹配则返回API json响应。
非常感谢您的帮助!谢谢
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)