web-dev-qa-db-ja.com

ジャージのセキュリティとセッション管理

ジャージーでプログラムでセッション管理またはセキュリティを取得する方法はありますか? Webアプリケーションセッション管理?または、トランザクション、セッション、およびセキュリティはすべて、Jerseyアプリケーションがデプロイされているコンテナによって処理されますか?

42
Adhir

セッション管理は、ジャージーがデプロイされているコンテナーの範囲です。ほとんどの本番環境では、セッション管理を実行するコンテナ内に展開されます。

以下のコードは、セッションオブジェクトを取得し、セッションに値を保存し、後続の呼び出しで値を取得するジャージリソースの簡単な例です。

@Path("/helloworld")
public class HelloWorld {

    @GET
    @Produces("text/plain")
    public String hello(@Context HttpServletRequest req) {

        HttpSession session= req.getSession(true);
        Object foo = session.getAttribute("foo");
        if (foo!=null) {
            System.out.println(foo.toString());
        } else {
            foo = "bar";
            session.setAttribute("foo", "bar");
        }
        return foo.toString();


    }
}
70
Jack Cox

セッションはnever RESTfulアプリケーションで使用するべきものだと思いました...

イゴールは正しい。サーバー側laの従来のWebアプリケーションで状態を維持しないでください。分離されたSOA指向のアプリケーションを構築する場合、REST WebサービスにAPI /フレームワークを使用する必要はありません。グローバルクライアントサーバーを維持する必要がある場合、または必要な場合サーバー側の状態では、SOA指向の[web]アプリと表現できるものを暗黙的に構築していますが、ジャージーを[web]のような開発フレームワークのように使用しています。誤って、Webサービスの性質(RESTまたは)。can最初の回答で提案された方法でそれを行いますが、must n't。最終結果はWebサービスではなく、単なる通常のアプリですWebサービスのツールで構築されています。

-_o

22
MAM

はい、可能です。 Jersey ドキュメント のコメント:

リクエストのセキュリティ情報は、@ Contextアノテーションを使用してJAX-RS SecurityContextインスタンスを注入することで利用できます。挿入されたセキュリティコンテキストインスタンスは、HttpServletRequest APIで使用可能な機能と同等の機能を提供します。挿入されるセキュリティコンテキストは、実際のJerseyアプリケーションの展開に依存します。たとえば、サーブレットコンテナにデプロイされたJerseyアプリケーションの場合、Jersey SecurityContextは、サーブレットリクエストから取得したセキュリティコンテキストからの情報をカプセル化します。 GrizzlyサーバーにデプロイされたJerseyアプリケーションの場合、SecurityContextはGrizzlyリクエストから取得した情報を返します。

例:

@Path("basket")
public ShoppingBasketResource get(@Context SecurityContext sc) {
    if (sc.isUserInRole("PreferredCustomer") {
        return new PreferredCustomerShoppingBasketResource();
    } else {
        return new ShoppingBasketResource();
    }
}

または

@Path("resource")
@Singleton
public static class MyResource {
    // Jersey will inject proxy of Security Context
    @Context
    SecurityContext securityContext;

    @GET
    public String getUserPrincipal() {
        return securityContext.getUserPrincipal().getName();
    }
}

または、注釈付きですぐに使用できるセキュリティが必要な場合は、 これらのドキュメント を確認してください。

Jerseyでは、SecurityContextをカスタマイズすることもできます。

SecurityContextは、getSecurityContext()メソッドを介してContainerRequestContextから直接取得できます。 setSecurityContext(SecurityContext)メソッドを使用して、リクエストコンテキストのデフォルトのSecurityContextをカスタムコンテキストに置き換えることもできます。 ContainerRequestFilterでカスタムSecurityContextインスタンスを設定すると、このセキュリティコンテキストインスタンスはJAX-RSリソースクラスフィールドへの注入に使用されます。この方法で、使用する独自のSecurityContextをセットアップするカスタム認証フィルターを実装できます。カスタム認証要求フィルターを確実に早期に実行するには、優先順位の定数を使用してフィルターの優先順位をAUTHENTICATIONに設定します。認証フィルターを早期に実行すると、他のすべてのフィルター、リソース、リソースメソッド、およびサブリソースロケーターがカスタムSecurityContextインスタンスで確実に実行されます。

Jerseyで要求フィルターを使用する方法の例 を参照してください。そして、私の次の例を確認してください:

import javax.annotation.Priority;
import javax.ws.rs.Priorities;

@Provider
@Priority(Priorities.AUTHENTICATION)
public class AuthRequestFilter implements ContainerRequestFilter {
    @Context
    HttpServletRequest webRequest;

    @Override
    public void filter(ContainerRequestContext requestContext) throws IOException {
        final HttpSession session = webRequest.getSession();

        requestContext.setSecurityContext(new SecurityContext() {
            @Override
            public Principal getUserPrincipal() {
                return new PrincipalImpl((String)session.getAttribute("USER_NAME"));
            }

            @Override
            public boolean isUserInRole(String s) {
                return false;
            }

            @Override
            public boolean isSecure() {
                return false;
            }

            @Override
            public String getAuthenticationScheme() {
                return null;
            }
        });
    }
}

警告! これはJersey 2.4で導入されました 。 Glassfish 4.0.0は古いJersey 2.0を使用するため、 これらのヒントを使用してJerseyをアップグレードする (うまく機能することが証明されていません)が必要です。または、より良い方法は Glassfish 4.0.1のナイトリービルド をダウンロードすることです。しかし、現時点では完全に安定しているわけではありません。新しいバージョンがまもなくリリースされることを願っています。

UPDATE:現時点(2014-02-14)Glassfish 4.0.1ナイトリービルドはJersey 2.5.1を使用しており、コンテキストインジェクションはうまく機能します。

セッションに関するジャックの応答は正しいです。これらは実行するコンテナに固有のものですが、サーブレット仕様では少なくともJavaEEコンテナ間の移植性が提供されます。

セキュリティに関しては、少なくともJaaS(Java Authentication and Authorization Service)と servlet filter を使用して、JAX-RS固有のコードから分離する機会があります。このフィルターを使用してHTTP認証を実施し、認証に成功すると、適切なプリンシパルでJaaSサブジェクトをセットアップできます。 JAX-RSリソースは、サブジェクトの適切なプリンシパルを確認できます。スタック全体を制御するため、リソース内の認証されたユーザーに依存することができます(ただし、これをテストしてください!)。また、リソースコードの現在の操作に基づいて承認を適用できます。

6
StevenC

クライアントにAuthorizationヘッダーを追加して、REST=メソッドで次のようにテストすることで、この問題を解決しました。

@GET
@PRODUCES(MediaType.APPLICATION_JSON)
public String returnClients(@Context HTTPServletRequest request(
    String auth = request.getHeader("Authorization");
    Account acc = null;
    if (auth!=null) {
       Account acc = Utils.LoginAccount(auth);
    }
    if (acc == null)
     // not logged in, handle it gracefully

この方法では、セッションを開始せずに認証が行われます。

4
Ron

Jerseyのセキュリティについては、jersey OAuth support。OAuthシステムのAPIを外部ユーザーに公開する場合に完全に適合します。 api

http://wikis.Oracle.com/display/Jersey/OAuth

3
abovesun

@pathを使用して、単一の名前空間でサービスをグループ化できます。例.

@Path("/helloworld")
public class HelloWorld {

    @GET
    @Produces("text/plain")
    public String hello() {


        return "";


    }
}
Instead of @Path("/helloworld") use
@Path("admin/helloworld") to expose you class as rest and bind filter on "admin/"
in web.xml as below.

<servlet>
            <servlet-name>jersey-serlvet</servlet-name>
            <servlet-class>com.Sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
            <init-param>
                <param-name>com.Sun.jersey.config.property.packages</param-name>
                <param-value>/</param-value>
            </init-param>
            <load-on-startup>1</load-on-startup>
        </servlet>
        <servlet-mapping>
            <servlet-name>jersey-serlvet</servlet-name>
            <url-pattern>/rest/*</url-pattern>
        </servlet-mapping>
         <filter>
            <filter-name>myfilter</filter-name>
            <filter-class>com.Filterclass</filter-class>
        </filter>
        <filter-mapping>
            <filter-name>myfilter</filter-name>
            <url-pattern>/rest/admin/*</url-pattern>
        </filter-mapping> 

    public class Filterclass implements Filter {
       public void doFilter(ServletRequest request, ServletResponse response,
                FilterChain chain)
                throws IOException, ServletException {
                  try{
                       chain.doFilter(request, response);
                    }catch(Exception e){
                   e.printStackTrace();
                       }
          }
    }

このフィルタークラスでセッションを検証できます。

2
ThmHarsh