JBoss での kerberos 認証にspnego ( http://spnego.sourceforge.net ) を使用しています。
PAC データを含む認証データにアクセスするには、Kerberos チケットを復号化する必要があります。ユーザーに付与するロールを決定するには、PAC データが必要です。
kerberos チケットにアクセスして解読する方法は? ネットで例を検索しましたが、努力はしませんでした。
JBoss での kerberos 認証にspnego ( http://spnego.sourceforge.net ) を使用しています。
PAC データを含む認証データにアクセスするには、Kerberos チケットを復号化する必要があります。ユーザーに付与するロールを決定するには、PAC データが必要です。
kerberos チケットにアクセスして解読する方法は? ネットで例を検索しましたが、努力はしませんでした。
これらの人は、完全な PAC デコードの実装を持っています。
http://jaaslounge.sourceforge.net/
次のようにトークン パーサーを使用できます。
HttpServletRequest request = (HttpServletRequest) req;
String header = request.getHeader("Authorization");
byte[] base64Token = header.substring(10).getBytes("UTF-8");
byte[] spnegoHeader = Base64.decode(base64Token);
SpnegoInitToken spnegoToken = new SpnegoInitToken(spnegoHeader);
基になる Kerberos チケットを解読したい場合は、いくつかのフープをジャンプする必要があります。それが必要かどうかわかりません。
許す
http://spnego.sourceforge.netのサーブレット フィルターをhttp://jaaslounge.sourceforge.net/の PAC パーサーと組み合わせて使用することに成功しました。DER/ASN.1 パーサーで明示的に何かを行う必要はありません。
/**
* Retrieve LogonInfo (for example, Group SID) from the PAC Authorization Data
* from a Kerberos Ticket that was issued by Active Directory.
*/
byte[] kerberosTokenData = gssapiData;
try {
SpnegoToken token = SpnegoToken.parse(gssapiData);
kerberosTokenData = token.getMechanismToken();
} catch (DecodingException dex) {
// Chromium bug: sends a Kerberos response instead of an spnego response
// with a Kerberos mechanism
} catch (Exception ex) {
log.error("", ex);
}
try {
Object[] keyObjs = IteratorUtils.toArray(loginContext.getSubject()
.getPrivateCredentials(KerberosKey.class).iterator());
KerberosKey[] keys = new KerberosKey[keyObjs.length];
System.arraycopy(keyObjs, 0, keys, 0, keyObjs.length);
KerberosToken token = new KerberosToken(kerberosTokenData, keys);
log.info("Authorizations: ");
for (KerberosAuthData authData : token.getTicket().getEncData()
.getUserAuthorizations()) {
if (authData instanceof KerberosPacAuthData) {
PacSid[] groupSIDs = ((KerberosPacAuthData) authData)
.getPac().getLogonInfo().getGroupSids();
log.info("GroupSids: " + Arrays.toString(groupSIDs));
response.getWriter().println("Found group SIDs: " +
Arrays.toString(groupSIDs));
} else {
log.info("AuthData without PAC: " + authData.toString());
}
}
} catch (Exception ex) {
log.error("", ex);
}
また、新しい HttpFilter (spnego.sf.net からフォーク) を作成しました: spnego-pac は、getUserPrincipal() を介して LogonInfo を公開します。
上記のコードを完全に示すサンプル プロジェクトは、次の場所にあります。
https://github.com/EleotleCram/jetty-spnego-demo
spnego-pac フィルター (上記の例で使用) は次の場所にあります。
https://github.com/EleotleCram/spnego.sf.net-fork
これが誰にとっても役立つことを願っています。
__
マルセル
次のようなメカニズムトークンを取得する場合spnegoToken
:
byte[] mechanismToken = spnegoToken.getMechanismToken();
メカニズムトークンは通常KerberosApRequest
です。KerberosToken
をとるコンストラクターがありますKerberosApRequest
。mechanismToken
キーと一緒にバイト配列を渡すだけで、コンテンツを復号化できます。
私は問題に対する独自の解決策を提供します:
BouncyCastle ライブラリ (トークンの一部を解析するため) と JaasLounge (トークンの暗号化された部分を解読するため) に基づいてソリューションを作成しました。残念ながら、JaasLounge から spnego トークン全体をデコードするコードは、私の要件では失敗しました。私はそれを自分で書かなければなりませんでした。
最初に byte[] 配列から DERObjects を構築して、チケットを部分的にデコードしました。
private DERObject[] readDERObjects(byte[] bytes) throws IOException {
ASN1InputStream stream = new ASN1InputStream(new ByteArrayInputStream(
bytes));
List<DERObject> objects = new ArrayList<DERObject>();
DERObject curObj;
while ((curObj = stream.readObject()) != null) {
objects.add(untag(curObj));
}
return objects.toArray(new DERObject[0]);
}
untag() は私のヘルパー関数で、DERTaggedObject のラッピングを削除します
private DERObject untag(DERObject src) {
if (src instanceof DERTaggedObject) {
return ((DERTaggedObject) src).getObject();
}
return src;
}
特定の DERObject から DERObject のシーケンスを抽出するために、別のヘルパー関数を作成しました。
private DERObject[] readDERObjects(DERObject container) throws IOException {
// do operation varying from the type of container
if (container instanceof DERSequence) {
// decode using enumerator
List<DERObject> objects = new ArrayList<DERObject>();
DERSequence seq = (DERSequence) container;
Enumeration enumer = seq.getObjects();
while (enumer.hasMoreElements()) {
DERObject curObj = (DERObject) enumer.nextElement();
objects.add(untag(curObj));
}
return objects.toArray(new DERObject[0]);
}
if (container instanceof DERApplicationSpecific) {
DERApplicationSpecific aps = (DERApplicationSpecific) container;
byte[] bytes = aps.getContents();
return readDERObjects(bytes);
}
if (container instanceof DEROctetString) {
DEROctetString octets = (DEROctetString) container;
byte[] bytes = octets.getOctets();
return readDERObjects(bytes);
}
throw new IllegalArgumentException("Unable to decode sequence from "+container);
}
最後に、暗号化された部分を含む DEROCtetStream を取得したら、KerberosEncData を使用しました。
KerberosEncData encData = new KerberosEncData(decrypted, matchingKey);
クライアント ブラウザから受信したバイト シーケンスは、チケット ルート - レベル 0 である単一の DERApplicationSpecific に解析されます
。ルートには以下が含まれます。
レベル 1 には以下が含まれます。
レベル 2 には以下が含まれます。
0x01 0x00
、ブール値として解析 (false)
レベル 3 には以下が含まれます。
チケット部分 - レベル 4 には以下が含まれます。
暗号化された部分シーケンス (レベル 5) には以下が含まれます。
問題は、シーケンス 0x01 0x00 が見つかったときに ArrayIndexOutOfBoundException をスローする DERBoolean コンストラクターにありました。そのコンストラクターを変更する必要がありました:
public DERBoolean(
byte[] value)
{
// 2011-01-24 llech make it byte[0] proof, sequence 01 00 is KRB5_AP_REQ
if (value.length == 0)
this.value = 0;
else
this.value = value[0];
}
spnego を使用してからしばらく経ちます (ほぼ 1 年) ... とてもクールな質問ですね。
私は少し掘り下げて、MS-ADで動作していたが、今日はそれを感じていない、しばらく前に持っていたコードを実行しようとしていました:-/
うまくいけば、それはあなたにいくつかの洞察を与えることができます.