You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用API Key与Secret保护无用户认证的Spring Boot API

我之前刚好帮朋友实现过一模一样的需求——不需要用户登录,只靠API Key/Secret来限制特定客户端访问Spring Boot接口,给你一套完整的落地方案:

具体实现方案

1. 配置API Key和Secret

首先把你的API密钥对存在配置文件里,绝对不要硬编码到代码中。在application.yml里添加:

api:
  auth:
    key: YOUR_UNIQUE_API_KEY  # 替换成你自己的唯一Key
    secret: YOUR_STRONG_API_SECRET  # 替换成你自己的高强度Secret

然后创建一个配置类来读取这些值,方便后续逻辑调用:

@ConfigurationProperties(prefix = "api.auth")
@Component
@Data  // 用Lombok简化getter/setter,没有Lombok的话手动写也可以
public class ApiAuthProperties {
    private String key;
    private String secret;
}

2. 编写认证拦截器

用Spring的HandlerInterceptor实现请求前的校验逻辑,拦截所有接口请求,检查请求头里的API密钥对是否有效:

@Component
public class ApiAuthInterceptor implements HandlerInterceptor {

    private final ApiAuthProperties apiAuthProperties;

    // 构造注入配置类
    public ApiAuthInterceptor(ApiAuthProperties apiAuthProperties) {
        this.apiAuthProperties = apiAuthProperties;
    }

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 从请求头获取客户端传来的Key和Secret
        String requestApiKey = request.getHeader("X-API-Key");
        String requestApiSecret = request.getHeader("X-API-Secret");

        // 第一步:检查密钥对是否为空
        if (StringUtils.isEmpty(requestApiKey) || StringUtils.isEmpty(requestApiSecret)) {
            sendErrorResponse(response, HttpStatus.UNAUTHORIZED, "Missing API Key or Secret");
            return false;
        }

        // 第二步:检查密钥对是否匹配配置值
        if (!apiAuthProperties.getKey().equals(requestApiKey) || !apiAuthProperties.getSecret().equals(requestApiSecret)) {
            sendErrorResponse(response, HttpStatus.UNAUTHORIZED, "Invalid API Key or Secret");
            return false;
        }

        // 校验通过,放行请求
        return true;
    }

    // 统一返回JSON格式的错误响应
    private void sendErrorResponse(HttpServletResponse response, HttpStatus status, String message) throws IOException {
        response.setStatus(status.value());
        response.setContentType("application/json;charset=UTF-8");
        response.getWriter().write("{\"code\": " + status.value() + ", \"message\": \"" + message + "\"}");
    }
}

这里用到的StringUtils是Spring Core里的工具类,Spring Boot项目默认已经包含依赖。

3. 注册拦截器,指定拦截范围

创建一个WebMvc配置类,把刚才的拦截器注册进去,明确要拦截的接口路径(比如所有/api/**开头的接口),如果有不需要校验的公开接口(比如健康检查),可以直接排除:

@Configuration
public class WebMvcConfig implements WebMvcConfigurer {

    private final ApiAuthInterceptor apiAuthInterceptor;

    public WebMvcConfig(ApiAuthInterceptor apiAuthInterceptor) {
        this.apiAuthInterceptor = apiAuthInterceptor;
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(apiAuthInterceptor)
                .addPathPatterns("/api/**")  // 拦截所有API接口,根据你的实际路径调整
                .excludePathPatterns("/api/public/health");  // 排除公开的健康检查接口
    }
}

4. 客户端调用方式

你的第三方前端在调用API时,只需要在请求头里带上X-API-Key和X-API-Secret两个字段即可,比如用Axios的示例:

axios.get('/api/data', {
  headers: {
    'X-API-Key': 'YOUR_UNIQUE_API_KEY',
    'X-API-Signature': 'YOUR_STRONG_API_SECRET'
  }
})

可选优化:更安全的签名机制

如果担心Secret在网络传输中被窃取,可以改用请求签名的方式,Secret不会直接在请求中传输:

  1. 客户端生成当前时间戳timestamp,将请求参数(或请求体JSON)+时间戳用Secret做HMAC-SHA256加密,得到signature
  2. 客户端请求时携带X-API-Key、X-API-Timestamp、X-API-Signature三个请求头
  3. 服务端先校验时间戳是否在有效期内(比如5分钟),防止重放攻击;再用同样的规则计算签名,和客户端传来的对比是否一致

这种方式即使Key被泄露,没有Secret也无法生成有效的签名,安全性会更高。


内容的提问来源于stack exchange,提问作者Vitalii Oleksiv

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 04:10:04