微服务和 Kerberos 身份验证

一则或许对你有用的小广告

欢迎加入小哈的星球 ,你将获得:专属的项目实战 / Java 学习路线 / 一对一提问 / 学习打卡/ 赠书活动

目前,正在 星球 内带小伙伴们做第一个项目:全栈前后端分离博客项目,采用技术栈 Spring Boot + Mybatis Plus + Vue 3.x + Vite 4手把手,前端 + 后端全栈开发,从 0 到 1 讲解每个功能点开发步骤,1v1 答疑,陪伴式直到项目上线,目前已更新了 204 小节,累计 32w+ 字,讲解图:1416 张,还在持续爆肝中,后续还会上新更多项目,目标是将 Java 领域典型的项目都整上,如秒杀系统、在线商城、IM 即时通讯、权限管理等等,已有 870+ 小伙伴加入,欢迎点击围观

kerberos 身份验证 用于保护各种大数据产品,如 apache hadoop 和最近的 apache kafka (>0.9)。在 hadoop 的情况下,它用于对每个用户和服务进行身份验证,以便使用 hadoop 生态系统。许多现代 nosql 数据库也提供对 kerberos 的支持,例如 apache cassandra 和 mongodb。 kerberos 身份验证在微服务架构中也很有用。它可用于实现单点登录功能。一个鲜为人知的属性是将代币委托给子服务的可能性。

在微服务架构中,您可能有一个 api 网关 ,它是本机移动应用程序或 html5 应用程序的单一入口点。网关可以将请求转发到多个微服务并将结果聚合到一个响应中。

来源:http://microservices.io/patterns/apigateway.html

这里的挑战是知道哪个用户登录了后备休息服务。在 kerberos 的情况下,可以将用户凭据委托给这些其余服务。这些微服务可以再次验证凭据。

这在 Java 中如何工作?

由于 java 是企业就绪的,因此 gss-api 从早期(jdk 1.4)开始就支持 kerberos。但是,这个 api 使用起来很尴尬。幸运的是,有一个用于 spring security 的 kerberos 插件 ,但是这个插件没有开箱即用的凭证委托支持。所以我写了一些代码来创建委托服务票:(注意这张票也是可转发的)


 import org.ietf.jgss.*;
import org.springframework.security.core.context.securitycontextholder;
import org.springframework.security.kerberos.authentication.kerberosservicerequesttoken;

import javax.security.auth.subject; import java.security.privilegedexceptionaction;

public static byte[] createservicetoken(string servicename) throws exception { kerberosservicerequesttoken authentication = (kerberosservicerequesttoken) securitycontextholder.getcontext().getauthentication();

subject subject = authentication.getticketvalidation().subject();

return subject.doas(subject, (privilegedexceptionaction<byte[]>) () -> {
    gssmanager manager = gssmanager.getinstance();
    gssname name = manager.createname("http@" + servicename, gssname.nt_hostbased_service);
    gsscontext context = manager.createcontext(name, 
                                null, 
                                authentication.getticketvalidation().getgsscontext().getdelegcred(), 
                                gsscontext.indefinite_lifetime);
    context.requestcreddeleg(true);
    byte[] servicetoken = context.initseccontext(authentication.gettoken(), 0, authentication.gettoken().length);
    context.dispose();
    return servicetoken;
});

}

一些解释:

第 9,10 行从 spring 安全上下文中检索 keberosservicetoken

第 12 行获取当前登录的主题

第 14 行运行 lambda 表达式作为这个主题

第 15 行获取 gssmanager

第 16 行为其余端点创建一个 gssname

第 17-20 行为此 rest 端点创建一个新的 gsscontext

第 21 行请求可转发的 kerberos 令牌,因此新服务票证也是可转发的

第 22 行使用当前的 kerberos 令牌启动安全上下文以获取新的服务票证

第 23 行关闭上下文并

第 24 行返回新票

我的一位同事还创建了 spring security kerberos 插件的扩展,以将用户凭据委托给 ldap 服务器。因此,不再需要使用绑定用户(具有特殊权限)。主要优点是您可以创建任何登录到您系统的用户的审计跟踪。