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

非Spring Boot Java应用:集成Keycloak实现REST接口无页面认证

可行解决方案

方案1:排除API登录路径的Keycloak拦截

Keycloak的Servlet适配器默认会拦截配置范围内的所有请求并触发重定向登录。你需要将/api/authentication/login路径从Keycloak的拦截范围中排除,让原有接口继续处理凭证校验,再通过Keycloak API获取令牌返回:

  • 在web.xml中配置Keycloak过滤器时,添加排除规则:
    <filter>
        <filter-name>Keycloak Filter</filter-name>
        <filter-class>org.keycloak.adapters.servlet.KeycloakOIDCFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>Keycloak Filter</filter-name>
        <url-pattern>/*</url-pattern>
        <exclude-url-pattern>/api/authentication/login</exclude-url-pattern>
    </filter-mapping>
    
  • 或者在Keycloak配置文件(keycloak.json)中添加排除规则:
    {
        "exclude-patterns": ["/api/authentication/login"]
    }
    
  • 排除后,原有接口可提取请求头中的Authorization凭证(如admin:admin),然后后端调用Keycloak的Token Endpoint(POST {keycloak-url}/realms/{你的realm}/protocol/openid-connect/token),使用password授权模式,传入参数:
    grant_type=password
    username=xxx
    password=xxx
    client_id=你的客户端ID
    client_secret=你的客户端密钥(若客户端为confidential类型)
    
    拿到Keycloak返回的令牌后,直接返回给调用方。

方案2:直接复用Keycloak密码授权模式替换原有接口

放弃原有自定义登录逻辑,将/api/authentication/login接口改造为Keycloak密码授权模式的代理:

  1. 在Keycloak控制台配置对应客户端:
    • 将客户端的Access Type设为confidential(需维护client secret)或public;
    • 在Advanced Settings > Grant Types中勾选Password;
  2. 后端接口接收请求中的用户名密码(可从Authorization头解析,或请求体参数),直接构造请求转发到Keycloak的Token Endpoint,参数同方案1中的password授权模式参数;
  3. 将Keycloak返回的令牌(包含access_token、refresh_token等)原样或包装后返回给调用方,无需自己校验凭证。

方案3:自定义Keycloak认证过滤器处理API路径

如果不想排除路径,可自定义过滤器继承Keycloak的BaseKeycloakFilter,针对/api/authentication/login路径做特殊处理:

  • 重写doFilter方法,判断当前请求路径是否为目标API:
    public class CustomKeycloakFilter extends BaseKeycloakFilter {
        @Override
        public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
            HttpServletRequest req = (HttpServletRequest) request;
            if ("/api/authentication/login".equals(req.getPathInfo())) {
                // 提取用户名密码(从Authorization头或请求体)
                String authHeader = req.getHeader("Authorization");
                String[] credentials = decodeBase64(authHeader.split(" ")[1]).split(":");
                String username = credentials[0];
                String password = credentials[1];
    
                // 调用Keycloak API校验凭证并获取令牌
                String token = fetchTokenFromKeycloak(username, password);
    
                // 返回令牌给客户端
                HttpServletResponse res = (HttpServletResponse) response;
                res.setContentType("application/json");
                res.getWriter().write("{\"access_token\":\"" + token + "\"}");
                return;
            }
            // 其他路径走正常Keycloak认证流程
            chain.doFilter(request, response);
        }
    
        private String fetchTokenFromKeycloak(String username, String password) {
            // 实现调用Keycloak Token Endpoint的逻辑,同方案1
            return "";
        }
    }
    
  • 在web.xml中替换原有的Keycloak过滤器为自定义过滤器。

关于你之前尝试无效的原因

新建覆盖/api路径的客户端并设置Client Authentication=false无法解决问题,因为Keycloak Servlet适配器通常是按应用全局配置拦截规则,路径与客户端的绑定并非直接生效;且默认的认证流程是针对浏览器的重定向授权,不会自动适配API的凭证校验场景,因此仍会触发登录页重定向。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 13:45:32