13

最近、AngularJS と Java EE 6 をいじっています。Jersey で Web サービスを構築し、Glassfish にプロジェクトをデプロイしました。なんらかの認証が必要で、OAuth 実装または JDBCRealm はやり過ぎに思えたので、ユーザーが正常にログインした場合にのみセッションを作成することにしました。

@POST
@Path("/login")
@Produces({MediaType.APPLICATION_JSON})
@Consumes({MediaType.APPLICATION_JSON})
public Response login(LoginDAO loginData, @Context HttpServletRequest req) {
    req.getSession().invalidate();
    loginData.setPassword(PasswordGenerator.hash(loginData.getPassword()));
    User foundUser = database.login(loginData);
    if(foundUser == null) {
        return Response.status(Status.CONFLICT).build();
    }
    req.getSession(true).setAttribute("username", foundUser.getUsername());
    return Response.ok().build();
}

@GET
@Path("/ping")
public Response ping(@Context HttpServletRequest req) {
    if(req.getSession().getAttribute("username") == null) {
        return Response.ok("no session with an username attribute has been set").build();
    }
    return Response.ok(req.getSession(true).getAttribute("username")).build();
}

Postman から /login に投稿するか、glassfish にデプロイされた基本的な jQuery Web ページから投稿すると、正しいユーザー名が返され、セッションが配置されます。/ping に GET リクエストを送信すると、ログインしたユーザー名が返されます。

ログインが必要なnode.js WebサーバーにデプロイされたAngularJSアプリケーションがあります。このサーバーは別のドメインの別のポートにあるため、cors を有効にするという苦労が必要でした。これは、レスポンス ヘッダーを設定するコンテナ レスポンス フィルタを作成することで実現しました。

public class CrossOriginResourceSharingFilter implements ContainerResponseFilter {
    @Override
    public ContainerResponse filter(ContainerRequest creq, ContainerResponse cresp) {
        cresp.getHttpHeaders().putSingle("Access-Control-Allow-Origin", "http://localhost:8000");
        cresp.getHttpHeaders().putSingle("Access-Control-Allow-Credentials", "true");
        cresp.getHttpHeaders().putSingle("Access-Control-Allow-Methods", "GET, POST, DELETE, PUT");
        cresp.getHttpHeaders().putSingle("Access-Control-Allow-Headers", "Content-Type, Accept, X-Requested-With");
        return cresp;
    }
}

これにより、AngularJS から Glassfish にデプロイされた Java EE 6 アプリケーションにさまざまなタイプの HTTP リクエストを送信できるようになりました。

問題は、AngularJS から /login メソッドに POST リクエストを送信すると、セッションが作成され、ユーザー名が返されることです。しかし、GET リクエストを /ping メソッドに送信すると、「ユーザー名属性を持つセッションが設定されていません」という通知が表示されます。

これはクロスドメイン防止に関係していると考えており、xhr リクエストを送信するときに withCredentials タグを設定する必要があります。私はAngularJSでこれをやろうとしていますが、これを行う方法がわかりません.

function LoginCtrl($scope, $http) {
    $scope.login = function() {
        $http.post("glassfish:otherport/api/login", $scope.credentials).
            success(function(data) {
                console.log(data);
            }).
            error(function(data, error) {
                console.log(error);
            });
    };
};

そして別のコントローラーで:

$scope.getUsername = function() {
    $http.get("glassfish:otherport/api/ping", {}).
        success(function(data) {
            $scope.username = data;
        }).
        error(function() {
            $scope.username = "error";
        })
    }

withCredentials を true に設定しようとしました

$http.defaults.withCredentials = true;

しかし、これは私の問題を解決しませんでした。また、構成パラメーターのすべてのリクエストで送信しようとしましたが、これでも問題は解決しませんでした。

4

3 に答える 3

20

使用している AngularJS のバージョンによっては、各 $http で設定する必要がある場合があります。

1.2以降、次のことができます:

$http.get(url,{ withCredentials: true, ...})

1.1.1 から、グローバルに構成できます。

config(['$httpProvider', function($httpProvider) {
  $httpProvider.defaults.withCredentials = true;
}]).

古いバージョンの Angular を使用している場合は、withCredentials を指定する構成オブジェクトを $http に渡してみてください。これは 1.1 より前のバージョンで動作するはずです:

$http({withCredentials: true, ...}).get(...)

mruelans の回答と以下も参照してください。

于 2013-01-01T13:52:43.247 に答える
5

1.2 バージョンでは、これは機能しません。

$http({withCredentials: true, ...}).get(...) 

ドキュメントを読むと、ショートカット メソッドは構成オブジェクトを取得する必要があります

$http.get(url,{ withCredentials: true, ...})

$http はシングルトンです。これが、同じアプリケーションで資格情報の有無にかかわらず要求を混在させる唯一の方法です。

于 2013-11-20T13:48:57.220 に答える