说明:
为了防止别人随意调用我们接口,需要提供用户与密码才能访问,这就是基本的HTTP Basic authentication 认证。
以下我提供认证代码以及调用接口测试有用例:
一、测试用例
@Slf4j
public class GhWebServiceTest {
String ghRequestUrl = "http://www.XXX/find";
@Test
public void web_service_test() {
String sendJson = "{\"op\":\"find\"}";
String resultStr = sendPostRequest(ghRequestUrl, sendJson);
System.out.println("返回:" + resultStr);
}
private String sendPostRequest(String url, String params) {
RestTemplate client = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
// 提供认证的用户与密码
headers.setBasicAuth("user", "pw123");
HttpMethod method = HttpMethod.POST;
// application/json
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<String> requestEntity = new HttpEntity<>(params, headers);
ResponseEntity<String> response = client.exchange(url, method, requestEntity, String.class);
return response.getBody();
}
}
二、服务端认证以及处理思路
1、提供服务的api,在spring mvc配置时,分开认证,因为接口只是提供特定人使用
在主程序过滤器排除调用你服务api,如:
.excludePathPatterns(WEB_SERVICE_PATHS);
添加上你的配置: registry.addInterceptor(basicAuthInterceptor) .addPathPatterns(WEB_SERVICE_PATHS);
2、获取认证用户与密码,并校验是否正确
2.1获取头部的用户与密码基类:
package com.ml.module.webbase;
import com.google.common.base.Strings;
import com.ml.support.codec.Encodes;
import com.ml.support.core.BusinessException;
import com.ml.support.core.ErrorCode;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.nio.charset.StandardCharsets;
import java.util.Objects;
/**
* 进行http basic 认证的基类
*/
@Slf4j
public abstract class BaseHttpBasicAuthInterceptor extends HandlerInterceptorAdapter {
private static final String KEY_PREFIX_AUTH = "Basic ";
private static final String KEY_BASIC_AUTH_SEP = ":";
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
String header = request.getHeader("Authorization");
if (Strings.isNullOrEmpty(header) || !StringUtils.startsWithIgnoreCase(header, KEY_PREFIX_AUTH))
throw BusinessException.with(ErrorCode.ERR_10025);
try {
String authContent = new String(Encodes.decodeBase64(StringUtils.substringAfter(header, KEY_PREFIX_AUTH)), StandardCharsets.UTF_8);
String[] keyAndSecret = StringUtils.split(authContent, KEY_BASIC_AUTH_SEP);
if (Objects.isNull(keyAndSecret) || keyAndSecret.length != 2) throw BusinessException.with(ErrorCode.ERR_10025);
afterGetBasicString(keyAndSecret[0], keyAndSecret[1]);
} catch (Exception e) {
throw BusinessException.with(ErrorCode.ERR_10025);
}
return true;
}
// 在此方法里实现用户与密码认证
public abstract void afterGetBasicString(String key, String secret);
}
2.2继承基类,并认证用户与密码,以下我简单实现:
@Slf4j
@Component
public class BasicAuthInterceptor extends BaseHttpBasicAuthInterceptor {
@Override
public void afterGetBasicString(String key, String secret) {
if ("user".equals(key) && "pw123".equals(secret)) {
log.debug("认证通过");
} else {
log.error("notice请求[{}:{}]校验失败", key, secret);
BusinessException.throwConstraintException("appKey/appSecret不正确");
}
}
}