在企业的统一认证场景里,SAML 2.协议算是非常成熟的方案。它的核心角色有两个:IdP(Identity Provider,身份提供者)负责认证用户身份,SP(Service Provider,服务提供者)负责提供业务应用。当用户访问SP时,SP生成一个SAML认证请求重定向到IdP,IdP完成用户认证后签发一个经过签名的断言(Assertion)返回给SP,SP验证签名后放行用户。整个过程中用户只需要登录一次,这就是单点登录的基本原理。本文将以Debian系统为平台,使用Shibboleth Identity Provider搭建一套完整的IdP服务。

一、SAML认证流程与IdP的职责
在动手安装之前,有必要先理解IdP在整个SAML流程中扮演什么角色。用户浏览器访问SP保护的资源时,SP发现用户未认证,会构造一个AuthnRequest请求,通过浏览器的HTTP重定向发送给IdP。IdP收到请求后展示登录页面,验证用户的账号密码或调用其他认证方式,认证通过后生成一条SAML断言,断言里包含用户名、邮箱、所属组等属性信息。
IdP随后用私钥对断言进行数字签名,把断言包装成Response消息,通过浏览器的POST表单回传给SP预先注册的ACS地址(Assertion Consumer Service)。SP拿到Response后,先用IdP的公钥证书验证签名,确认断言没有被篡改,再检查时间窗口和受众限制,全部通过后才认为用户合法。理解这个过程对后面的配置非常重要,因为IdP需要维护三样东西:用于签名的密钥对、描述自身能力的IdP Metadata、以及每个可信SP的元数据信息。
Shibboleth IdP是Java Web应用,以war包形式发布,需要运行在Servlet容器里。在Debian上推荐的组合是OpenJDK加Tomcat,这也是官方文档建议的生产部署方式。
二、在Debian上安装基础环境
首先更新系统并安装OpenJDK。Debian 11/12的仓库里默认提供OpenJDK 17,Shibboleth IdP 4.x完整支持这个版本:
apt update && apt upgrade -y apt install -y openjdk-17-jdk wget unzip java -version # 输出 openjdk version "17.x.x" 说明安装成功
接着安装Tomcat 9。Debian仓库自带的tomcat9包可以直接使用,也可以手动部署二进制版本。这里采用apt安装方式,方便后续用systemd管理:
apt install -y tomcat9 systemctl enable --now tomcat9 # 检查默认8080端口是否已经监听 ss -tlnp | grep 8080
需要特别注意一点:Tomcat默认以tomcat用户运行,home目录是/usr/share/tomcat9。后面安装IdP时要把安装目录的属主设置好,否则IdP启动时会因为读不到密钥文件而报权限错误,这是新手最常见的坑之一。另外Shibboleth IdP对JVM内存有要求,建议编辑/etc/default/tomcat9,把JAVA_OPTS里的堆内存调整到至少1500M,否则大并发登录时容易出现内存溢出。
三、下载并安装Shibboleth IdP
从官方下载地址获取IdP安装包并解压执行安装脚本:
cd /opt wget https://shibboleth.net/downloads/identity-provider/latest4/shibboleth-identity-provider-4.3.1.tar.gz tar xzf shibboleth-identity-provider-4.3.1.tar.gz cd shibboleth-identity-provider-4.3.1 ./bin/install.sh \ -Didp.entityid=https://idp.example.edu/idp/shibboleth \ -Didp.hostname=idp.example.edu \ -Didp.sealing.password=YourSealingSecret
安装脚本会把IdP部署到/opt/shibboleth-idp目录,war包放在/opt/shibboleth-idp/war下。entityid是IdP在SAML圈内的唯一标识,建议直接使用域名形式,后期变更会牵连所有SP的对接配置。执行过程中脚本会提示生成两类密钥:idp-signing用于给断言签名,idp-encryption用于加密断言内容,这两个密钥的密码要妥善保存,后续改配置时需要用到。
war包本身可以直接解压部署,但更推荐的做法是配置Tomcat的context片段,把war路径指向IdP目录。创建/etc/tomcat9/Catalina/localhost/idp.xml,内容如下:
<Context docBase="/opt/shibboleth-idp/war/idp.war"
privileged="true">
<Manager pathname="" />
</Context>写完之后重启Tomcat,访问https://idp.example.edu/idp/status(需要先配好HTTPS),看到状态页输出就说明IdP服务已经跑起来了。IdP强制要求HTTPS,推荐用Let's Encrypt签发免费证书,也可以内部环境用自签证书,只要保证Tomcat的connector配置里启用了443端口并绑定证书即可。
四、配置属性释放与SP对接
IdP安装完成后只是一个空壳,需要告诉它两件事:去哪里认证用户、释放哪些属性给SP。用户认证最简单的方式是LDAP,编辑/opt/shibboleth-idp/conf/ldap.properties,配置LDAP地址、BindDN和密码:
idp.authn.LDAP.authn = %{idp.authn.LDAP.authn:simple}
idp.authn.LDAP.host = ldap://ldap.example.edu:389
idp.authn.LDAP.baseDN = ou=people,dc=example,dc=edu
idp.authn.LDAP.bindDN = cn=idp,ou=service,dc=example,dc=edu
idp.authn.LDAP.bindDNCredential = YourLDAPPassword
idp.authn.LDAP.userFilter = (uid={user})属性释放的策略在conf/attribute-filter.xml里定义。下面是一个典型例子,表示只对实体ID为特定SP释放uid和mail两个属性:
<afp:AttributeFilterPolicy id="releaseToDemoSP">
<afp:PolicyRequirementRule xsi:type="Requester" value="https://sp.example.edu/shibboleth"/>
<afp:AttributeRule attributeID="uid">
<afp:PermitValueRule xsi:type="ANY"/>
</afp:AttributeRule>
<afp:AttributeRule attributeID="mail">
<afp:PermitValueRule xsi:type="ANY"/>
</afp:AttributeRule>
</afp:AttributeFilterPolicy>SP对接部分需要把SP的Metadata加载进来。编辑conf/metadata-providers.xml,最简单的方式是引用本地文件:
<MetadataProvider id="DemoSP"
xsi:type="FilesystemMetadataProvider"
metadataFile="/opt/shibboleth-idp/metadata/sp-metadata.xml"/>所有配置修改完成后,进入/opt/shibboleth-idp/bin目录执行./build.sh重新编译war包,再重启Tomcat生效。最后用官方提供的测试SP,或者自己搭一个Shibboleth SP,访问受保护页面触发跳转,如果能正确显示IdP登录页并在登录后带属性回到SP,整套配置就完成了。
五、常见问题排查
配置过程中最容易遇到三类问题。第一类是属性拿不到,多半是attribute-resolver.xml里的属性定义和LDAP返回字段对不上,可以在conf/logback.xml里把日志级别调成DEBUG,重启后在/opt/shibboleth-idp/logs/idp-process.log中查看属性解析的详细过程。
第二类是SP报签名验证失败,原因通常是SP侧的IdP Metadata过期或与当前证书不匹配。IdP的证书存放在credentials目录下,重新生成证书后必须同步更新对外发布的https://idp.example.edu/idp/shibboleth这个Metadata地址里的内容,并让SP重新拉取。
第三类是时钟不同步导致的断言过期错误。SAML对时间敏感,断言默认有效期为几分钟,如果Debian服务器的时间不准,SP会直接拒绝断言。装上chrony或ntp做时间同步是生产环境的基本要求:apt install -y chrony && systemctl enable --now chrony。把这几个点照顾到,IdP服务基本就能稳定运行了。