環境:
- ジャワ
- グラスフィッシュ
- 別のマシンの REST サービス
- AJAX と JQuery を使用した HTML5 クライアント
- ジャージー
これは私がこれまでに実装したものです:
HTML5 クライアント
$('#btnSignIn').click(function () {
var username = $("#username").val();
var password = $("#password").val();
function make_base_auth(user, password) {
var tok = user + ':' + password;
var final = "Basic " + $.base64.encode(tok);
console.log("FINAL---->" + final);
alert("FINAL---->" + final);
return final;
}
$.ajax({
type: "GET",
contentType: "application/json",
url: "http://localhost:8080/SesameService/webresources/users/secured/login",
crossDomain: true,
dataType: "text",
async: false,
data: {},
beforeSend: function (xhr) {
xhr.setRequestHeader('authorization', make_base_auth(username, password));
},
success: function () {
alert('Thanks for your signin in! ');
},
error: function (jqXHR, textStatus, errorThrown) {
console.log(textStatus, errorThrown);
alert(' Error in signIn-process!! ' + textStatus);
}
});
});
サーバ
セキュリティでは、セキュリティ マネージャーを有効にしていません。無効になっています。
Glassfish に BASIC 認証を設定しました。私の web.xml は次のようになります。
<servlet-mapping>
<servlet-name>ServletAdaptor</servlet-name>
<url-pattern>/webresources/*</url-pattern>
</servlet-mapping>
<security-constraint>
<web-resource-collection>
<web-resource-name>REST Protected resources</web-resource-name>
<description/>
<url-pattern>/users/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>admin</role-name>
<role-name>customer</role-name>
<role-name>user</role-name>
</auth-constraint>
</security-constraint>
<login-config>
<auth-method>BASIC</auth-method>
<realm-name>jdbcRealm</realm-name>
</login-config>
<security-role>
<role-name>admin</role-name>
</security-role>
<security-role>
<role-name>user</role-name>
</security-role>
<security-role>
<description/>
<role-name>customer</role-name>
</security-role>
グラスフィッシュ
ログ
FINE: [Web-Security] Setting Policy Context ID: old = null ctxID = SesameService/SesameService
FINE: [Web-Security] hasUserDataPermission perm: ("javax.security.jacc.WebUserDataPermission" "/webresources/users/secured/login" "GET")
FINE: [Web-Security] hasUserDataPermission isGranted: true
FINE: [Web-Security] Policy Context ID was: SesameService/SesameService
FINE: [Web-Security] hasResource isGranted: true
FINE: [Web-Security] hasResource perm: ("javax.security.jacc.WebResourcePermission" "/webresources/users/secured/login" "GET")
質問:
ユーザーがサインアップするときにクライアントでパスワードを暗号化 (エンコードしない) し、SSL/HTTPS で転送する場合、これは安全で実装に適した方法ですか?
クライアントなしで REST サービスを使用すると、常に開いているのはなぜですか? BASIC認証なし?これらの URL パターンに何か問題があることを理解しましたか?
http://localhost:8080/SesameService/webresources/users/secured/login
これが機能する場合、それをテストする方法は、一度認証すると常に承認されるためです。RESTサービス内でプログラムで「ログアウト」することは可能ですか、または一般的にログアウトを実装する方法はありますか?
必須のbase64でエンコードされたユーザー名:パスワードを含むヘッダーで承認を使用する場合、ユーザー名とパスワードもDBにエンコードする必要がありますか? 私はそれを試して、Glassfish の jdbcRealm に Encoding (許可されている値は Hex と Base64) を追加しました。パスワードで十分なようですが、両方がクライアントでエンコードされているとどうなりますか?
更新: web.xml を変更したところ、ブラウザーで REST サービスを直接呼び出すと、BASIC 認証が機能するようになりました。http://localhost:8080/SesameService/users/secured/login
変更点:
- Glassfish でセキュリティ マネージャを有効にしました
- URLパターンを変更しました
<servlet-mapping>
<servlet-name>ServletAdaptor</servlet-name>
<url-pattern>/*</url-pattern>----> I took webresources off. It was generated by Netbeans
</servlet-mapping>
- サービスの URL を次のように変更しました。
http://localhost:8080/SesameService/users/secured/login
HTML5 クライアントから認証しようとすると、HTTP/1.1 401 Unauthorized が返されます。
リクエスト ヘッダー:
Origin: http://localhost:8383
Host:localhost:8080
Connection:keep-alive
Access-Control-Request-Method:GET
Access-Control-Request-Headers:authorization,content-type
応答:
x-powered-by:Servlet/3.0 JSP/2.2 (GlassFish Server Open Source Edition 3.1.2.2 Java/Oracle Corporation/1.7)
WWW-Authenticate:Basic realm="jdbcRealm"
Server:GlassFish Server Open Source Edition 3.1.2.2
Pragma:No-cache
Expires:Thu, 01 Jan 1970 02:00:00 EET
Date:Sat, 13 Apr 2013 15:25:06 GMT
Content-Type:text/html
Content-Length:1073
Cache-Control:no-cache
更新 2
JavaScript + Authorization-header で認証しようとすると、401 エラーが発生し、ログに次のように記録されます。
FINE: [Web-Security] Setting Policy Context ID: old = null ctxID = SesameService/SesameService
FINE: [Web-Security] hasUserDataPermission perm: ("javax.security.jacc.WebUserDataPermission" "/users/secured/login" "OPTIONS")
FINE: [Web-Security] hasUserDataPermission isGranted: true---->!!!!!!!!!!!!!
FINE: [Web-Security] Policy Context ID was: SesameService/SesameService
FINE: [Web-Security] Codesource with Web URL: file:/SesameService/SesameService
FINE: [Web-Security] Checking Web Permission with Principals : null------->!!!!!!!
FINE: [Web-Security] Web Permission = ("javax.security.jacc.WebResourcePermission" "/users/secured/login" "OPTIONS")
FINEST: JACC Policy Provider: PolicyWrapper.implies, context (SesameService/SesameService)- result was(false) permission (("javax.security.jacc.WebResourcePermission" "/users/secured/login" "OPTIONS"))
FINE: [Web-Security] hasResource isGranted: false------->!!!!!!!!!
FINE: [Web-Security] hasResource perm: ("javax.security.jacc.WebResourcePermission" "/users/secured/login" "OPTIONS")
FINEST: JACC Policy Provider: PolicyWrapper.getPermissions(cs), context (null) codesource ((null <no signer certificates>)) permissions: java.security.Permissions@5d4de3b0 (
更新 3 クロスドメインのケースで BASIC を使用して認証しようとしているのは、私だけではありません。クロス オリジン フィルターを次のように変更しました。
response.getHttpHeaders().putSingle("Access-Control-Allow-Headers", "Authorization");
401 エラーはなくなりましたが、JavaScript ではまだエラーです。IN Glassfish ログ:
FINEST: JACC Policy Provider:
getPolicy (SesameService/SesameService) is NOT in service----->!!!!!!!!
FINE: JACC Policy Provider: file arrival check type: granted arrived: false exists: false lastModified: 0 storedTime: 1365968416000 state: deleted SesameService/SesameService
FINE: JACC Policy Provider: file arrival check type: excluded arrived: false exists: false lastModified: 0 storedTime: 0 state: deleted SesameService/SesameService
FINE: TM: getTransaction: tx=null, tm=null
FINE: TM: componentDestroyedorg.apache.catalina.servlets.DefaultServlet@227fe9a8
FINE: TM: resourceTable before: 0
FINE: TM: resourceTable after: 0
ところで、私はこの作業をしたことがないので、独自のドメインで REST サービスを直接呼び出すのと同じ方法でこの作業を行います。最初にクライアント要求、サーバー要求、およびユーザー名とパスワードのウィンドウが開き、次にクライアント要求とサーバーがページを認証して応答しますか? 私はそれを取得しようとしています: Authorization ヘッダーを含むリクエスト、残りのサービスからの結果を含むサーバーからの応答、それだけです。RESTサービスを保護する方法はありますか? それより簡単ですか?不可能だよ。
更新 4
HTML5クライアントをJava Webプロジェクトの下、純粋なhtmlページだけで同じドメインの下に移動しようとしましたが、BASIC認証は100%機能しています。その理由は、クロスドメイン環境のためです。