u-ryo's blog

various information for coding...

Category: Authentication

Digest Authentication and File Realm on Glassfish

| Comments

客先から「192.168.1.134にdiget認証のrelmsを作成してください」と 相変わらずわけわかんない指令を受けたので、 「何かに使う『digest』認証を任意の『Realm』で設定」 と解釈して取り組みました。 一番簡単なFileRealmでいいっしょ、 これは4848のGUIからRealms辿ってManage Usersボタンからuser足せばいいし、 Digest Authは<auth-method>DIGEST</auth-method>で瞬殺、 とか思ってたら、ハマりました。 index.htmlweb.xmlのみの最小構成でproof application作ったのですが、 どうしても認証できないのです。 server.log見ると、

1
SEC1105: A PasswordCredential was required but not provided.

と言われています。えー!? 何で? 試しにBASIC認証にしてみると、(紆余曲折ありましたが要するに)通ります。 だから、keyfileの書き方が悪いわけでは無いんですね。 勿論色々ググりました。が、なかなか出て来ません類似例。 辛うじて同じような症状があっても、Answerがついてません。 半日悩みました。 GlassfishのRealmって、 JAAS Contextを指定する必要があって、これは.../domains/domain/config/login.confで規定されているんですね。 これを見ると、 fileについてはfileRealmは一つなのに、 jdbcについてはjdbcRealmjdbcDigestRealmってあるぢゃないですか。 をぉ、と思って、source treeを探してみると、 com.sun.enterprise.security.auth.login.DigestLoginModule というのもあるんですね。 これどうやって使うんでしょうね。 使い方とかも例も、 JavaDocに書いてないしググっても出て来ませんでした。 試しにdigestRealmなんてlogin.confに他のを真似して、 上のDigestLoginModuleを指定して作って使ってみたのですが、 fileから読み込むようにはなっていないようで、

1
WEB9102: Web Login Failed: com.sun.enterprise.security.auth.login.common.LoginException: Login failed: unable to instantiate LoginModule: null

と言われて失敗してました。 ...って、これabstract classだから当たり前じゃないですか恥ずかしい。 DigestLoginModuleをextendsしてるのはJDBCDigestLoginModuleだけだから、 file realmで使うならJDBCDigestLoginModuleみたいなのを自前で作らないとならないんじゃないでしょうかね。 でもそうならどっかにそう書いといてよねー。

結局、大人しくjdbcDigestRealmを使うように変更することで面倒を回避しました。 まぁ、それだけ世にDigest Authenticationのdemandがない、 という証左なのかなと思いました。

minimum web.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?xml version="1.0" encoding="UTF-8" ?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
                             http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
         version="3.0">
  <security-constraint>
    <web-resource-collection>
      <web-resource-name>Digest Authentication Test</web-resource-name>
      <url-pattern>/*</url-pattern>
    </web-resource-collection>
    <auth-constraint>
      <role-name>someRole</role-name>
    </auth-constraint>
  </security-constraint>
  <login-config>
    <auth-method>DIGEST</auth-method>
    <realm-name>someCreatedRealmUsingjdbcDigestRealmOnJAASContext</realm-name>
  </login-config>
  <security-role>
    <role-name>someRole</role-name>
  </security-role>
</web-app>

WEB-INF/glassfish-web.xml

glassfishの場合は、以下のようにrole-namegroup-nameを結びつけるglassfish-web.xmlもないとダメでした。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE glassfish-web-app PUBLIC "-//GlassFish.org//DTD GlassFish Application Server 3.1 Servlet 3.0//EN" 
"http://glassfish.org/dtds/glassfish-web-app_3_0-1.dtd">
<glassfish-web-app error-url="">
  <security-role-mapping>
    <role-name>user</role-name>
    <group-name>user</group-name>
  </security-role-mapping>
  <class-loader delegate="true"/>
  <jsp-config>
    <property name="keepgenerated" value="true">
      <description>.</description>
    </property>
  </jsp-config>
</glassfish-web-app>

AuthType None

| Comments

さっき同僚に聞かれて調べました。 apacheにおけるBasic認証/Form認証等を 子ディレクトリにおいては無効にしたい場合、 .htaccessに、

1
Satisfy Any

と書けば良い、という説が諸所にあったのですが、 ちゃんとキャンセルするには、

1
2
AuthType None
Require all granted

とすべき、みたいです。 「AuthType None」だけだと、 「No authentication done but request not allowed without authentication for /~u-ryo/test/test/. Authentication not configured?」と言われて500 Internal Server Errorになってしまいます。

親ディレクトリではIP制限とBasic認証を同時にかけて、 子ディレクトリではIP制限だけ、 且つBasic認証のポップアップは出ないように (IP制限で弾かれれば即403)、 という要件だったので、

1
2
3
4
5
6
AuthType Basic
AuthName test
AuthUserFile password.txt
require valid-user
Allow from 127.0.0.1
Satisfy Any

1
2
3
4
5
6
AuthType None
Require all granted
Order deny,allow
Allow from 127.0.0.1
Deny from all
Satisfy All

といった感じで解決しました。