最近、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;
しかし、これは私の問題を解決しませんでした。また、構成パラメーターのすべてのリクエストで送信しようとしましたが、これでも問題は解決しませんでした。